/******************************************************************* * * DESCRIPTION: definitions of messages ( Y, *, D, X, I )for the TimeWarp version * * AUTHOR: Alejandro Troccoli * * EMAIL: mailto://atroccol@dc.uba.ar * * DATE: 01/11/2000 * *******************************************************************/ #ifndef __PMESSAGE_H #define __PMESSAGE_H /** include files **/ #include "BasicEvent.hh" // TimeWarp BasicEvent class #include "message.h" // NCD++ Message. #include "value.h" #include "port.h" /** definitions **/ class TWMessage: public BasicEvent { public: //Proc Id of the sender ProcId procId; #ifdef JACKY_EVENT_JUMP //~~~~~~~~~~~~~~ Nov. 22, 2005 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //this flag is to distinguish those (X) messages derived from external events in the //NC's EventList from other ordinary (X) messages sending from other simulators bool TWExternalEventFlag; const bool &derivedFromExternalEvent() const { return TWExternalEventFlag; } #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //define the different message types enum TWMessageType { TWInitMsg, TWInternalMsg, TWDoneMsg, TWExternalMsg, TWOutputMsg, TWOutputSyncMsg, TWCollectMsg }; TWMessageType getMessageType(){ return msgType; } virtual Message* getMessage() = 0; virtual ~TWMessage(){} //Destructor #ifdef JACKY_LAZY_CANCELLATION //[2006-04-14] //Jacky Note: //This virtual function is defined in TimeWarpBasicEvent to compare the newly generated //output event with the event that have been sent out previously before rollbacks to //determine a Lazy Hit or a Lazy Miss //The TimeWarpBasicEvent::lazyCmp() function only compare 2 BasicEvents based on their: // 1. recvTime, 2. sendTime, 3. sender, 4. dest, and 5. sign //Here, we need to override that implementation to compare 2 messages with additional info. //In this TWMessage base class for all messages at the PCD++ level, we add: // 6. TWMessageType, 7. TWExternalEventFlag virtual bool lazyCmp(BasicEvent* target){ #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "**** TWMessage::lazyCmp() called! ****" << endl << flush; #endif //1. call base version in TimeWarpBasicEvent if( BasicEvent::lazyCmp(target) == false ){ return false; } else {// pass the BasicEvent version //cast the target to a TWMessage TWMessage* targetMsg = dynamic_cast(target); //2. compare TWMessageType & TWExternalEventFlag if( targetMsg != NULL && (targetMsg->getMessageType() == this->getMessageType()) && (targetMsg->derivedFromExternalEvent() == this->derivedFromExternalEvent()) ){ #ifdef JACKY_DEBUG jacky_os << "**** TWMessage::lazyCmp() return TRUE" << endl << flush; #endif return true; } else { return false; } } } #endif //end JACKY_LAZY_CANCELLATION [2006-04-14] protected: #ifndef JACKY_EVENT_JUMP //~~~~~~~~~~~~~~ Nov. 22, 2005 ~~~~~~~~~~~~~~~Original version~~~~~~ TWMessage( const Message &msg, const TWMessageType type): msgType(type) { procId = msg.procId(); recvTime = msg.time(); //size should be initialized in each subclass }; #else //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ New Version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWMessage( const Message &msg, const TWMessageType type): msgType(type) { procId = msg.procId(); recvTime = msg.time(); TWExternalEventFlag = msg.isEvent(); //Nov. 22, 2005 /* #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "CCCCCCCCCCCCCC create TWMessage, TWExternalEventFlag = " << TWExternalEventFlag << endl << flush; #endif */ //size should be initialized in each subclass }; #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private: TWMessageType msgType; }; // class TWMessage class TWInitMessage : public TWMessage { public: TWInitMessage( const InitMessage &msg ): TWMessage(msg, TWInitMsg){ size = sizeof(TWInitMessage); }; // constructor InitMessage* getMessage(); virtual ~TWInitMessage() //Destructor {} }; class TWInternalMessage : public TWMessage { public: TWInternalMessage( const InternalMessage &msg ): TWMessage(msg , TWInternalMsg) { size = sizeof(TWInternalMessage); }; // constructor virtual ~TWInternalMessage() //Destructor {} virtual InternalMessage* getMessage(); }; // class TWInternalMessage class TWOutputSyncMessage : public TWMessage { public: TWOutputSyncMessage( const OutputSyncMessage &msg ): TWMessage(msg , TWOutputSyncMsg) { size = sizeof(TWOutputSyncMessage); }; // constructor virtual ~TWOutputSyncMessage() //Destructor {} virtual OutputSyncMessage* getMessage(); }; // class TWOutputSyncMessage class TWCollectMessage : public TWMessage { public: TWCollectMessage( const CollectMessage &msg ): TWMessage(msg , TWCollectMsg) { size = sizeof(TWCollectMessage); }; // constructor virtual ~TWCollectMessage() //Destructor {} virtual CollectMessage* getMessage(); }; // class TWCollectMessage class TWDoneMessage : public TWMessage { public: TWDoneMessage( const DoneMessage &msg ): TWMessage(msg, TWDoneMsg) { nextChange = msg.nextChange() ; slaveSync = msg.isFromSlave() ; size = sizeof(TWDoneMessage); }; // constructor virtual ~TWDoneMessage() //Destructor {} virtual DoneMessage* getMessage(); #ifdef JACKY_LAZY_CANCELLATION //[2006-04-14] //Jacky Note: //Compare 2 (D) messages using two more attributes: // 8. nextChange, 9. slaveSync virtual bool lazyCmp(BasicEvent* target){ #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "**** TWDoneMessage::lazyCmp() called! ****" << endl << flush; #endif //1. call base version in TWMessage if( TWMessage::lazyCmp(target) == false ){ return false; } else {// pass the TWMessage version //cast the target to a TWDoneMessage TWDoneMessage* targetMsg = dynamic_cast(target); //2. compare nextChange & slaveSync if( targetMsg != NULL && (targetMsg->nextChange == this->nextChange) && (targetMsg->slaveSync == this->slaveSync) ){ #ifdef JACKY_DEBUG jacky_os << "**** TWDoneMessage::lazyCmp() return TRUE" << endl << flush; #endif return true; } else { return false; } } } #endif //end JACKY_LAZY_CANCELLATION [2006-04-14] private: VTime nextChange; bool slaveSync; }; // class TWDoneMessage //This class is here to guarantee that the memory copying in //TWExternalMessage will work correctly. class TWBasicExternalMessage : public TWMessage { public: TWBasicExternalMessage( const BasicExternalMessage &msg) : TWMessage( msg, TWExternalMsg ) { mid = msg.port().modelId(); p = msg.port().id(); sendermid = msg.senderModelId(); }; protected: ModelId mid; ModelId sendermid; PortId p; }; //class TWBasicExternalMessage class TWExternalMessage : public TWBasicExternalMessage, public BasicMsgValue { public: TWExternalMessage( const BasicExternalMessage &msg ) : TWBasicExternalMessage(msg) { size = sizeof(TWBasicExternalMessage) + msg.value()->valueSize(); //Dirty memory copying... memcpy((BasicMsgValue*)this, msg.value(), msg.value()->valueSize()); }; // constructor virtual ~TWExternalMessage() //Destructor {} virtual BasicExternalMessage* getMessage(); #ifdef JACKY_STATISTICS //[2006-04-25] //This function is to get the size of the messages transmitted between compute nodes static int getTWExternalMessageSize(){ return sizeof(TWExternalMessage); } #endif //end JACKY_STATISTICS //[2006-04-25] #ifdef JACKY_LAZY_CANCELLATION //[2006-04-14] //Jacky Note: //Compare 2 (X) messages using 3 more attributes: // 8. senderModelId, 9. destination port, and 10. value virtual bool lazyCmp(BasicEvent* target){ #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "**** TWExternalMessage::lazyCmp() called! ****" << endl << flush; #endif //1. call base version in TWMessage if( TWMessage::lazyCmp(target) == false ){ return false; } else {// pass the TWMessage version //cast it to TWExternalMessage TWExternalMessage* targetMsg = dynamic_cast(target); if( targetMsg != NULL ){ //this is a TWExternalMessage //get the associated BasicExternalMessage BasicExternalMessage* targetXMsg = targetMsg->getMessage(); //need delete! //get BasicExternalMessage from this BasicExternalMessage* thisXMsg = this->getMessage(); //need delete! //2. compare senderModelId, destination port id, and value if( (targetXMsg->senderModelId() == thisXMsg->senderModelId()) && ((targetXMsg->port()).id() == (thisXMsg->port()).id()) && (((RealMsgValue*)(targetXMsg->value()))->v == ((RealMsgValue*)(thisXMsg->value()))->v) ){ delete targetXMsg; delete thisXMsg; #ifdef JACKY_DEBUG jacky_os << "**** TWExternalMessage::lazyCmp() return TRUE" << endl << flush; #endif return true; } else { delete targetXMsg; delete thisXMsg; return false; } } else { //this is not a TWExternalMessage at all return false; } } } #endif //end JACKY_LAZY_CANCELLATION [2006-04-14] }; // class TWExternalMessage //TWOutputMessage will work correctly. class TWBasicOutputMessage : public TWMessage { public: TWBasicOutputMessage( const BasicOutputMessage &msg) : TWMessage( msg, TWOutputMsg ) { mid = msg.port().modelId(); p = msg.port().id(); }; protected: ModelId mid; PortId p; }; //class TWBasicOutputMessage class TWOutputMessage : public TWBasicOutputMessage, public BasicMsgValue { public: TWOutputMessage( const BasicOutputMessage &msg ) : TWBasicOutputMessage(msg) { size = sizeof(TWBasicOutputMessage) + msg.value()->valueSize(); //Dirty memory copying... memcpy((BasicMsgValue*)this, msg.value(), msg.value()->valueSize()); }; // constructor virtual ~TWOutputMessage() //Destructor {} virtual BasicOutputMessage* getMessage(); #ifdef JACKY_LAZY_CANCELLATION //[2006-04-14] //Jacky Note: //Compare 2 (X) messages using 3 more attributes: // 8. destination port, and 9. value virtual bool lazyCmp(BasicEvent* target){ #ifdef JACKY_DEBUG ostream& jacky_os = JackyDebugStream::Instance().Stream(); jacky_os << "**** TWOutputMessage::lazyCmp() called! ****" << endl << flush; #endif //1. call base version in TWMessage if( TWMessage::lazyCmp(target) == false ){ return false; } else {// pass the TWMessage version //cast it to TWOutputMessage TWOutputMessage* targetMsg = dynamic_cast(target); if( targetMsg != NULL ){ //this is a TWOutputMessage //get the associated BasicOutputMessage BasicOutputMessage* targetYMsg = targetMsg->getMessage(); //need delete! //get BasicOutputMessage from this BasicOutputMessage* thisYMsg = this->getMessage(); //need delete! //2. compare destination port id, and value if( ((targetYMsg->port()).id() == (thisYMsg->port()).id()) && (((RealMsgValue*)(targetYMsg->value()))->v == ((RealMsgValue*)(thisYMsg->value()))->v) ){ delete targetYMsg; delete thisYMsg; #ifdef JACKY_DEBUG jacky_os << "**** TWOutputMessage::lazyCmp() -> return TRUE" << endl << flush; #endif return true; } else { delete targetYMsg; delete thisYMsg; return false; } } else { //this is not a TWExternalMessage at all return false; } } } #endif //end JACKY_LAZY_CANCELLATION [2006-04-14] }; // class TWOutputMessage #endif //__PMESSAGE_H