From 4de80a1b6c5a5abdb241c97481dd72f18240d3a9 Mon Sep 17 00:00:00 2001
From: Daniel Knorreck <daniel.knorreck@telecom-paristech.fr>
Date: Thu, 23 Jul 2009 10:01:44 +0000
Subject: [PATCH] extended listener functionality (task start, task end,
 command start,...)

---
 .../c++2/src_simulator/ChannelListener.h      | 70 ++++++++++++++++++
 .../c++2/src_simulator/CommandListener.h      |  9 ++-
 .../c++2/src_simulator/ListenersSimCmd.cpp    | 48 ++++++++++++
 .../c++2/src_simulator/ListenersSimCmd.h      | 44 +++++++++++
 simulators/c++2/src_simulator/Simulator.cpp   | 21 +++---
 simulators/c++2/src_simulator/TMLChannel.h    |  4 +-
 simulators/c++2/src_simulator/TMLCommand.cpp  | 30 ++++----
 simulators/c++2/src_simulator/TMLCommand.h    |  6 +-
 .../c++2/src_simulator/TMLStopCommand.cpp     |  1 +
 simulators/c++2/src_simulator/TMLTask.cpp     | 15 +++-
 simulators/c++2/src_simulator/TMLTask.h       |  5 +-
 .../c++2/src_simulator/TMLTransaction.cpp     |  2 +
 .../c++2/src_simulator/TMLWaitCommand.cpp     |  1 +
 simulators/c++2/src_simulator/TaskListener.h  | 73 +++++++++++++++++++
 .../c++2/src_simulator/TransactionListener.h  |  2 -
 simulators/c++2/src_simulator/definitions.h   |  1 +
 16 files changed, 296 insertions(+), 36 deletions(-)
 create mode 100644 simulators/c++2/src_simulator/ChannelListener.h
 create mode 100644 simulators/c++2/src_simulator/TaskListener.h

diff --git a/simulators/c++2/src_simulator/ChannelListener.h b/simulators/c++2/src_simulator/ChannelListener.h
new file mode 100644
index 0000000000..1a58455849
--- /dev/null
+++ b/simulators/c++2/src_simulator/ChannelListener.h
@@ -0,0 +1,70 @@
+/*Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Daniel Knorreck,
+Ludovic Apvrille, Renaud Pacalet
+ *
+ * ludovic.apvrille AT telecom-paristech.fr
+ *
+ * This software is a computer program whose purpose is to allow the
+ * edition of TURTLE analysis, design and deployment diagrams, to
+ * allow the generation of RT-LOTOS or Java code from this diagram,
+ * and at last to allow the analysis of formal validation traces
+ * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP
+ * from INRIA Rhone-Alpes.
+ *
+ * This software is governed by the CeCILL  license under French law and
+ * abiding by the rules of distribution of free software.  You can  use,
+ * modify and/ or redistribute the software under the terms of the CeCILL
+ * license as circulated by CEA, CNRS and INRIA at the following URL
+ * "http://www.cecill.info".
+ *
+ * As a counterpart to the access to the source code and  rights to copy,
+ * modify and redistribute granted by the license, users are provided only
+ * with a limited warranty  and the software's author,  the holder of the
+ * economic rights,  and the successive licensors  have only  limited
+ * liability.
+ *
+ * In this respect, the user's attention is drawn to the risks associated
+ * with loading,  using,  modifying and/or developing or reproducing the
+ * software by the user in light of its specific status of free software,
+ * that may mean  that it is complicated to manipulate,  and  that  also
+ * therefore means  that it is reserved for developers  and  experienced
+ * professionals having in-depth computer knowledge. Users are therefore
+ * encouraged to load and test the software's suitability as regards their
+ * requirements in conditions enabling the security of their systems and/or
+ * data to be ensured and,  more generally, to use and operate it in the
+ * same conditions as regards security.
+ *
+ * The fact that you are presently reading this means that you have had
+ * knowledge of the CeCILL license and that you accept its terms.
+ *
+ */
+
+#ifndef ChannelListenerH
+#define ChannelListenerH
+#define NOTIFY_WRITE_TRANS_EXECUTED(iTrans) for(std::list<ChannelListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) {(*i)->transExecuted(iTrans);(*i)->writeTrans(iTrans);}
+#define NOTIFY_READ_TRANS_EXECUTED(iTrans) for(std::list<ChannelListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) {(*i)->transExecuted(iTrans);(*i)->readTrans(iTrans);}
+
+///Encapsulates events associated with commands
+class ChannelListener{
+public:
+	///Gets called when a transaction is executed
+	/**
+	\param  iTrans Pointer to the transaction
+	\return true if simulation is stopped
+	*/
+	virtual bool transExecuted(TMLTransaction* iTrans){return false;}
+	///Gets called when a read transaction is executed
+	/**
+	\param  iTrans Pointer to the transaction
+	\return true if simulation is stopped
+	*/
+	virtual bool readTrans(TMLTransaction* iTrans){return false;}
+	///Gets called when a write transaction is executed
+	/**
+	\param  iTrans Pointer to the transaction
+	\return true if simulation is stopped
+	*/
+	virtual bool writeTrans(TMLTransaction* iTrans){return false;}
+	virtual ~ChannelListener(){}
+protected:
+};
+#endif
diff --git a/simulators/c++2/src_simulator/CommandListener.h b/simulators/c++2/src_simulator/CommandListener.h
index 1fb07de9bd..565eb90525 100644
--- a/simulators/c++2/src_simulator/CommandListener.h
+++ b/simulators/c++2/src_simulator/CommandListener.h
@@ -40,10 +40,11 @@ Ludovic Apvrille, Renaud Pacalet
 
 #ifndef CommandListenerH
 #define CommandListenerH
-//#define FOR_EACH_CMDLISTENER for(std::list<CommandListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i)
 #define NOTIFY_CMD_ENTERED(iComm) for(std::list<CommandListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->commandEntered(iComm)
 #define NOTIFY_CMD_EXECUTED(iComm) for(std::list<CommandListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->commandExecuted(iComm)
 #define NOTIFY_CMD_FINISHED(iComm) for(std::list<CommandListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->commandFinished(iComm)
+#define NOTIFY_CMD_STARTED(iComm) for(std::list<CommandListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->commandStarted(iComm)
+
 
 ///Encapsulates events associated with commands
 class CommandListener{
@@ -66,6 +67,12 @@ public:
 	\return true if simulation is stopped
 	*/
 	virtual bool commandFinished(TMLCommand* iComm){return false;}
+	///Gets called when a the first transaction of the command is executed
+	/**
+	\param  iComm Pointer to the command
+	\return true if simulation is stopped
+	*/
+	virtual bool commandStarted(TMLCommand* iComm){return false;}
 	///Destructor
 	virtual ~CommandListener(){}
 protected:
diff --git a/simulators/c++2/src_simulator/ListenersSimCmd.cpp b/simulators/c++2/src_simulator/ListenersSimCmd.cpp
index 24a086f51b..9cad901f92 100644
--- a/simulators/c++2/src_simulator/ListenersSimCmd.cpp
+++ b/simulators/c++2/src_simulator/ListenersSimCmd.cpp
@@ -298,6 +298,54 @@ bool RunTillTransOnTask::transExecuted(TMLTransaction* iTrans){
 }
 
 
+//************************************************************************
+RunTillTransOnChannel::RunTillTransOnChannel(SimComponents* iSimComp, ListenerSubject<ChannelListener>* iSubject):_simComp(iSimComp), _subject(iSubject) {
+	_subject->registerListener(this);
+}
+
+RunTillTransOnChannel::~RunTillTransOnChannel(){
+	_subject->removeListener(this);
+}
+
+bool RunTillTransOnChannel::transExecuted(TMLTransaction* iTrans){
+	//_simComp->setStopFlag(true);
+	_simComp->setStopFlag(true, MSG_TRANSONDEVICE);
+	return true;
+}
+
+
+//************************************************************************
+TestListener::TestListener(SimComponents* iSimComp):_simComp(iSimComp){
+}
+
+bool TestListener::taskStarted(TMLTransaction* iTrans){
+	std::cout << "Task started\n";
+}
+
+bool TestListener::taskFinished(TMLTransaction* iTrans){
+	std::cout << "Task finished\n";
+}
+
+bool TestListener::readTrans(TMLTransaction* iTrans){
+	std::cout << "readTrans\n";
+}
+
+bool TestListener::writeTrans(TMLTransaction* iTrans){
+	std::cout << "write Trans\n";
+}
+
+bool TestListener::commandFinished(TMLCommand* iComm){
+	std::cout << "command started\n";
+}
+
+bool TestListener::commandStarted(TMLCommand* iComm){
+	std::cout << "command finished\n";
+}
+
+TestListener::~TestListener(){
+}
+
+
 //************************************************************************
 ConstraintBlock::ConstraintBlock(SimComponents* iSimComp):_simComp(iSimComp){
 }
diff --git a/simulators/c++2/src_simulator/ListenersSimCmd.h b/simulators/c++2/src_simulator/ListenersSimCmd.h
index 5c5af3c7be..f197be5780 100644
--- a/simulators/c++2/src_simulator/ListenersSimCmd.h
+++ b/simulators/c++2/src_simulator/ListenersSimCmd.h
@@ -283,6 +283,50 @@ protected:
 };
 
 
+//************************************************************************
+///Listener which stops the simulation as soon data is conveyed on a given channel
+class RunTillTransOnChannel: public ChannelListener{
+public:
+	///Constructor
+	/**
+	\param iSimComp Pointer to a SimComponents object
+	\param iSubject Channel to listen on
+	*/
+	RunTillTransOnChannel(SimComponents* iSimComp, ListenerSubject<ChannelListener>* iSubject);
+	///Destructor
+	virtual ~RunTillTransOnChannel();
+	bool transExecuted(TMLTransaction* iTrans);
+protected:
+	///Pointer to a SimComponents object
+	SimComponents* _simComp;
+	///Channel to listen on
+	ListenerSubject <ChannelListener> * _subject;
+};
+
+
+//************************************************************************
+class TestListener: public TaskListener, public ChannelListener, public CommandListener{
+public:
+	///Constructor
+	/**
+	\param iSimComp Pointer to a SimComponents object
+	*/
+	TestListener(SimComponents* iSimComp);
+	bool taskStarted(TMLTransaction* iTrans);
+	bool taskFinished(TMLTransaction* iTrans);
+	bool readTrans(TMLTransaction* iTrans);
+	bool writeTrans(TMLTransaction* iTrans);
+	bool commandFinished(TMLCommand* iComm);
+	bool commandStarted(TMLCommand* iComm);
+	///Destructor
+	virtual ~TestListener();
+	
+protected:
+	///Pointer to a SimComponents object
+	SimComponents* _simComp;
+};
+
+
 //************************************************************************
 class ConstraintBlock: public TransactionListener{
 	ConstraintBlock(SimComponents* iSimComp);
diff --git a/simulators/c++2/src_simulator/Simulator.cpp b/simulators/c++2/src_simulator/Simulator.cpp
index 3c20367a2c..c96134eab6 100644
--- a/simulators/c++2/src_simulator/Simulator.cpp
+++ b/simulators/c++2/src_simulator/Simulator.cpp
@@ -42,12 +42,6 @@ Ludovic Apvrille, Renaud Pacalet
 #include <Server.h>
 #include <ServerLocal.h>
 #include <TMLSelectCommand.h>
-//#include <BusAbstr.h>
-//#include <CPUAbstr.h>
-//#include <ChannelAbstr.h>
-//#include <TaskAbstr.h>
-//#include <CommandAbstr.h>
-//#include <TransactionAbstr.h>
 
 Simulator::Simulator(SimServSyncInfo* iSyncInfo):_syncInfo(iSyncInfo), _simComp(iSyncInfo->_simComponents), _busy(false), _simTerm(false), _leafsID(0), _randChoiceBreak(iSyncInfo->_simComponents) {}
 
@@ -974,7 +968,16 @@ void Simulator::printVariablesOfTask(TMLTask* iTask, std::ostream& ioMessage){
 }
 
 bool Simulator::runToNextBreakpoint(TMLTransaction*& oLastTrans){
-	return simulate(oLastTrans);
+	//TestListener myListener(_simComp);
+	//_simComp->getTaskByName("DIPLODOCUSDesign__TMLTask_0")->registerListener(&myListener);
+	//_simComp->getChannelByName("DIPLODOCUSDesign__evt")->registerListener(&myListener);
+	//_simComp->getTaskByName("DIPLODOCUSDesign__TMLTask_0")->getCommandByID(17)->registerListener(&myListener);
+	//bool erg=simulate(oLastTrans);
+	 return simulate(oLastTrans);
+	//_simComp->getTaskByName("DIPLODOCUSDesign__TMLTask_0")->removeListener(&myListener);
+	//_simComp->getChannelByName("DIPLODOCUSDesign__evt")->removeListener(&myListener);
+	//_simComp->getTaskByName("DIPLODOCUSDesign__TMLTask_0")->getCommandByID(17)->removeListener(&myListener);
+	//return erg;
 }
 
 bool Simulator::runXTransactions(unsigned int iTrans, TMLTransaction*& oLastTrans){
@@ -1022,8 +1025,8 @@ bool Simulator::runToSlaveTrans(Slave* iSlave, TMLTransaction*& oLastTrans){
 }
 
 bool Simulator::runToChannelTrans(TMLChannel* iChannel, TMLTransaction*& oLastTrans){
-	ListenerSubject<TransactionListener>* aSubject= static_cast<ListenerSubject<TransactionListener>* > (iChannel);
-	RunTillTransOnDevice aListener(_simComp, aSubject);
+	ListenerSubject<ChannelListener>* aSubject= static_cast<ListenerSubject<ChannelListener>* > (iChannel);
+	RunTillTransOnChannel aListener(_simComp, aSubject);
 	return simulate(oLastTrans);
 }
 
diff --git a/simulators/c++2/src_simulator/TMLChannel.h b/simulators/c++2/src_simulator/TMLChannel.h
index 3b52beea3c..98d91549a4 100644
--- a/simulators/c++2/src_simulator/TMLChannel.h
+++ b/simulators/c++2/src_simulator/TMLChannel.h
@@ -46,7 +46,7 @@ Ludovic Apvrille, Renaud Pacalet
 #include <Slave.h>
 #include <Serializable.h>
 #include <ListenerSubject.h>
-#include <TransactionListener.h>
+#include <ChannelListener.h>
 
 class TMLTransaction;
 class TMLCommand;
@@ -54,7 +54,7 @@ class TMLTask;
 class Bus;
 
 ///This class defines the basic interfaces and functionalites of a TML channel. All specific channels are derived from this base class. A channel is able to convey data and events. 
-class TMLChannel: public Serializable, public ListenerSubject <TransactionListener> {
+class TMLChannel: public Serializable, public ListenerSubject <ChannelListener> {
 public:
 	///Constructor
     	/**
diff --git a/simulators/c++2/src_simulator/TMLCommand.cpp b/simulators/c++2/src_simulator/TMLCommand.cpp
index 0dc15c2be3..9e31d71cb2 100644
--- a/simulators/c++2/src_simulator/TMLCommand.cpp
+++ b/simulators/c++2/src_simulator/TMLCommand.cpp
@@ -53,7 +53,7 @@ Ludovic Apvrille, Renaud Pacalet
 std::list<TMLCommand*> TMLCommand::_instanceList;
 SimComponents* TMLCommand::_simComp=0;
 
-TMLCommand::TMLCommand(unsigned int iID, TMLTask* iTask, TMLLength iLength, ParamFuncPointer iParamFunc, unsigned int iNbOfNextCmds): _ID(iID), _length(iLength), _progress(0), _currTransaction(0), _task(iTask), _nextCommand(0), _paramFunc(iParamFunc), _nbOfNextCmds(iNbOfNextCmds), _breakpoint(0){
+TMLCommand::TMLCommand(unsigned int iID, TMLTask* iTask, TMLLength iLength, ParamFuncPointer iParamFunc, unsigned int iNbOfNextCmds): _ID(iID), _length(iLength), _progress(0), _currTransaction(0), _task(iTask), _nextCommand(0), _paramFunc(iParamFunc), _nbOfNextCmds(iNbOfNextCmds), _breakpoint(0), _justStarted(true){
 	_instanceList.push_back(this);
 	_task->addCommand(iID, this);
 }
@@ -72,8 +72,8 @@ TMLCommand* TMLCommand::prepare(bool iInit){
 	if(_length==_progress){
 		TMLCommand* aNextCommand;
 		//std::cout << "COMMAND FINISHED!!n";
-		//FOR_EACH_CMDLISTENER (*i)->commandFinished(this);
 		NOTIFY_CMD_FINISHED(this);
+		if (_justStarted) NOTIFY_CMD_STARTED(this);
 		_progress=0;
 		//std::cout << "Prepare command, get next command" << std::endl;
 		aNextCommand=getNextCommand();
@@ -87,33 +87,29 @@ TMLCommand* TMLCommand::prepare(bool iInit){
 		}
 	}else{
 		//std::cout << "Prepare next transaction beg " << _listeners.size() << std::endl;
-		//_simStopped=false;
 		if (iInit){
-			//_simStopped=false;
 			if (_currTransaction!=0) delete _currTransaction;
+			if (_progress==0) _justStarted=true;
 		}else{
-			//_simStopped=false;
-			if (_progress==0)
-				//FOR_EACH_CMDLISTENER _simStopped|= (*i)->commandEntered(this);
-				//FOR_EACH_CMDLISTENER (*i)->commandEntered(this);
+			if (_progress==0){
 				NOTIFY_CMD_ENTERED(this);
-			else
-				//FOR_EACH_CMDLISTENER _simStopped|= (*i)->commandExecuted(this);
-				//FOR_EACH_CMDLISTENER (*i)->commandExecuted(this);
+				_justStarted=true;
+			}else{
 				NOTIFY_CMD_EXECUTED(this);
+				if (_justStarted){
+					NOTIFY_CMD_STARTED(this);
+					_justStarted=false;
+				}
+			}
 			//std::cout << "Prepare next transaction" << std::endl;
-			//if (_simStopped){
-			//if (_simComp->getStopFlag()){
-			//	std::cout << "aSimStopped=true " << std::endl;
-			//	_task->setCurrCommand(this);
-			//	return this;  //for command which generates transactions this is returned anyway by prepareTransaction
-			//}
 		}
 		TMLCommand* result = prepareNextTransaction();
 		//if (_length==0) std::cout << "create trans with length 0: " << toString() << std::endl;
+#ifdef REGISTER_TRANS_AT_CPU 
 		if (_currTransaction!=0 && _currTransaction->getVirtualLength()!=0){
 			_task->getCPU()->registerTransaction(_currTransaction,0);
 		}
+#endif
 		return result;
 	}
 	return 0;
diff --git a/simulators/c++2/src_simulator/TMLCommand.h b/simulators/c++2/src_simulator/TMLCommand.h
index 2891b46d4e..fb7e0c5136 100644
--- a/simulators/c++2/src_simulator/TMLCommand.h
+++ b/simulators/c++2/src_simulator/TMLCommand.h
@@ -199,8 +199,10 @@ protected:
 	unsigned int _nbOfNextCmds;
 	///Breakpoint
 	CommandListener* _breakpoint;
-	///Indicates if the breakpoint of the command has stopped the simulation  
-	bool _simStopped;
+	/////Indicates if the breakpoint of the command has stopped the simulation  
+	//bool _simStopped;
+	///Is true until the first transaction of a task is executed
+	bool _justStarted;
 	///Determines the next command based on the _nextCommand array
 	/**
 	\return Pointer to the next command
diff --git a/simulators/c++2/src_simulator/TMLStopCommand.cpp b/simulators/c++2/src_simulator/TMLStopCommand.cpp
index 7879501bbf..13c233f672 100644
--- a/simulators/c++2/src_simulator/TMLStopCommand.cpp
+++ b/simulators/c++2/src_simulator/TMLStopCommand.cpp
@@ -48,6 +48,7 @@ void TMLStopCommand::execute(){
 }
 
 TMLCommand* TMLStopCommand::prepareNextTransaction(){
+	_task->finished();
 	return 0;
 }
 
diff --git a/simulators/c++2/src_simulator/TMLTask.cpp b/simulators/c++2/src_simulator/TMLTask.cpp
index 0d7343c652..150d01df11 100644
--- a/simulators/c++2/src_simulator/TMLTask.cpp
+++ b/simulators/c++2/src_simulator/TMLTask.cpp
@@ -43,7 +43,7 @@ Ludovic Apvrille, Renaud Pacalet
 #include <TMLStopCommand.h>
 #include <CPU.h>
 
-TMLTask::TMLTask(unsigned int iID, unsigned int iPriority, std::string iName, CPU* iCPU): _ID(iID), _name(iName), _priority(iPriority), _endLastTransaction(0), _currCommand(0), _firstCommand(0), _cpu(iCPU), _previousTransEndTime(0), _comment(0), _busyCycles(0), _CPUContentionDelay(0), _noCPUTransactions(0) {
+TMLTask::TMLTask(unsigned int iID, unsigned int iPriority, std::string iName, CPU* iCPU): _ID(iID), _name(iName), _priority(iPriority), _endLastTransaction(0), _currCommand(0), _firstCommand(0), _cpu(iCPU), _previousTransEndTime(0), _comment(0), _busyCycles(0), _CPUContentionDelay(0), _noCPUTransactions(0), _justStarted(true) {
 	//_myid=++_id;
 	_cpu->registerTask(this);
 #ifdef ADD_COMMENTS
@@ -121,6 +121,10 @@ void TMLTask::addTransaction(TMLTransaction* iTrans){
 	_busyCycles+=iTrans->getOperationLength();
 	//FOR_EACH_TASKLISTENER (*i)->transExecuted(iTrans);
 	NOTIFY_TASK_TRANS_EXECUTED(iTrans);
+	if (_justStarted){
+		NOTIFY_TASK_STARTED(iTrans);
+		_justStarted=false;	
+	}
 	if(iTrans->getChannel()==0){
 		_noCPUTransactions++;
 		_CPUContentionDelay+=iTrans->getStartTime()-iTrans->getRunnableTime();
@@ -229,6 +233,7 @@ std::istream& TMLTask::readObject(std::istream& s){
 		//_currCommand->prepare();
 	}
 	//std::cout << "End Read Object TMLTask " << _name << std::endl;
+	_justStarted=false;
 	return s;
 }
 
@@ -251,7 +256,8 @@ void TMLTask::reset(){
 	_transactList.clear();
 	_busyCycles=0;
 	_CPUContentionDelay=0;
-	_noCPUTransactions=0; 
+	_noCPUTransactions=0;
+	_justStarted=true;
 }
 
 ParamType* TMLTask::getVariableByName(std::string& iVarName ,bool& oIsId){
@@ -286,3 +292,8 @@ VariableLookUpTableID::const_iterator TMLTask::getVariableIteratorID(bool iEnd)
 VariableLookUpTableName::const_iterator TMLTask::getVariableIteratorName(bool iEnd) const{
 	return (iEnd)?_varLookUpName.end():_varLookUpName.begin();
 }
+
+void TMLTask::finished(){
+	_justStarted=true;
+	if (!_transactList.empty()) NOTIFY_TASK_FINISHED(_transactList.front());
+}
diff --git a/simulators/c++2/src_simulator/TMLTask.h b/simulators/c++2/src_simulator/TMLTask.h
index 6025a370d9..472ad1b2d2 100644
--- a/simulators/c++2/src_simulator/TMLTask.h
+++ b/simulators/c++2/src_simulator/TMLTask.h
@@ -174,7 +174,8 @@ public:
 	\return Const iterator for variable table
 	*/
 	VariableLookUpTableName::const_iterator getVariableIteratorName(bool iEnd) const;
-
+	///Is called when a stop command is encountered
+	void finished();
 protected:
 	///ID of the task
 	unsigned int _ID;
@@ -218,6 +219,8 @@ protected:
 	VariableLookUpTableID _varLookUpID;
 	///Hash table containing commands
 	CommandHashTab _commandHash;
+	///Is true until the first transaction of a task is executed
+	bool _justStarted;
 };
 
 #endif
diff --git a/simulators/c++2/src_simulator/TMLTransaction.cpp b/simulators/c++2/src_simulator/TMLTransaction.cpp
index 7018865c99..ee1560024e 100644
--- a/simulators/c++2/src_simulator/TMLTransaction.cpp
+++ b/simulators/c++2/src_simulator/TMLTransaction.cpp
@@ -62,7 +62,9 @@ void TMLTransaction::setRunnableTime(TMLTime iRunnableTime){
 	//	std::cout << "ERROR: runnable time set twice\n";
 	//}else{
 		//_runnableTimeSet=true;
+#ifdef REGISTER_TRANS_AT_CPU 
 	_command->getTask()->getCPU()->registerTransaction(this,0);
+#endif
 	//}
 }
 
diff --git a/simulators/c++2/src_simulator/TMLWaitCommand.cpp b/simulators/c++2/src_simulator/TMLWaitCommand.cpp
index 3f2700c650..f954ea0c35 100644
--- a/simulators/c++2/src_simulator/TMLWaitCommand.cpp
+++ b/simulators/c++2/src_simulator/TMLWaitCommand.cpp
@@ -61,6 +61,7 @@ void TMLWaitCommand::execute(){
 
 TMLCommand* TMLWaitCommand::prepareNextTransaction(){
 	//std::cout << "wait command length: " << _length  << "  progress: " << _progress << std::endl; 
+	if (_progress==0 && _channel->getRequestChannel()) _task->finished();
 	_currTransaction=new TMLTransaction(this, _length-_progress, _task->getEndLastTransaction(), _channel);
 	_channel->testRead(_currTransaction);
 	return this;
diff --git a/simulators/c++2/src_simulator/TaskListener.h b/simulators/c++2/src_simulator/TaskListener.h
new file mode 100644
index 0000000000..af56c29829
--- /dev/null
+++ b/simulators/c++2/src_simulator/TaskListener.h
@@ -0,0 +1,73 @@
+/*Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Daniel Knorreck,
+Ludovic Apvrille, Renaud Pacalet
+ *
+ * ludovic.apvrille AT telecom-paristech.fr
+ *
+ * This software is a computer program whose purpose is to allow the
+ * edition of TURTLE analysis, design and deployment diagrams, to
+ * allow the generation of RT-LOTOS or Java code from this diagram,
+ * and at last to allow the analysis of formal validation traces
+ * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP
+ * from INRIA Rhone-Alpes.
+ *
+ * This software is governed by the CeCILL  license under French law and
+ * abiding by the rules of distribution of free software.  You can  use,
+ * modify and/ or redistribute the software under the terms of the CeCILL
+ * license as circulated by CEA, CNRS and INRIA at the following URL
+ * "http://www.cecill.info".
+ *
+ * As a counterpart to the access to the source code and  rights to copy,
+ * modify and redistribute granted by the license, users are provided only
+ * with a limited warranty  and the software's author,  the holder of the
+ * economic rights,  and the successive licensors  have only  limited
+ * liability.
+ *
+ * In this respect, the user's attention is drawn to the risks associated
+ * with loading,  using,  modifying and/or developing or reproducing the
+ * software by the user in light of its specific status of free software,
+ * that may mean  that it is complicated to manipulate,  and  that  also
+ * therefore means  that it is reserved for developers  and  experienced
+ * professionals having in-depth computer knowledge. Users are therefore
+ * encouraged to load and test the software's suitability as regards their
+ * requirements in conditions enabling the security of their systems and/or
+ * data to be ensured and,  more generally, to use and operate it in the
+ * same conditions as regards security.
+ *
+ * The fact that you are presently reading this means that you have had
+ * knowledge of the CeCILL license and that you accept its terms.
+ *
+ */
+
+#ifndef TaskListenerH
+#define TaksListenerH
+#include <TransactionListener.h>
+#define NOTIFY_TASK_TRANS_EXECUTED(iTrans) for(std::list<TaskListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->transExecuted(iTrans)
+#define NOTIFY_TASK_FINISHED(iTrans) for(std::list<TaskListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->taskFinished(iTrans)
+#define NOTIFY_TASK_STARTED(iTrans) for(std::list<TaskListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->taskStarted(iTrans)
+
+///Encapsulates events associated with transactions
+class TaskListener{
+public:
+	///Gets called when a task executes its first transaction
+	/**
+	\param  iTrans Pointer to the transaction
+	\return true if simulation is stopped
+	*/
+	virtual bool taskStarted(TMLTransaction* iTrans){return false;}
+	///Gets called when a task executes its last transaction
+	/**
+	\param  iTrans Pointer to the transaction
+	\return true if simulation is stopped
+	*/
+	virtual	bool taskFinished(TMLTransaction* iTrans){return false;}
+	///Destructor
+	///Gets called when a transaction is executed
+	/**
+	\param  iTrans Pointer to the transaction
+	\return true if simulation is stopped
+	*/
+	virtual bool transExecuted(TMLTransaction* iTrans){return false;}
+	virtual ~TaskListener(){}
+protected:
+};
+#endif
diff --git a/simulators/c++2/src_simulator/TransactionListener.h b/simulators/c++2/src_simulator/TransactionListener.h
index aebf631681..1ce29ca2bd 100644
--- a/simulators/c++2/src_simulator/TransactionListener.h
+++ b/simulators/c++2/src_simulator/TransactionListener.h
@@ -42,8 +42,6 @@ Ludovic Apvrille, Renaud Pacalet
 #define TransactionListenerH
 //#define FOR_EACH_TRANSLISTENER for(std::list<TransactionListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i)
 #define NOTIFY_TRANS_EXECUTED(iTrans) for(std::list<TransactionListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->transExecuted(iTrans)
-#define NOTIFY_WRITE_TRANS_EXECUTED(iTrans) for(std::list<TransactionListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->transExecuted(iTrans)
-#define NOTIFY_READ_TRANS_EXECUTED(iTrans) for(std::list<TransactionListener*>::iterator i=_listeners.begin(); i != _listeners.end(); ++i) (*i)->transExecuted(iTrans)
 
 ///Encapsulates events associated with transactions
 class TransactionListener{
diff --git a/simulators/c++2/src_simulator/definitions.h b/simulators/c++2/src_simulator/definitions.h
index 2fa18d86b8..8371521b20 100644
--- a/simulators/c++2/src_simulator/definitions.h
+++ b/simulators/c++2/src_simulator/definitions.h
@@ -83,6 +83,7 @@ using std::max;
 #define PARAMETER_BLOCK_SIZE 1000
 #define ADD_COMMENTS
 #define NO_EVENTS_TO_LOAD 10
+#undef REGISTER_TRANS_AT_CPU 
 #define PORT "3490"
 #define BACKLOG 10
 #define VCD_PREFIX "b"
-- 
GitLab