/******************************************************************* * * DESCRIPTION: class TransportDelayCell * * AUTHOR: Amir Barylko & Jorge Beyoglonian * Version 2: Daniel Rodriguez. * Version 3: Gabriel Wainer * Version 4: 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: 03/07/1999 (v2) * DATE: 06/02/2000 * DATE: 11/01/2006 (v4) * * Suggested changes: * 21/04/2001 - Alejandro Troccoli. * In the output queue, save the output time instead of the delay. * This saves processing time because it is no longer necessary to update the remaining time * every time a new internal transition occurs. * *******************************************************************/ // ** include files **// #include "tdcell.h" // header class #include "message.h" // class InternalMessage #include "coupcell.h" // CoupledCell #include "realfunc.h" // calculateWithQuantum #include "strutil.h" #include "JackyDebugStream.h" //jacky-debug-mode /******************************************************************* * TRANSPORT DELAY CELL STATE *******************************************************************/ /****************************************************************** * Method: operator= ******************************************************************/ TDCellState &TDCellState::operator=(TDCellState& thisState) { (AtomicCellState &)*this = (AtomicCellState &)thisState; queueVal = thisState.queueVal; #ifdef JACKY_SYNC //================================================================ transientVal = thisState.transientVal; #ifdef JACKY_PORTIN_FIRST // [2006-01-06] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recordTime = thisState.recordTime; #endif //end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #ifdef JACKY_STATE_VAR // [2006-01-10] ////////////////////////////////////// //copy the saved values of state variables at the beginning of Round 0 vars_round0 = thisState.vars_round0; #endif //end JACKY_STATE_VAR //////////////////////////////////////////////// #endif //end JACKY_SYNC ============================================================ return *this; } /************************************************************************ * Method: copyState ************************************************************************/ #ifndef JACKY_REVISION //original version ================== void TDCellState::copyState(TDCellState *thisState) { *this = *(TDCellState *) thisState; } #else //This is Jacky's revision 10-17-2005 ================ void TDCellState::copyState(BasicState *rhs){ *this = *((TDCellState *) rhs); } #endif //=================================================== /*************************************** * Method: getSize() ***************************************/ int TDCellState::getSize() const { return sizeof(TDCellState); } /************************************************************************ * TRANSPORT DELAY CELL ************************************************************************/ /******************************************************************* * Method: TransportDelayCell ********************************************************************/ TransportDelayCell::TransportDelayCell( const CellPosition& cellPos, const string &name, const LocalTransAdmin::Function &fn ) : AtomicCell( cellPos, name, fn ) { } /******************************************************************* * Method: initializeCell ********************************************************************/ void TransportDelayCell::initializeCell() { AtomicCell::initializeCell(); //This function requires the cell state to be already created. if ( UseQuantum().Active() ) QuantumValue( Real(UseQuantum().Value()) ); } /******************************************************************* * Method: initFunction * Description: ********************************************************************/ Model &TransportDelayCell::initFunction() { PortList::iterator cursor; //To start the simulation, hold in for 0 time and queue the present value in the output queue list. //This will cause all models to evaluate their local transition function at time zero. for (cursor = outNCPortList().begin(); cursor != outNCPortList().end(); cursor++) { string out_port(cursor->second->name()); string in_port(calculateInPort(out_port)); #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^^^^^^ Previous Version ^^^^^^^^^^^^ TDCellState::QueueValue QV(out_port, value(in_port)); #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^^^^^^^^^^^^^^ TDCellState::QueueValue QV(out_port, value(in_port)); //create a QueueValueWithFlag, pair< QueueValue, boolFlag > //the default value for the boolFlag is FALSE TDCellState::QueueValueWithFlag QVF(QV, false); //element of TransientQueue #ifdef JACKY_TDCELL // [2006-01-11] ``````````````````````````````````````````` //create a QueueValueWithScheduleTime, pair< QueueValue, VTime > //the scheduleTime is set to Zero TDCellState::QueueValueWithScheduleTime QVST(QV, VTime::Zero); #endif // end JACKY_TDCELL ```````````````````````````````````````````````````` #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "\t------------> TDCell::initFunction() -> push element on the Queue" << endl << flush; #else //````````````````````````````````````````````````````````````````````````` << " / ST = " << (VTime::Zero).asString() << "> on the Queue" << endl << flush; #endif // end JACKY_TDCELL `````````````````````````````````````````````````````` jacky_os << "\t------------> TDCell::initFunction() -> push element <" << out_port << " = " << value(in_port) << " / flag = FALSE> on the TransientQueue!" << endl << flush; #endif #ifdef JACKY_SYNC #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^^^^^^ Previous Version ^^^^^^^^^^^^^^ //initialize the transient values to the initial value on the //neighborChange & in_XXX ports of the cell transientVal().push_back( QV ); #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^ //push the QueueValueWithFlag, pair , //onto the transient queue transientVal().push_back( QVF ); #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #endif //end JACKY_SYNC #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^^^^^^ Previous Version ^^^^^^^^^^^^^^^ queueVal().push_back( TDCellState::QueueElement( VTime::Zero, QV ) ); #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #ifndef JACKY_TDCELL //[2006-01-11] `````````````````````````````````````````````````` queueVal().push_back( TDCellState::QueueElement( VTime::Zero, QVF ) ); #else // [2006-01-11] ```````````````````````````````````````````````````````````````` //push the QVST on to the Queue queueVal().push_back( TDCellState::QueueElement( VTime::Zero, QVST ) ); #endif //end JACKY_TDCELL ```````````````````````````````````````````````````````````` #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } #ifdef JACKY_PORTIN_FIRST // [2006-01-06] ^^^^^^^^^^^ //initialize the RT to Zero setRecordTime( VTime::Zero ); #endif // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #ifdef JACKY_STATE_VAR // [2006-01-10] ////////////////////////////////////////////// //save the StateVars (variables) in AtomicCellState to the StateVars (vars_round0) in TDCellState recordStateVariables() = cellStateVariables(); #ifdef JACKY_DEBUG jacky_os << "\t[2006-01-10] StateVariables in AtomicCellState = " << cellStateVariables().asString() << endl << flush; jacky_os << "\t[2006-01-10] Recorded StateVariables in TDCellState = " << recordStateVariables().asString() << endl << flush; #endif #endif //end JACKY_STATE_VAR ///////////////////////////////////////////////////////// holdIn(AtomicState::active, VTime::Zero); #ifdef JACKY_DEBUG //this is the number to record the number of the Round in the multiple-round message passing roundNum = 0; #endif //end JACKY_DEBUG return *this; } /******************************************************************* * Method: externalFunction ********************************************************************/ #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^^^^^^ Previous Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Model &TransportDelayCell::externalFunction( const MessageBag &msgs ) { //Note: [2006-01-13] // the definition of this function when the JACKY_PORTIN_FIRST macro is not defined has been removed!!! //the old version of this definition can be found in ars_files, alpha_files, and hpc_files MASSERTMSG( false, "TDCell::externalFunction() -> macro JACKY_PORTIN_FIRST is NOT defined!" ); return *this ; } #else // Nov. 29, 2005 ^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Model &TransportDelayCell::externalFunction( const MessageBag &msgs ) { //Jacky: this function is to set the received Y message to the input port on this cell // Must be called at the very beginning of this function to ensure that the P value is updated!!! localTransitionConfluent( msgs ); #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "\t------------->TDCell::externalFunction() called() " << endl << flush; jacky_os << "[~~PORT~~] inputPort() [in] -> " << flush; if( inputPort().size() == 0 ){ jacky_os << "NO InputPort -----" << endl << flush; } else { PortList::const_iterator inputPortCursor = inputPort().begin(); for( ; inputPortCursor != inputPort().end(); inputPortCursor++ ){ jacky_os << inputPortCursor->second->name() << " " << flush; } jacky_os << endl << flush; } jacky_os << "[~~PORT~~] outPortList() [output] -> " << flush; if( outPortList().size() == 0 ){ jacky_os << "NO OutputPort -----" << endl << flush; } else { PortList::const_iterator outPortCursor = outPortList().begin(); for( ; outPortCursor != outPortList().end(); outPortCursor++ ){ jacky_os << outPortCursor->second->name() << " " << flush; } jacky_os << endl << flush; } jacky_os << "[~~PORT~~] inNCPortList() [Xports] -> " << flush; if( inNCPortList().size() == 0 ){ jacky_os << "NO Xport -----" << endl << flush; } else { PortList::const_iterator inNCPortCursor = inNCPortList().begin(); for( ; inNCPortCursor != inNCPortList().end(); inNCPortCursor++ ){ jacky_os << inNCPortCursor->second->name() << " " << flush; } jacky_os << endl << flush; } jacky_os << "[~~PORT~~] outNCPortList() [Yports] -> " << flush; if( outNCPortList().size() == 0 ){ jacky_os << "NO Yport -----" << endl << flush; } else { PortList::const_iterator outNCPortCursor = outNCPortList().begin(); for( ; outNCPortCursor != outNCPortList().end(); outNCPortCursor++ ){ jacky_os << outNCPortCursor->second->name() << " " << flush; } jacky_os << endl << flush; } jacky_os << "[~~PORT~~] NCPortNames() [NCPortNames] -> " << flush; if( NCPorts().size() == 0 ){ jacky_os << "NO NCPortNames -----" << endl << flush; } else { list::const_iterator ncPortNameCursor = NCPorts().begin(); for( ; ncPortNameCursor != NCPorts().end(); ncPortNameCursor++ ){ jacky_os << (*ncPortNameCursor) << " " << flush; } jacky_os << endl << flush; } #endif #ifdef JACKY_TDCELL // [2006-01-11] ````````````````````````````````````````````````````````````` //flag to record a time change bool timeChanged; #endif // end JACKY_TDCELL `````````````````````````````````````````````````````````````````````` //let's check whether there is a time change (usually time advance, but time //can go back in case of a rollback) if( getRecordTime() != msgs.time() ){ //there is a time change #ifdef JACKY_DEBUG jacky_os << "\t\t!!!!! TDCell::externalFunction() Time Change !!!!!" << endl << flush; jacky_os << "\t\t Before Update: RT = " << getRecordTime().asString() << endl << flush; #endif //update the RT setRecordTime( msgs.time() ); // [2006-01-13] // This seems not necessary since we will reset all values on the transient queue // to the previous values anyway ! //reset the flags in TransientValue to FALSE for the new time resetTransientFlags( transientVal() ); #ifdef JACKY_TDCELL // [2006-01-11] ````````````````````````````````````````````````````````````` //set the "time change" flag to true timeChanged = true; // [2006-01-13] // Now, the simulated time has changed, this time change could happen in one the // following two scenarios: // 1. If this cell is imminent, the time change is triggered by an @ message from // the NC. In this case, the outputFunction and internalFunction have been called // before this function. // -> a> // if this cell's neighborhood is defined to include (0,0), i.e. the cell itself, // the Y message from the outputFunction has been received by this cell itself ( // this is done by function localTransitionConfluent( msgs ), which must be called // at the very beginning of this function!!!!) // // Thus, the previousValue (P) is updated to be the last newValue (N) & the last // transientValue (T). Therefore, we have P = T = last N. // [P is actually the cell's current state value!] // // -> b> // if the cell's neighborhood does not include (0,0), the Y message sent by this // cell will not be received by this cell itself. Thus, P is NOT updated to the // last N (which is also the last T). Therefore, P != T & P != last N // // 2. If this cell is not imminent at all, the time change is triggered by some X messages // from the cell's neighbors followed by a * message. In this case, the outputFunction // and internalFunction is NOT called before this function. // -> As a result, this cell has no chance to update its P to T (or the last N). So // P may or may not be equal to T // // As we can see, P != T can happen in 1.b> or in 2. In order to make the following conditions // for "new state change", "change back", and "change further" correct, we have to update T to // be P whenever we detect a time change! // Update T = P just like we did in the initFunction! PortList::iterator port_cursor; for (port_cursor = outNCPortList().begin(); port_cursor != outNCPortList().end(); port_cursor++) { string out_port(port_cursor->second->name()); // output port name string in_port(calculateInPort(out_port)); // corresponding input port name Real currentPreviousValue = value(in_port); //set the T value on this output port, flag = FALSE setTransientValue(out_port, currentPreviousValue); //Note: this will reset the flags in transient values to FALSE as well, so // we can spare calling resetTransientFlags() } //end for [update T to P] //Now we can make sure P = T when we enter the if conditions for any NEW TIME! //end [2006-01-13] #endif // end JACKY_TDCELL `````````````````````````````````````````````````````````````````````` #ifdef JACKY_DEBUG jacky_os << "\t TDCell::externalFunction() After Update: RT = " << getRecordTime().asString() << endl << flush; jacky_os << "\t Reset flags in TQ to FALSE!!!!-------" << endl << flush; jacky_os << "\t [2006-01-13] NOTE: T is set to P for this new time!!!!" << endl << flush; //reset the round number to 0 roundNum = 0; #endif //end JACKY_DEBUG #ifdef JACKY_STATE_VAR // [2006-01-10] ////////////////////////////////////////////////////////////////////// //save the state variables in the RV recordStateVariables() = cellStateVariables(); #ifdef JACKY_DEBUG jacky_os << "\t[2006-01-10] TDCell ROUND " << roundNum << ", save state variables, SV = " << recordStateVariables().asString() << endl << flush; #endif //end JACKY_DEBUG #endif //end JACKY_STATE_VAR ///////////////////////////////////////////////////////////////////////////////// } //end if time change else { #ifdef JACKY_TDCELL // [2006-01-11] ````````````````````````````````````````````````````````````` //set the "time change" flag to false timeChanged = false; #endif // end JACKY_TDCELL `````````````````````````````````````````````````````````````````````` #ifdef JACKY_DEBUG //No time change happens, so these are the following rounds! ++roundNum; //increase the number of the round #endif //end JACKY_DEBUG } //This is should be removed once the new Cell Devs definition language is //approved and considers multiple messages from external models bool executedLocal = false; VTime delay( static_cast( parent() )->defaultDelay() ) ; //[2006-01-11] //this is the current simulated time, which is also the schedule time for all queue elements VTime actualTime( msgs.time() ); #ifdef JACKY_STATE_VAR // [2006-01-10] ////////////////////////////////////////////////////////////////////// //Before we evaluate the transition functions, reset the state variables using the recorded one cellStateVariables() = recordStateVariables(); #ifdef JACKY_DEBUG jacky_os << "\t[2006-01-10] TDCell: ROUND " << roundNum << " Restore state variables, V = " << cellStateVariables().asString() << endl << flush; #endif //end JACKY_DEBUG #endif //end JACKY_STATE_VAR ///////////////////////////////////////////////////////////////////////////////// #ifdef JACKY_DEBUG //here, delay is the default delay as defined in the MA file jacky_os << "[TD VARIABLE DELAY] default delay = " << delay.asString() << " / AT = " << msgs.time().asString() << endl << flush; #endif list tv; //Jacky: a list of , NewValues! ////////////////////////////////////////////////////////////////////// //Right now, for this implementation, give priority to portInTransitions //This should be changed! for ( MessageBag::iterator cursor = msgs.begin(); cursor != msgs.end(); cursor++) { ExternalMessage msg = *((ExternalMessage *)(*cursor)); if( !executedLocal && !isInNCPort( msg.port().name() ) ) { string functionName = inputPortFunction()[ msg.port().name() ]; if (functionName == DEFAULT_FUNCTION_InPort) { PortValue pv(msg.port().name(), msg.value()); tv.push_back(pv); #ifdef JACKY_DEBUG jacky_os << "\t\tTDCell::externalFunction() use default_function_inport: " << DEFAULT_FUNCTION_InPort << endl << flush; jacky_os << "\t\t\t(tv) = " << flush; for(list::iterator temp_it = tv.begin(); temp_it != tv.end(); temp_it++) { jacky_os << "<" << temp_it->first << " = " << (temp_it->second).value() << "> " << flush; } jacky_os << endl << flush; #endif } else { // sino es un PortInTransition valido VirtualPortList *vpl = new VirtualPortList; getOutPorts(vpl); #ifdef JACKY_DEBUG jacky_os << "\t\tTDCell::externalFunction() evaluate (" << functionName << ") with neighborhood : " << endl << flush; neighborhood().print(jacky_os); #endif tv = SingleLocalTransAdmin::Instance().evaluate( functionName, neighborhood(), &(inputPortValues()), delay, actualTime, vpl, this, msg.port().name() ) ; #ifdef JACKY_DEBUG jacky_os << "\t\t\t(tv) = " << flush; for(list::iterator temp_it = tv.begin(); temp_it != tv.end(); temp_it++) { jacky_os << "<" << temp_it->first << " = " << (temp_it->second).value() << "> " << flush; } jacky_os << endl << flush; #endif delete vpl; }//if executedLocal = true; }//if else if ( executedLocal && !isInNCPort( msg.port().name() ) ) { cerr << "At: " << msgs.time() << endl; cerr << "Warning: Current implementation can not handle multiple messages" << " from external models!!. Some messages have been ignored!" << endl; #ifdef JACKY_DEBUG jacky_os << "\t------------->TDCell::externalFunction() Warning: Current implementation can not" << " handle multiple messages from external models!!. Some messages have been ignored!!!" << endl << flush; #endif MASSERTMSG( false, "TDCell::externalFunction() -> check the EV file! Multiple inputs to a cell at the same time!" ); } }//for //If there were no messages in ports that were not neighbor ports if ( !executedLocal ) { VirtualPortList *vpl = new VirtualPortList; getOutPorts(vpl); #ifdef JACKY_DEBUG //see neighbors jacky_os << "\t\tTDCell::externalFunction() evaluate localFunc (" << localFunction() << ") with neighborhood : " << endl << flush; neighborhood().print(jacky_os); #endif tv = SingleLocalTransAdmin::Instance().evaluate( localFunction(), neighborhood(), NULL, delay, actualTime, vpl, this ) ; #ifdef JACKY_DEBUG jacky_os << "\t\t\t==>(tv) = " << flush; for(list::iterator temp_it = tv.begin(); temp_it != tv.end(); temp_it++) { jacky_os << "<" << temp_it->first << " = " << (temp_it->second).value() << "> " << flush; } jacky_os << endl << flush; #endif delete vpl; } #ifdef JACKY_DEBUG jacky_os << "\t\tTDCell::externalFunction() resulting (tv) is ---------------------- " << endl << flush; list::iterator tv_it; for (tv_it = tv.begin(); tv_it != tv.end(); tv_it++){ jacky_os << "\t\t\t" << tv_it->first << " = " << (tv_it->second).value() << endl << flush; } jacky_os << "\t\tTDCell::externalFunction() BEFORE COMPARISON, [transientQ] is ==========" << endl << flush; TDCellState::TransientQueue::const_iterator transientQ_it; //print the Transient Queue for (transientQ_it = transientVal().begin(); transientQ_it != transientVal().end(); transientQ_it++){ jacky_os << "\t\t" << (transientQ_it->first).first // portName << " = " << (transientQ_it->first).second.value() << " / "<< flush; // portValue if(transientQ_it->second == true){ // flag in TQ jacky_os << "flag = TRUE" << endl << flush; } else { jacky_os << "flag = FALSE" << endl << flush; } } #endif /////////////////////////////////////////////////////////////////////// Real ltb; // Previous value (P) #ifdef JACKY_SYNC Real tranValue; // Transient value (T) #ifdef JACKY_PORTIN_FIRST //[2006-01-06] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bool tranValueFlag; // Transient flag (TF) #endif // JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //#ifdef JACKY_TDCELL // [2006-01-11] ``````````````````````````````````` //all external events to be put onto the queue have a schedule time //that is equal to the current simulatied time // VTime scheduleTime = msgs.time(); // Schedule Time (ST) //#endif // JACKY_TDCELL ``````````````````````````````````````````````` #endif // JACKY_SYNC ///////////////////////////////////////////////////////////////////////////////////////////// //Dec. 8, 2005 //Jacky Note: // the following valueTime is calculated from the msgTime [actualTime] and // the delay [static_cast(parent())->defaultDelay()] // if the delay is constant, there is no problem; // if the delay is NOT constant, then the resulting valueTime may be different // each time the calculation is done. Thus, the "change-back" and "change-further" // scenarios for the multi-round message passing may generate wrong results (they // erase/replace the element on the Queue based on the TIME and PORT value to find // the target element) // So how to handle this situation? ///////////////////////////////////////////////////////////////////////////////////////////// //[2006-01-11] //valueTime is the output time (OT) when the internal event on the queue will be output VTime valueTime = actualTime + delay; #ifdef JACKY_DEBUG jacky_os << "[TD VARIABLE DELAY 2] new D = " << delay.asString() << " / AT = " << msgs.time().asString() << " => VT (D+AT) = " << valueTime.asString() << endl << flush; #endif list::iterator pvCursor; //cout << "Cell: " << cellPosition().print() << endl; //cout << "UseQuantum().Active() " << UseQuantum().Active() << " UseDynQuantum().Active() " // << UseDynQuantum().Active() << endl; //cout << "tv = " << tv.asString() << " ltb = " << ltb.asString() << endl; //cout << "valueWithQuantum(tv, QuantumValue() = " << valueWithQuantum(tv, QuantumValue()).asString() << endl; //cout << "valueWithQuantum(ltb, QuantumValue() = " << valueWithQuantum(ltb, QuantumValue()).asString() << endl; #ifdef JACKY_DEBUG int for_count = 0; #endif /****************************************************************************************************************** ** Jacky Note: ** "tv" (a list of ) ---> contains the NewValues calculated from the inputPortFunction & the ** localFunction. ** In the following iteration over the "tv" list, we first get the PreviousValues from the corresponding ** "neighborChange" or "in_XXX" or other input ports in "ltb", and then compare the corresponding NewValue in ** "tv" and the PreviousValue in "ltb" ** 1. if a> Quantization (static or dynamic) is used && the quantized values are different OR ** b> Quantization is NOT used && the values are different ** -> state change happens! insert element onto the Queue ** 2. if dynamic quantization is used, adjust the Quantum size based on the comparison of the quantized values ** ** In my revision, the transientVal list holds temporary values on all output port of the cell ** We will go through the values in the "tv" (the NewValues), compare the three values: ** A> previous value : "ltb" ** B> transient value: value in the TransientQueue ** C> new value : value in the "tv" ** There are 5 possibilities [see document] */ //iterate over all new values for (pvCursor = tv.begin(); pvCursor != tv.end(); pvCursor++){ #ifdef JACKY_DEBUG jacky_os << "\t\t***TDCell::externalFunction() for(" << for_count << ") NEW value: <" << pvCursor->first << " = " << (pvCursor->second).value() << ">" << endl << flush; #endif string in_port = calculateInPort(pvCursor->first); string out_port = calculateOutPort(pvCursor->first); ltb = value(in_port); //Jacky: P tranValue = getTransientValue(out_port); //Jacky: T tranValueFlag = getTransientValueFlag(out_port); //Jacky: TF #ifdef JACKY_DEBUG jacky_os << "[PORT TRANSFER] tv::portName = " << pvCursor->first << " / in_port = " << in_port << " / corresponding out_port = " << out_port << endl << flush; jacky_os << "\t\t\t PREVIOUS value: <" << in_port << " = " << ltb.value() << ">" << endl << flush; jacky_os << "\t\t\t TRANSIENT value: <" << out_port << " = " << tranValue.value() << "> [flag = " << flush; if( tranValueFlag == true ){ jacky_os << "TRUE" << endl << flush; } else { jacky_os << "FALSE" << endl << flush; } jacky_os << "\t\t for(" << for_count << ") BEFORE: Queue size = " << queueVal().size() << " : " << endl << flush; list::iterator q_it; int q_count = 0; //print the current Queue for (q_it = queueVal().begin(); q_it != queueVal().end(); q_it++){ jacky_os << "\t\t\t[" << ++q_count << "] OT = " << (q_it->first).asString() //output time << " / " << (q_it->second).first.first << " = " //portName << (q_it->second).first.second.value() << " / " << flush; //portValue #ifndef JACKY_TDCELL // [2006-01-11] `````````````````````````````````````````````````````````````````````` if( (q_it->second).second == true ){ jacky_os << " flag = TRUE" << endl << flush; } else { jacky_os << " flag = FALSE" << endl << flush; } #else // [2006-01-11] `````````````````` print the schedule time of the element ``````````````````````````` jacky_os << "ST = " << (q_it->second).second.asString() << endl << flush; //schedule time #endif // end JACKY_TDCELL } #endif // [2006-01-06] //The following condition is added to avoid offset results derived from external events //Change back & change further of the cell state is only allowed if no external event received at this time //Once an event is received: // if the event causes a state change -> change the state, and set flag=TRUE, thus no further change // if the event does not cause a change -> just set flag=TRUE, thus no further change as well // for ALL the message-passing rounds at this time. // When time changes, the flag will be reset to false. if( tranValueFlag == false ){ // if flag in T is FALSE, i.e. TF = FALSE //1> new state change happens if( ( ( UseQuantum().Active() || UseDynQuantum().Active() ) && ( valueWithQuantum(pvCursor->second, QuantumValue()) != valueWithQuantum(ltb, QuantumValue()) ) && //N != P ( valueWithQuantum(ltb, QuantumValue()) == valueWithQuantum(tranValue, QuantumValue()) ) //P == T ) || ( !UseQuantum().Active() && ( ltb != pvCursor->second ) && //N != P ( ltb == tranValue ) //P == T ) ) { #ifdef JACKY_DEBUG jacky_os << "\t\t\t 1> new state change " << endl << flush; #endif //a> set T = N if( isInputPort(pvCursor->first) ){ //Value change is derived from external event! //set the flag in the transient value to TRUE setTransientValue(out_port, pvCursor->second, true); #ifdef JACKY_DEBUG jacky_os << "[~~PORT~~] set TRANSIENT value : <" << out_port << " = " << pvCursor->second.value() << " / flag = TRUE>" << endl << flush; #endif } else { setTransientValue(out_port, pvCursor->second); #ifdef JACKY_DEBUG jacky_os << "[~~PORT~~] set TRANSIENT value : <" << out_port << " = " << pvCursor->second.value() << " / flag = FALSE>" << endl << flush; #endif } //end update [T] //b> Queue insertion TDCellState::Queue::iterator cursorAux; for ( cursorAux = queueVal().begin(); cursorAux != queueVal().end() && cursorAux->first <= valueTime; cursorAux++ ); //Jacky: Now cursorAux points to the 1st element with time > valueTime or NULL // the new element will be inserted before cursorAux //Jacky: create a new element with NEW value to be inserted onto the Queue TDCellState::QueueValue qv(out_port, pvCursor->second); #ifndef JACKY_TDCELL //[2006-01-11] ```````` previously, there is a flag in queue element `````````````````````````` // [2006-01-06] // Flags in the elements on the Queue will be set to TRUE iff the insertion (i.e. new // state change) is triggered by an external event if( isInputPort(pvCursor->first) ){ TDCellState::QueueValueWithFlag qvf(qv, true); queueVal().insert( cursorAux, TDCellState::QueueElement(valueTime, qvf) ); } else { TDCellState::QueueValueWithFlag qvf(qv, false); queueVal().insert( cursorAux, TDCellState::QueueElement(valueTime, qvf) ); } //end insertion of Queue #else // [2006-01-11] ```````````Now, there is no flag in queue elements, but there is a schedule time ````````````` //the schedule time is actualTime TDCellState::QueueValueWithScheduleTime qvst(qv, actualTime); //insert the qvst onto the queue at the place given by "cursorAux" //the output time is valueTime queueVal().insert( cursorAux, TDCellState::QueueElement(valueTime, qvst) ); #endif // end JACKY_TDCELL holdIn( AtomicState::active, firstQueuedTime() - msgs.time() ); } //end if 1> [new state change] //2> change back else if( ( ( UseQuantum().Active() || UseDynQuantum().Active() ) && ( valueWithQuantum(pvCursor->second, QuantumValue()) == valueWithQuantum(ltb, QuantumValue()) ) && //N == P ( valueWithQuantum(ltb, QuantumValue()) != valueWithQuantum(tranValue, QuantumValue()) ) && //P != T ( valueWithQuantum(pvCursor->second, QuantumValue()) != valueWithQuantum(tranValue, QuantumValue()) ) //N != T ) || ( !UseQuantum().Active() && ( pvCursor->second == ltb ) && //N == P ( ltb != tranValue ) && //P != T ( pvCursor->second != tranValue ) //N != T ) ) { //[2006-01-06] // we can enter the "new change"/"change back"/"change further" logic iff TF = false // don't need to test the Flag in the Queue elements again here!!! // if( getQueueElementFlag(valueTime, out_port) == false ){ //not event //a> reset T = P //setTransientValue(out_port, ltb); #ifdef JACKY_DEBUG jacky_os << "\t\t\t 2> change back" << endl << flush; jacky_os << "\t\t Set TransientValue T = PreviousValue = <" << out_port << " = " << ltb.value() << ">" << endl << flush; #endif //[2006-01-11] if( isInputPort(pvCursor->first) ){ //Value change is derived from external event! //set the flag in the transient value to TRUE setTransientValue(out_port, ltb, true); #ifdef JACKY_DEBUG jacky_os << "[Change Back] reset T = P : <" << out_port << " = " << ltb.value() << " / flag = TRUE>" << endl << flush; #endif } else { setTransientValue(out_port, pvCursor->second); #ifdef JACKY_DEBUG jacky_os << "[Change Back] reset T = P : <" << out_port << " = " << ltb.value() << " / flag = FALSE>" << endl << flush; #endif } //end update [T] //end [2006-01-11] #ifndef JACKY_TDCELL //[2006-01-11] ``````````````````` previous version: search output time ````````````````````````` //b> Queue removal TDCellState::Queue::iterator cursorAux; #ifdef JACKY_DEBUG jacky_os << "[TD VARIABLE DELAY 3] Change Back! find element with [OT = " << valueTime.asString() << " & PORT = " << out_port << "] on the Queue" << endl << flush; #endif bool found = false; for ( cursorAux = queueVal().begin(); cursorAux != queueVal().end(); cursorAux++) { if( ( cursorAux->first == valueTime ) && ( (cursorAux->second).first.first == out_port ) ) {//same time & same port found = true; break; } } #ifdef JACKY_DEBUG if( found ){ jacky_os << "\t\t\t\t--> previous element with same outputTime & portName removed from the Queue!" << endl << flush; } else { jacky_os << "\t\t\t\t--> No element on Queue is found with same outputTime & portName, REMOVAL FAILED!" << endl << flush; } #endif MASSERTMSG( found, "TDCell::externalFunction() -> no element found, ChangeBack:Removal failed!" ); queueVal().erase( cursorAux ); //[2006-01-06] The following 6 lines are not needed any more!!! // } else { //result is from external event // //No change back & no removal !!! //#ifdef JACKY_DEBUG // jacky_os << "[~~PORT~~] should NOT change BACK the result from external events!!!!!" << endl << flush; //#endif // } //end if event if( !queueVal().empty() ){ holdIn( AtomicState::active, firstQueuedTime() - msgs.time() ); } else { passivate(); } #else //[2006-01-11] ````````````````````` new version: search schedule time ````````````````````````````````````````` //[2006-01-11] //if this is within the process of multiple-round message passing, we need //to do Queue Removal; if it is not (i.e. getRecordTime() != msgs.time(), //msgTime has changed), we do nothing here! if( !timeChanged ){ //[2006-01-11] //Time has not changed, we are within the multiple rounds at the given time! //Do Queue removal! //b> Queue removal TDCellState::Queue::iterator cursorAux; #ifdef JACKY_DEBUG jacky_os << "[TD VARIABLE DELAY 3] MultipleRound! Change Back -> find element with [ST = " << actualTime.asString() << " & PORT = " << out_port << "] on the Queue" << endl << flush; #endif bool found = false; for ( cursorAux = queueVal().begin(); cursorAux != queueVal().end(); cursorAux++) { //scheduleTime = actualTime if( ( (cursorAux->second).second == actualTime ) && ( (cursorAux->second).first.first == out_port ) ) { //same schedule time & same port found = true; break; } } #ifdef JACKY_DEBUG if( found ){ jacky_os << "\t\t\t\t--> previous element with [ST = " << actualTime.asString() << " / port = " << out_port << "] found, remove from the Queue!" << endl << flush; } else { jacky_os << "\t\t\t\t--> No element with [ST = " << actualTime.asString() << " / port = " << out_port << "] is found, REMOVAL FAILED! [Variable Delays used? ]" << endl << flush; } #endif MASSERTMSG( found, "TDCell::externalFunction()->no element found, ChangeBack:Removal failed!"); queueVal().erase( cursorAux ); if( !queueVal().empty() ){ holdIn( AtomicState::active, firstQueuedTime() - msgs.time() ); } else { passivate(); } } //end if ( !timeChanged ) else { //The time has changed, it's NOT within the multiple rounds! //In this case, since N = P (i.e. No state change), no new element should be //added onto the Queue, nor do we need to remove some element from the Queue //leave the Queue along & no state change! #ifdef JACKY_DEBUG jacky_os << "[2006-01-11]TDCell:ChangeBack & timeChanged = TRUE -> Not in multiple rounds! NO REMOVAL!" << endl << flush; #endif } //end if ( timeChanged ) #endif // end JACKTY_TDCELL ``````````````````````````````````````````````````````````````````````````````````````````` } //end if 2> [change back] //3> change further else if( ( ( UseQuantum().Active() || UseDynQuantum().Active() ) && ( valueWithQuantum(pvCursor->second, QuantumValue()) != valueWithQuantum(ltb, QuantumValue()) ) && //N != P ( valueWithQuantum(ltb, QuantumValue()) != valueWithQuantum(tranValue, QuantumValue()) ) && //P != T ( valueWithQuantum(pvCursor->second, QuantumValue()) != valueWithQuantum(tranValue, QuantumValue()) ) //N != T ) || ( !UseQuantum().Active() && ( pvCursor->second != ltb ) && //N != P ( ltb != tranValue ) && //P != T ( pvCursor->second != tranValue ) //N != T ) ) { //[2006-01-06] // we can enter the "new change"/"change back"/"change further" logic iff TF = false // don't need to test the Flag in the Queue elements again here!!! // if( getQueueElementFlag(valueTime, out_port) == false ){ //not event //a> set T = N //setTransientValue(out_port, pvCursor->second); #ifdef JACKY_DEBUG jacky_os << "\t\t\t 3> change further" << endl << flush; jacky_os << "\t\t Set TransientValue T = NewValue = <" << out_port << " = " << (pvCursor->second).value() << ">" << endl << flush; #endif //[2006-01-11] if( isInputPort(pvCursor->first) ){ //Value change is derived from external event! //set the flag in the transient value to TRUE setTransientValue(out_port, pvCursor->second, true); #ifdef JACKY_DEBUG jacky_os << "[Change Further] reset T = N : <" << out_port << " = " << (pvCursor->second).value() << " / flag = TRUE>" << endl << flush; #endif } else { setTransientValue(out_port, pvCursor->second); #ifdef JACKY_DEBUG jacky_os << "[Change Further] reset T = N : <" << out_port << " = " << (pvCursor->second).value() << " / flag = FALSE>" << endl << flush; #endif } //end update [T] //end [2006-01-11] #ifndef JACKY_TDCELL //[2006-01-11] ``````````````````` previous version: search output time ````````````````````````` #ifdef JACKY_DEBUG jacky_os << "[TD VARIABLE DELAY 4] Change Further! find element with [OT = " << valueTime.asString() << " / PORT = " << out_port << "] on the Queue" << endl << flush; #endif //b> Queue replacement TDCellState::Queue::iterator cursorAux; bool found = false; for ( cursorAux = queueVal().begin(); cursorAux != queueVal().end(); cursorAux++) { if( ( cursorAux->first == valueTime ) && ( (cursorAux->second).first.first == out_port ) ) { //same time & same port found = true; break; } } #ifdef JACKY_DEBUG if( found ){ jacky_os << "\t\t\t\t--> previous element replaced from the Queue!" << endl << flush; } else { jacky_os << "\t\t\t\t--> No element on Queue is found, REPLACEMENT FAILED! [Variable Delays used? ]" << endl << flush; } #endif MASSERTMSG( found, "TDCell::externalFunction() -> no element on Queue is found, replacement failed!" ); (cursorAux->second).first.second = pvCursor->second; //replace the value on that port //[2006-01-06] The following 6 lines are not needed any more!!! // } else { //result is from external event // //No change back & no replacement !!! //#ifdef JACKY_DEBUG // jacky_os << "[~~PORT~~] should NOT change FURTHER the result from external events!!!!!" << endl << flush; //#endif // } //end if external event holdIn( AtomicState::active, firstQueuedTime() - msgs.time() ); #else //[2006-01-11] ````````````````````` new version: search schedule time ````````````````````````````````````````` //[2006-01-11] //if this is within the process of multiple-round message passing, we need //to do Queue Replacement; if it is not (i.e. getRecordTime() != msgs.time(), //msgTime has changed), we do Queue Insertion here (i.e. a new state change //happened at a new time)! if( !timeChanged ){ //[2006-01-11] //Time has not changed, we are within the multiple rounds at the given time! //Do Queue replacement! #ifdef JACKY_DEBUG jacky_os << "[TD VARIABLE DELAY 4] Change Further! find element with [ST = " << actualTime.asString() << " / PORT = " << out_port << "] on the Queue" << endl << flush; #endif //b> Queue replacement TDCellState::Queue::iterator cursorAux; bool found = false; for ( cursorAux = queueVal().begin(); cursorAux != queueVal().end(); cursorAux++) { //scheduleTime = actualTime if( ( (cursorAux->second).second == actualTime ) && ( (cursorAux->second).first.first == out_port ) ) { //same schedule time & same port found = true; break; } } #ifdef JACKY_DEBUG if( found ){ jacky_os << "\t\t\t\t--> previous element with [ST = " << actualTime.asString() << " / port = " << out_port << "] found, replace it on the Queue!" << endl << flush; } else { jacky_os << "\t\t\t\t--> No element with [ST = " << actualTime.asString() << " / port = " << out_port << "] is found, REPLACEMENT FAILED! [Variable Delays used? ]" << endl << flush; } #endif MASSERTMSG( found, "TDCell::externalFunction()->no element found, ChangeFurther:Replacement failed!"); //replace the value on that port (cursorAux->second).first.second = pvCursor->second; holdIn( AtomicState::active, firstQueuedTime() - msgs.time() ); } //end if ( !timeChanged ) else { //The time has changed, it's NOT within the multiple rounds! //In this case, since N != P (i.e. state change), new element should be //added onto the Queue //insert element on the queue #ifdef JACKY_DEBUG jacky_os << "[2006-01-11]TDCell:ChangeFurther & timeChanged = TRUE -> Not in multiple rounds! Q INSERTION!!!" << endl << flush; #endif //c> Queue insertion TDCellState::Queue::iterator cursorAux; for ( cursorAux = queueVal().begin(); cursorAux != queueVal().end() && cursorAux->first <= valueTime; cursorAux++ ); //Jacky: Now cursorAux points to the 1st element with time > valueTime or NULL // the new element will be inserted before cursorAux //Jacky: create a new element with NEW value to be inserted onto the Queue TDCellState::QueueValue qv(out_port, pvCursor->second); //the schedule time is actualTime TDCellState::QueueValueWithScheduleTime qvst(qv, actualTime); //insert the qvst onto the queue at the place given by "cursorAux" //the output time is valueTime queueVal().insert( cursorAux, TDCellState::QueueElement(valueTime, qvst) ); holdIn( AtomicState::active, firstQueuedTime() - msgs.time() ); } //end if ( timeChanged ) #endif // end JACKTY_TDCELL ``````````````````````````````````````````````````````````````````````````````````````````` } //end if 3> [change further] // [ ****************** 2006-01-06 *********************] // Note:If the external event does not cause cell's value changes, i.e. N = P // We still need to set the flag in the TransientValue to TRUE so that further messages // from neighbors will NOT cause new changes to this cell!!! // Ex: At time 04:000, cell's value is 1 (P), and an external event arrives at the cell // at the same time 04:000 with value 1. Thus, the cell's value at time 05:000 (after // a delay of 1000) should be 1 (the same as the external event based on Default-Port-In) // The resulting tv is , which is the same as the event value. In the following // rounds of message-passing, the cell gets values from its neighbors (all 1's), and the // resulting tv is based on Local-Transition. // Since in the 1st round, the event didn't cause state change, the flag in T is NOT set // to TRUE, the cell's value will be changed to 0 in the 2nd round!!! // This is NOT what we want! We need to set the flag in T to TRUE event when the external // event does not trigger a state change in the cell! // The following else clause will set the flag in T to TRUE (but do NOT change the value in T) // if the tv is derived from an event. else { // No state change, N = P if( isInputPort(pvCursor->first) ){ // set the flag in T to TRUE // In this case, external event's value is the same as the current cell's value // No value change! And we will NOT allow any potential urther changes derived // from neighbor's values in the later rounds of message-passing //portName = out_port //value is the current value, getTransientValue(out_port) //TF = true setTransientValue(out_port, getTransientValue(out_port), true); } } } //end "result-NOT-derived-from-external-events", TF = false else { //[2006-01-06] // If TF = TRUE, i.e. the value of the cell has been changed (or is the same as the // external event) according to the external event, do NOTHING! #ifdef JACKY_DEBUG jacky_os << "[~~PORT~~] Scheduled change is derived from events! No further change is allowed!!! ~~~~~~~~~~~~~~" << endl << flush; #endif } //If using DynamicQuantum, calculate the new Quantum value. if ( UseDynQuantum().Active() ) { #ifdef JACKY_DEBUG jacky_os << "\t\t\t Using Dynamic Quantization, change Quantum Size -------" << endl << flush; #endif if ( valueWithQuantum(pvCursor->second, QuantumValue()) == valueWithQuantum(ltb, QuantumValue())) {//Jacky: N == P if ( UseDynQuantum().Strat() ) QuantumValue ( QuantumValue() * (1-UseDynQuantum().Ratio())); else QuantumValue ( QuantumValue() * (1+UseDynQuantum().Ratio())); } //GW // Esta es una nueva modificacion: si son distintos, lo reduzco. else { // Jacky: N != P if ( !UseDynQuantum().Strat() ) QuantumValue ( QuantumValue() * (1-UseDynQuantum().Ratio())); else QuantumValue ( QuantumValue() * (1+UseDynQuantum().Ratio())); } //cout << " q act = " << QuantumValue().value() << endl; } //end if } // for #ifdef JACKY_DEBUG jacky_os << "\t\tTDCell::externalFunction() before END Queue size = " << queueVal().size() << " ------------- " << endl << flush; list::iterator q_it; int q_count = 0; for (q_it = queueVal().begin(); q_it != queueVal().end(); q_it++){ jacky_os << "\t\t[" << ++q_count << "] " << (q_it->first).asString() //time << " / " << (q_it->second).first.first << " = " //portName << (q_it->second).first.second.value() << " / " << flush; //portValue if( (q_it->second).second == true ){ jacky_os << " flag = TRUE" << endl << flush; } else { jacky_os << " flag = FALSE" << endl << flush; } } jacky_os << "\t\tTDCell::externalFunction() queue End -------------------- " << endl << flush; #endif return *this ; } #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /****************************************************************** * Method: internalFunction * Jacky : This function will remove all elements on the Queue that have * the same time as the received * msg. ********************************************************************/ Model &TransportDelayCell::internalFunction( const InternalMessage &msg ) { /* #ifdef JACKY_DEBUG if( (firstQueuedTime() != msg.time()) || (queueVal().empty()) ){ if(firstQueuedTime() != msg.time()){ cerr << "TDCell::internalFunction() -> firstQTime = " << firstQueuedTime().asString() << " / msgTime = " << msg.time().asString() << " | NOT EQUAL!" << endl; } if(queueVal().empty()){ cerr << "TDCell::internalFunction() -> QSize = " << queueVal().size() << " | EMPTY!" << endl; } } #endif */ MASSERT( !queueVal().empty() && firstQueuedTime() == msg.time() ) ; #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "\t------------->TDCell[" << asString() << "]::internalFunction() called" << endl << flush; #endif //Delete all messages that are scheduled for the current time while (!queueVal().empty() && firstQueuedTime() == msg.time() ){ #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^^^^^^ Previous Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #ifdef JACKY_DEBUG jacky_os << "\t\t TDCell[" << asString() << "]::internalFunction() erase <" << (queueVal().begin()->first).asString() << " / " //time << (queueVal().begin()->second).first << " = " //portName << (queueVal().begin()->second).second.value() //portValue << ">" << endl << flush; #endif #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #ifdef JACKY_DEBUG jacky_os << "\t\t TDCell[" << asString() << "]::internalFunction() erase first).asString() << " / " //output time << (queueVal().begin()->second).first.first << " = " //portName << (queueVal().begin()->second).first.second.value() //portValue #ifdef JACKY_TDCELL //[2006-01-11] ````````````````````````````````````````````````````````````` << " / ST = " << (queueVal().begin()->second).second.asString() //schedule time #endif // end JACKY_TDCELL `````````````````````````````````````````````````````````````````````` << ">" << endl << flush; #endif //end JACKY_DEBUG #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ queueVal().erase( queueVal().begin() ); } if( queueVal().empty() ) { passivate() ; #ifdef JACKY_DEBUG jacky_os << "\t\t TDCell[" << asString() << "]::internalFunction() passivate()!" << endl << flush; #endif } else { #ifdef JACKY_DEBUG jacky_os << "\t\t TDCell[" << asString() << "]::internalFunction() stay active for period = " << ( firstQueuedTime() - msg.time() ).asString() << endl << flush; #endif holdIn( AtomicState::active, ( firstQueuedTime() - msg.time() ) ); } return *this ; } /******************************************************************* * Method: outputFunction * Jacky : This function will send all elements on the Queue that have * the same time as the time of the received @ msg ********************************************************************/ Model &TransportDelayCell::outputFunction( const CollectMessage &msg ) { //Send all messages that are scheduled for the current time TDCellState::Queue::iterator cursor; #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "\t------------->TDCell[" << asString() << "]::outputFunction() called, cellState::QueueSize = " << queueVal().size() << endl << flush; #endif for( cursor = queueVal().begin() ; cursor != queueVal().end() && cursor->first == msg.time() ; cursor++ ) { //sendOutput( msg.time(), outputPort(), cursor->second.value() ) ; #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^^^^^^ Previous Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #ifdef JACKY_DEBUG jacky_os << "\t\t\t TDCell[" << asString() << "] sends value=" << cursor->second.second.value() << " to port=" << outputPort(cursor->second.first).name() << "@" << outputPort(cursor->second.first).model().asString() << endl << flush; #endif sendOutput( msg.time(), outputPort(cursor->second.first), cursor->second.second.value() ) ; #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #ifdef JACKY_DEBUG jacky_os << "\t\t\t TDCell[" << asString() << "] sends value=" << (cursor->second).first.second.value() << " to port=" << outputPort((cursor->second).first.first).name() << "@" << outputPort((cursor->second).first.first).model().asString() << endl << flush; #endif sendOutput( msg.time(), outputPort((cursor->second).first.first), (cursor->second).first.second.value() ) ; #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } return *this ; } /******************************************************************* * Function Name: firstQueuedTime ********************************************************************/ const VTime & TransportDelayCell::firstQueuedTime() const { return queueVal().begin()->first; } /******************************************************************* * Function Name: firstQueuedValue ********************************************************************/ const Real &TransportDelayCell::firstQueuedValue() const { #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^ Previous Version ^^^^ TDCellState::QueueValue &QV = queueVal().begin()->second; return QV.second; #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^ TDCellState::QueueValue &QV = (queueVal().begin()->second).first; return QV.second; #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } /******************************************************************* * Function Name: firstQueuedPort ********************************************************************/ const string &TransportDelayCell::firstQueuedPort() const { #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^ Previous Version ^^^^^^ TDCellState::QueueValue &QV = queueVal().begin()->second; return QV.first; #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^^^ TDCellState::QueueValue &QV = (queueVal().begin()->second).first; return QV.first; #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } /******************************************************************* * Function Name: updateRemainingTime * Description : this function is to update the output time for all elements on the Queue to reflect the elapse of time ********************************************************************/ TransportDelayCell & TransportDelayCell::updateRemainingTime( const VTime &elapsed ) { for( TDCellState::Queue::iterator cursor = queueVal().begin() ; cursor != queueVal().end() ; cursor++ ) cursor->first -= elapsed ; return *this; } #ifdef JACKY_SYNC /******************************************************************* * Function Name: getTransientValue * Description : function to get the transient value on a given port ********************************************************************/ const Real &TransportDelayCell::getTransientValue(const string &portName) const{ TDCellState::TransientQueue::iterator it; bool result = false; for( it = transientVal().begin(); it != transientVal().end() ; it++){ #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^ Previous Version ^^^^ if( it->first == portName ){ #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^ if( (it->first).first == portName){ #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ result = true; break; } } MASSERTMSG( result, "TDCell::getTransientValue() -> no transient value on \"" + portName + "\" is found!" ); #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^ Previous Version ^^^^ return it->second; #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^ return (it->first).second; #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } #ifdef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^ Previous Version ^^^^^ //function to get the flag in the transient value const bool TransportDelayCell::getTransientValueFlag(const string &portName) const{ TDCellState::TransientQueue::iterator it; bool result = false; for( it = transientVal().begin(); it != transientVal().end() ; it++){ if( (it->first).first == portName){ result = true; break; } } MASSERTMSG(result, "TDCell::getTransientValueFlag() -> no transient value flag on \"" + portName + "\" is found!"); return it->second; } //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 TransportDelayCell::getQueueElementFlag(const VTime &time, const string &portName) { TDCellState::Queue::const_iterator cursorAux; bool result = false; bool found = false; #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); #endif for ( cursorAux = queueVal().begin(); cursorAux != queueVal().end(); cursorAux++) { if( ( cursorAux->first == time ) && ( (cursorAux->second).first.first == portName ) ) { //same time & same port result = (cursorAux->second).second; found = true; #ifdef JACKY_DEBUG jacky_os << "[====Note====] element on Queue found, flag = " << flush; if( result ){ jacky_os << "TRUE ~~~~~~~~~~~~~" << endl << flush; } else { jacky_os << "FALSE ~~~~~~~~~~~~" << endl << flush; } #endif break; } } #ifdef JACKY_DEBUG if(found == false){ //Not found! jacky_os << "[ERROR] cannot find element for