/******************************************************************* * * DESCRIPTION: class InertialDelayCell * * 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://gabrielw@dc.uba.ar * mailto://liuqi@sce.carleton.ca * * DATE: 27/06/1998 * DATE: 17/09/1999 (v2) * DATE: 09/10/2005 (v5) * *******************************************************************/ // ** include files **// #include "idcell.h" // header class #include "message.h" // ExternalMessage #include "coupcell.h" // CoupledCell #include "realfunc.h" // calculateWithQuantum /*************************************** * INERTIAL DELAY CELL STATE ***************************************/ /*************************************** * Method: operator= ***************************************/ IDCellState &IDCellState::operator=(IDCellState& thisState) { (AtomicCellState &)*this = (AtomicCellState &)thisState; actualValue = thisState.actualValue; futureValue = thisState.futureValue; #ifdef JACKY_SYNC //======================================= recordActual = thisState.recordActual; recordTime = thisState.recordTime; recordState = thisState.recordState; #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 /////////////////////// #ifdef JACKY_IDCELL // [2006-01-16] ```````````````` //record the delay of the cell at the beginning //of R0 if its phase is Active recordDelay = thisState.recordDelay; #endif //end JACKY_IDCELL `````````````````````````` #endif //end JACKY_SYNC =================================== return *this; } /*************************************** * Method: copyState ***************************************/ #ifndef JACKY_REVISION //original version =============== void IDCellState::copyState(IDCellState *thisState) { *this = *(IDCellState *) thisState; } #else //This is Jacky's revision 10-17-2005 ============== void IDCellState::copyState(BasicState *rhs){ *this = *((IDCellState*)rhs); } #endif //================================================= /*************************************** * Method: getSize() ***************************************/ int IDCellState::getSize() const { return sizeof(IDCellState); } /*************************************** * INERTIAL DELAY CELL ***************************************/ /******************************************************************* * Method: initializeCell ********************************************************************/ void InertialDelayCell::initializeCell() { AtomicCell::initializeCell(); //This function requires the cell state to be already created. if ( UseQuantum().Active() ) QuantumValue( Real(UseQuantum().Value()) ); } /******************************************************************* * Method: initFunction * Description: ********************************************************************/ Model &InertialDelayCell::initFunction() { PortList::iterator cursor; //To start the simulation, send an output message with the current //value and passivate. Model will become active on processing the //outputs from the other cells. for (cursor = outNCPortList().begin(); cursor != outNCPortList().end(); cursor++) { string out_port(cursor->second->name()); string in_port(calculateInPort(out_port)); actualValue( out_port, value(in_port) ); //Jacky: set actual value, flag is default FALSE futureValue( out_port, value(in_port) ); //Jacky: set future value, flag is default FALSE #ifdef JACKY_SYNC //================================================================== //Jacky: get a copy of the current actual value, flag is default FALSE setRecordActual( out_port, value(in_port) ); #endif //end JACKY_SYNC ============================================================= } holdIn( AtomicState::active, VTime::Zero); #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "\t --------> IDCell::initFunction() -> " << endl << flush; jacky_os << "\t\t --- RT = " << getRecordTime().asString() << " / " << "RS = " << flush; if(getRecordState() == AtomicState::active){ jacky_os << "active" << endl << flush; } else { jacky_os << "passive" << endl << flush; } jacky_os << "\t\t --- A = " << flush; printValues(actualMap(), jacky_os); jacky_os << endl << "\t\t --- F = " << flush; printValues(futureMap(), jacky_os); jacky_os << endl << "\t\t --- RA = " << flush; printValues(recordActualVal(), jacky_os); jacky_os << endl << flush; #endif //end JACKY_DEBUG #ifdef JACKY_SYNC //================================================================= //Jacky: initialize the recordTime to 0 setRecordTime( VTime::Zero ); //Jacky: initialize the recordState to passive setRecordState( AtomicState::passive ); #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 IDCellState = " << recordStateVariables().asString() << endl << flush; #endif #endif //end JACKY_STATE_VAR ///////////////////////////////////////////////// #ifdef JACKY_IDCELL // [2006-01-16] `````````````````````````````````````````` //initialize the RD to Zero since when the cell enters externalFunction //(after outputFunction and internalFunction) the cell's delay at time 0 //will be Infinity. The internalFunction calls passivate() on this cell! setRecordDelay( VTime::Inf ); #endif //end JACKY_IDCELL ```````````````````````````````````````````````````` #endif //end JACKY_SYNC ============================================================= #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 &InertialDelayCell::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, "IDCell::externalFunction() -> macro JACKY_PORTIN_FIRST is NOT defined!" ); return *this ; } #else // Nov. 29, 2005 ^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Model &InertialDelayCell::externalFunction( const MessageBag &msgs ) { //This function must be called before processing any messages! //It is this function who will set the neighborhood value //correctly localTransitionConfluent( msgs ); #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "\t-------->IDCell::externalFunction() called() " << endl << flush; #endif #ifdef JACKY_SYNC //================================================================== #ifdef JACKY_IDCELL // [2006-01-16] ````````````````````````````````````````````````````````````` //flag to record a time change bool timeChanged; #endif // end JACKY_IDCELL `````````````````````````````````````````````````````````````````````` //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!!!!! IDCell::externalFunction() Time Change !!!!!" << endl << flush; jacky_os << "\t\t Before Update: RT = " << getRecordTime().asString() << " / " << "RS = " << flush; if(getRecordState() == AtomicState::active){ jacky_os << "active" << endl << flush; } else { jacky_os << "passive" << endl << flush; } jacky_os << "\t\t Before Update: RA = " << flush; printValues(recordActualVal(), jacky_os); jacky_os << endl << flush; #endif //1> update the RT setRecordTime( msgs.time() ); //2> update the RS for this new time setRecordState( state() ); //3> reset the flags in ActualValue to false resetValueFlags( actualMap() ); //Nov. 29, 2005 #ifdef JACKY_DEBUG jacky_os << "[~~PORT~~] reset flag in ActualValue to FALSE!!!! ~~~~~~~~~~~~~" << endl << flush; #endif //4> update RA = A for this new time recordActualVal() = actualMap(); // [2006-01-16] // At the beginning of any given simulated time, F should be equal to A // We can check this here if we want to make sure that F = A = RA is the case! #ifdef JACKY_DEBUG jacky_os << "\t IDCell::externalFunction() ---> TIME CHANGED !!!!!!!!!!!!!!!!" << endl << flush; jacky_os << "\t IDCell::externalFunction() After Update: " << endl << flush; jacky_os << "\t\t --- RT = " << getRecordTime().asString() << " / " << "RS = " << flush; if(getRecordState() == AtomicState::active){ jacky_os << "active" << endl << flush; } else { jacky_os << "passive" << endl << flush; } jacky_os << "\t\t --- Current ActualValues = " << flush; printValues(actualMap(), jacky_os); jacky_os << endl << "\t\t --- Current FutureValues = " << flush; printValues(futureMap(), jacky_os); jacky_os << endl << "\t\t --- RA = " << flush; printValues(recordActualVal(), jacky_os); jacky_os << 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] IDCell ROUND " << roundNum << ", save state variables, SV = " << recordStateVariables().asString() << endl << flush; #endif //end JACKY_DEBUG #endif //end JACKY_STATE_VAR ///////////////////////////////////////////////////////////////////////////////// #ifdef JACKY_IDCELL // [2006-01-16] ````````````````````````````````````````````````````````````` //set the "time change" flag to true timeChanged = true; //if the cell enters a new time with Active phase, records its delay here if ( state() == AtomicState::active ){ //Note: //original delay = lastChange() + nextChange() - msgs.time() //That is, the current delay (time to the next change) is the absoluteNext - currentTime //Time has elapsed for a period of [currentTime - lastChange()], and the time left is //lastChange() + nextChange() - currentTime VTime currentDelay = lastChange() + nextChange() - msgs.time(); setRecordDelay( currentDelay ); #ifdef JACKY_DEBUG jacky_os << "\t\tTime Change & Active! currentDelay = " << currentDelay.asString() << " -> set RD = " << currentDelay.asString() << endl << flush; #endif } #endif // end JACKY_IDCELL `````````````````````````````````````````````````````````````````````` } //end if time change else { //No time change happens, so these are the following rounds! #ifdef JACKY_IDCELL // [2006-01-16] ````````````````````````````````````````````````````````````` //set the "time change" flag to false timeChanged = false; #endif // end JACKY_IDCELL `````````````````````````````````````````````````````````````````````` #ifdef JACKY_DEBUG ++roundNum; //increase the number of the round #endif //end JACKY_DEBUG } #endif //end JACKY_SYNC ============================================================== //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() ) ; 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] IDCell: ROUND " << roundNum << " Restore state variables, V = " << cellStateVariables().asString() << endl << flush; #endif //end JACKY_DEBUG #endif //end JACKY_STATE_VAR ///////////////////////////////////////////////////////////////////////////////// list tv; ////////////////////////////////////////////////////////////////////// //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 (!isInNCPort(msg.port().name())) { MASSERTMSG( executedLocal == false, "Current implementation can not handle multiple messages from external models!!"); 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\tIDCell::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\tIDCell::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 }//for if ( !executedLocal ) { VirtualPortList *vpl = new VirtualPortList; getOutPorts(vpl); #ifdef JACKY_DEBUG jacky_os << "\t\tIDCell::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\tIDCell::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\tIDCell::externalFunction() BEFORE COMPARISON, [A] is ==========" << endl << flush; printValues( actualMap(), jacky_os ); #endif //cout << " Quantum : " << QuantumValue().value() << endl; //cout << " ActualValue : " << actualValue().value() << " with q " // << valueWithQuantum(actualValue(), QuantumValue()) << endl; //cout << " New value : " << tv << " with q " << valueWithQuantum(tv, QuantumValue()) << endl; list::iterator pvCursor; #ifdef JACKY_DEBUG //flags for debugging purpose int for_count = 0; bool valueChanged = false; #endif for (pvCursor = tv.begin(); pvCursor != tv.end(); pvCursor++) { string output_portname = calculateOutPort(pvCursor->first); #ifdef JACKY_DEBUG jacky_os << "\t\t***IDCell::externalFunction() for(" << for_count << ") NEW value: <" << pvCursor->first << "->[" << calculateOutPort( pvCursor->first ) << "] = " << (pvCursor->second).value() << ">" << endl << flush; jacky_os << "\t\t***IDCell::externalFunction() for(" << for_count << ") Actual value: <" << pvCursor->first << "->[" << calculateOutPort( pvCursor->first ) << "] = " << actualValue(output_portname).value() << flush; if( actualValueFlag(output_portname) == true ){ jacky_os << " / flag = TRUE> " << endl << flush; } else { jacky_os << " / flag = FALSE> " << endl << flush; } #endif //Nov. 29, 2005 //this condition is added to avoid offset results derived from external events //if NOT derived from event, we allow further changes // [2006-01-06] //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( actualValueFlag(output_portname) == false ){ #ifndef JACKY_REVISION //====================================================================================== if( ( UseQuantum().Active() || UseDynQuantum().Active() ) && ( valueWithQuantum(pvCursor->second, QuantumValue()) != valueWithQuantum(actualValue(pvCursor->first), QuantumValue()) ) || ( !UseQuantum().Active() && (actualValue(pvCursor->first) != pvCursor->second ) ) ) { //============================================================================================================= #else //This is Jacky's revision for translate the port name! EX: tv = should be translated to tv = if( ( UseQuantum().Active() || UseDynQuantum().Active() ) && ( valueWithQuantum(pvCursor->second, QuantumValue()) != valueWithQuantum(actualValue(output_portname), QuantumValue()) ) || ( !UseQuantum().Active() && (actualValue(output_portname) != pvCursor->second ) //Jacky: N != A ) ) { #endif //end JACKY_REVISION ==================================================================================== #ifdef JACKY_DEBUG jacky_os << "\t\t Value Changed (N != A) on port [" << pvCursor->first << "] ---------------------" << endl << flush; valueChanged = true; #endif if( isInputPort(pvCursor->first) ){ //the value is from input port from the environment //1> Jacky: set A = N with flag = true actualValue ( output_portname, pvCursor->second, true ); #ifdef JACKY_DEBUG jacky_os << "[~~PORT~~] set ActualValue : <" << output_portname << " = " << pvCursor->second.value() << " / flag = TRUE>" << endl << flush; #endif } else { //1> Jacky: set A = N with flag = false actualValue ( output_portname, pvCursor->second ); #ifdef JACKY_DEBUG jacky_os << "[~~PORT~~] set ActualValue : <" << output_portname << " = " << pvCursor->second.value() << " / flag = FALSE>" << endl << flush; #endif } //end update [ActualValue] => A = N #ifdef JACKY_DEBUG jacky_os << "\t\t 1> resulting A = < " << output_portname << " = " << actualValue(output_portname).value() << flush; if( actualValueFlag(output_portname) == true ){ jacky_os << " / flag = TRUE> " << endl << flush; } else { jacky_os << " / flag = FALSE> " << endl << flush; } #endif //2> Jacky: state change if( state() == AtomicState::passive ) { //a> Jacky: passive to active //This is in the document! holdIn( AtomicState::active, delay ) ; if( !timeChanged && (msgs.time() != VTime::Zero) ) { cerr << "Panic: passive => active, but No time change! At" << msgs.time().asString() << endl; } /* if( timeChanged ){ cerr << "\tTimeChange! P ==> A" << endl; } */ #ifdef JACKY_DEBUG jacky_os << "\t\t 2> Passive => Active, schedule output -> {" << (pvCursor->second).value() << "} @" << (msgs.time() + nextChange()).asString() << endl << flush; #endif } else { //Jacky: state() == AtomicState::active #ifdef JACKY_DEBUG jacky_os << "\t\t 3> isActive, current NEXT = " << nextChange().asString() << endl << flush; #endif #ifndef JACKY_SYNC //==================================================================================================== if( nextChange() > VTime::Zero && futureValue(pvCursor->first) != pvCursor->second) { holdIn( AtomicState::active, delay ) ; } //======================================================================================================================= #else //this is Jacky's revision for handling multi-round message passing in distributed simulation //[2006-01-16] // Now, we have the situation of: // (A = F = RA) && (N != A) && Active // We have set A = N, and we will set F = N, thus after this calculation, we have: // (A = F = N) && (N != RA) & Active #ifndef JACKY_IDCELL // [2006-01-16] ```````````````This version does not check "timeChanged"```````````````````````````` if( getRecordActual(output_portname) != pvCursor->second ) { // N != RA [==== CHANGE FURTHER ===] #ifdef JACKY_DEBUG jacky_os << "\t\t 4> Changed / Changed further! RA[<" << output_portname << " = " << getRecordActual(output_portname).value() << ">] != " << "N[<" << output_portname << " = " << (pvCursor->second).value() << ">]" << endl << flush; #endif //end JACKY_DEBUG //b> Jacky: active & preemption // the coupled sets sigma to the reminder time until //the next internal transition if( nextChange() > VTime::Zero && futureValue(output_portname) != pvCursor->second) { //Jacky: here is the preemption!!! //Jacky: if we need to change state later && the current future //value is different from the new value (it is also the current //actual value), then schedule the state change holdIn( AtomicState::active, delay ) ; #ifdef JACKY_DEBUG jacky_os << "\t\t 5> Preemption!!! isActive, NEXT > 0 && current F[" << futureValue(output_portname).value() << "] != N[" << (pvCursor->second).value() << "] ==> reset absoluteNext = " << (msgs.time() + nextChange()).asString() << endl << flush; #endif //end JACKY_DEBUG } //end preemption }//end change / change further else { // N == RA [==== CHANGE BACK ====] #ifdef JACKY_DEBUG jacky_os << "\t\t 6> Changed back! RA[<" << output_portname << " = " << getRecordActual(output_portname).value() << ">] == " << "N[<" << output_portname << " = " << (pvCursor->second).value() << ">]" << endl << flush; #endif //end JACKY_DEBUG //c> Jacky: active & changed back if (getRecordState() == AtomicState::passive) { //originally passive at RT //change back to passive passivate(); #ifdef JACKY_DEBUG jacky_os << "\t\t 7> Passivate again !!! NEXT = " << nextChange().asString() << endl << flush; #endif //end JACKY_DEBUG } //end change back to passive } //end change back #else // [2006-01-16] ``````````````````new version to check "timeChanged" ````````````````````````````````````````````` //we have to check the "timeChanged" flag //1. if there is a time change // -> we are entering a new multiple-round message passing for this new time // i.e. we enter these multiple rounds with (A = F = RA) & (RS = Active) // Thus, we will set A = F = N, and do preemption here! //2. if there is not a time change // -> we are entering round 1 ... round N for this time. // i.e. we enter the following rounds! Thus "change back" & "change further" // will happen here! // if ( timeChanged ) { //[2006-01-17] //Now, (N != A) & (A = F) & Active -> we have set A = N //So if current F = RA, we have the situation of (A = F = RA & N != A & Active) //do a state change based on the condition of (F = RA) if( futureValue(output_portname) == getRecordActual(output_portname) ){ //F = RA //2. there is a state change, do pre-emption if necessary //This is in the document! #ifdef JACKY_DEBUG jacky_os << "\t\t Change! Active => Active, RA[<" << output_portname << " = " << getRecordActual(output_portname).value() << ">] != " << "N[<" << output_portname << " = " << (pvCursor->second).value() << ">]" << endl << flush; #endif //end JACKY_DEBUG //active & preemption if( nextChange() > VTime::Zero && futureValue(output_portname) != pvCursor->second) { //before the time for the next output && F != N holdIn( AtomicState::active, delay ) ; cerr << "! active preemption" << endl; #ifdef JACKY_DEBUG jacky_os << "\t\t Preemption!!! isActive, NEXT > 0 && current F[" << futureValue(output_portname).value() << "] != N[" << (pvCursor->second).value() << "] ==> reset absoluteNext = " << (msgs.time() + nextChange()).asString() << endl << flush; #endif //end JACKY_DEBUG } //end preemption // [2006-01-16] //For this case, new time changed, N != A, A = F = RA, Active //We set A = F = N, and do preemption //Cell's new state is: A = F = N, N != RA, Active } else { //F != RA, do change back / further! //a) change further if timeChanged = false && N != RA //This is in the document! if( (!timeChanged) && //No time change (getRecordActual(output_portname) != pvCursor->second) ) { //N !=RA // N != RA [==== CHANGE FURTHER ====] cerr << "\tCF : " << msgs.time().asString() << endl; #ifdef JACKY_DEBUG jacky_os << "\t\t Changed further! RA[<" << output_portname << " = " << getRecordActual(output_portname).value() << ">] != " << "N[<" << output_portname << " = " << (pvCursor->second).value() << ">]" << endl << flush; #endif //end JACKY_DEBUG //active & preemption if( nextChange() > VTime::Zero && futureValue(output_portname) != pvCursor->second) { holdIn( AtomicState::active, delay ) ; #ifdef JACKY_DEBUG jacky_os << "\t\t Preemption!!! isActive, NEXT > 0 && current F[" << futureValue(output_portname).value() << "] != N[" << (pvCursor->second).value() << "] ==> reset absoluteNext = " << (msgs.time() + nextChange()).asString() << endl << flush; #endif //end JACKY_DEBUG } //end preemption }//end change further //b) change back if timeChanged = flase && N = RA else if ( !timeChanged ){ // N == RA [==== CHANGE BACK ====] //This is in the document! #ifdef JACKY_DEBUG jacky_os << "\t\t Changed back! RA[<" << output_portname << " = " << getRecordActual(output_portname).value() << ">] == " << "N[<" << output_portname << " = " << (pvCursor->second).value() << ">]" << endl << flush; #endif //end JACKY_DEBUG //c> active & changed back //This is in the document! if (getRecordState() == AtomicState::passive) { //i> originally passive at RT, change back to passive //Note: //Passivating the cell does 2 things: // 1. it set the cell's phase to passive, which is the phase // at the beginning of this time // i.e. restore the cell's phase to its original phase // 2. implicitly, this preempts the current scheduled output // i.e. preempt the current delay to infinity! //The 2nd thing is done implicitly! We have to restore the //cell's phase and its delay! passivate(); cerr << "\tCB (passive): "< reset absoluteNext = " << (msgs.time() + nextChange()).asString() << endl << flush; #endif //end JACKY_DEBUG } //end change back to active } // end change back } // [end path 4, 5, 6a, 6b] #endif // end JACKY_IDCELL ````````````````````````````````````````````````````````````````````````````````````````````` } //end state() == AtomicState::active #endif //end JACKY_SYNC =================================================================================================== #ifndef JACKY_REVISION //============================================================================================== futureValue( pvCursor->first, pvCursor->second); #else //Jacky's revision for translating the port ==================================================================== //3> Jacky: set F = N futureValue( output_portname, pvCursor->second); #endif //end JACKY_REVISION ========================================================================================= #ifdef JACKY_DEBUG jacky_os << "\t\t 8> set F = N = <" << output_portname << " = " << futureValue(output_portname).value() << flush; if( futureValueFlag(output_portname) == true ){ jacky_os << " / flag = TRUE> " << endl << flush; } else { jacky_os << " / flag = FALSE> " << endl << flush; } #endif } //end state change // [ ****************** 2006-01-06 *********************] // Note:If the external event does not cause cell's value changes, i.e. N = A // We still need to set the flag in the ActualValue 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 (A), 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 A 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 A 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 A to TRUE (but do NOT change the value in A) // if the tv is derived from an event. else { // N = A //This is in the document! [No State Change] if ( isInputPort(pvCursor->first) ) { // set the flag in A 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 // Since N = A, setting the value of A to N means "do not change the value of A"! actualValue ( output_portname, pvCursor->second, true ); } } } //end "result-NOT-derived-from-external-events" actualValueFlag on port is false else { //Mov. 29, 2005 // If the flag in A is 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 } #ifdef JACKY_DEBUG if(!valueChanged){ jacky_os << "\t\t No Value changes on ALL port!-------------" << 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 #ifndef JACKY_REVISION //================================================================================================= if ( valueWithQuantum(pvCursor->second,QuantumValue()) == valueWithQuantum(actualValue(pvCursor->first), QuantumValue())) { 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 { if ( !UseDynQuantum().Strat() ) QuantumValue ( QuantumValue() * (1-UseDynQuantum().Ratio())); else QuantumValue ( QuantumValue() * (1+UseDynQuantum().Ratio())); } //======================================================================================================================== #else //this is Jacky's revision for translating the input port to output port! if ( valueWithQuantum(pvCursor->second,QuantumValue()) == valueWithQuantum(actualValue(output_portname), QuantumValue())) { //Jacky: quantized new value = quantized actual value 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 { if ( !UseDynQuantum().Strat() ) QuantumValue ( QuantumValue() * (1-UseDynQuantum().Ratio())); else QuantumValue ( QuantumValue() * (1+UseDynQuantum().Ratio())); } #endif //end JACKY_REVISION //cout << " q act = " << QuantumValue().value() << endl; } //end using-quantum } // for return *this ; } #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /******************************************************************* * Method: outputFunction ********************************************************************/ Model &InertialDelayCell::outputFunction( const CollectMessage &msg ) { #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "\t-------->IDCell::outputFunction() called" << endl << flush; jacky_os << "\t\t --- Current ActualValues @ (" << msg.time().asString() << ") = " << flush; printValues(actualMap(), jacky_os); jacky_os << endl << "\t\t --- Current FutureValues @ (" << msg.time().asString() << ") = " << flush; printValues(futureMap(), jacky_os); jacky_os << endl << "\t\t --- RA for RT (" << getRecordTime().asString() << ") = " << flush; printValues(recordActualVal(), jacky_os); jacky_os << endl << "\t\t --- RS for RT (" << getRecordTime().asString() << ") = " << flush; if(getRecordState() == AtomicState::active){ jacky_os << "active" << endl << flush; } else { jacky_os << "passive" << endl << flush; } #endif PortList::iterator cursor; for (cursor = outNCPortList().begin(); cursor != outNCPortList().end(); cursor++) { string out_port(cursor->second->name()); #ifndef JACKY_REVISION //============================================================================================= string in_port(calculateInPort(out_port)); /* #ifdef JACKY_DEBUG jacky_os << "\t\t\t in_port = " << in_port << " / actualValue(in_port) = " << actualValue(in_port).value() << endl << flush; #endif */ //Jacky: There is a bug here! // Initially, the actualValue and futureValue are pair < out_port, value_of_CalculateInPort_out_port > // i.e. the key of the map is "out_port" ! // In the following send(), it tries to get the actualValue using key = "in_port". Since "in_port" does // Not exist in the map, this inserts a NEW pair into the map with value Real(), which is -0.5657XX. sendOutput( msg.time(), outputPort(out_port), actualValue(in_port).value() ); #else // Jacky's revision to fix the bug ============================================================================= #ifdef JACKY_DEBUG jacky_os << "\t\t => send output <" << msg.time().asString() << " / " << outputPort(out_port).name() << " = " << actualValue(out_port).value() << ">" << endl << flush; #endif //end JACKY_DEBUG sendOutput( msg.time(), outputPort(out_port), actualValue(out_port).value() ); #endif //end JACKY_REVISION ========================================================================================== } return *this; } /******************************************************************* * Method: internalFunction ********************************************************************/ Model &InertialDelayCell::internalFunction( const InternalMessage &msg ) { passivate(); #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "\t-------->IDCell::internalFunction() called, Passivate()! nextChange = " << nextChange().asString() << endl << flush; #endif return *this; } #ifdef JACKY_DEBUG //====================================================================== /******************************************************************* * Method: printValues *Description: function for printing the content of the actualValue, * futureValue, and recordActual ********************************************************************/ void InertialDelayCell::printValues(const IDCellState::StateValues &toPrint , ostream &out) const{ IDCellState::StateValues::const_iterator it; for(it = toPrint.begin(); it != toPrint.end(); it++){ #ifndef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^^^^^^ Previous Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out << "< " << it->first << " = " << (it->second).value() << " > " << flush; #else // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jacky's New Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out << "< " << it->first //portName << " = " << (it->second).first.value() //portValue << " / flag = " << flush; if( (it->second).second == true){ //event flag out << "TRUE > " << flush; } else { out << "FALSE > " << flush; } #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } } #endif //end JACKY_DEBUG =================================================================== #ifdef JACKY_PORTIN_FIRST // Nov. 29, 2005 ^^^^^^^^^ Previous Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /******************************************************************* * Method: resetValueFlags *Description: reset all flags accociated with values of the given MAP (A/F/RA) to FALSE ********************************************************************/ void InertialDelayCell::resetValueFlags( IDCellState::StateValues &values ){ IDCellState::StateValues::iterator it; for(it = values.begin(); it != values.end(); it++){ (it->second).second = false; } } #endif // end JACKY_PORTIN_FIRST ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^