#ifdef SYSTEMC
/*
 * $Id: Commit_unit_genMoore.cpp 100 2009-01-08 13:06:27Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Commit_unit/include/Commit_unit.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace commit_unit {


#undef  FUNCTION
#define FUNCTION "Commit_unit::genMoore"
  void Commit_unit::genMoore (void)
  {
    log_begin(Commit_unit,FUNCTION);
    log_function(Commit_unit,FUNCTION,_name.c_str());

    // ===================================================================
    // =====[ REEXECUTE ]=================================================
    // ===================================================================
    {
      // Store instruction comming Out Of Order in Load Store Unit. 
      // Must be executed in no speculative mode. Also, send a signal when an Store is in head of ROB

      Tcontrol_t val = false;

      if (not _rob[reg_NUM_BANK_HEAD].empty())
	{
	  entry_t    * entry = _rob [reg_NUM_BANK_HEAD].front();
	  rob_state_t  state = entry->state;

          // Test state
	  val   = ((state == ROB_STORE_HEAD_OK) or
		   (state == ROB_STORE_HEAD_KO));
	  
	  if (val)
	    {
              // Reexecute store
	      if (_param->_have_port_context_id)
  	      PORT_WRITE(out_REEXECUTE_CONTEXT_ID            [0], entry->context_id           );
	      if (_param->_have_port_front_end_id)
  	      PORT_WRITE(out_REEXECUTE_FRONT_END_ID          [0], entry->front_end_id         );
	      if (_param->_have_port_rob_ptr  )
  	      PORT_WRITE(out_REEXECUTE_PACKET_ID             [0], entry->ptr                  );
	      PORT_WRITE(out_REEXECUTE_TYPE                  [0], entry->type                 );
	      PORT_WRITE(out_REEXECUTE_STORE_QUEUE_PTR_WRITE [0], entry->store_queue_ptr_write);
	      PORT_WRITE(out_REEXECUTE_OPERATION             [0], (state == ROB_STORE_HEAD_OK)?OPERATION_MEMORY_STORE_HEAD_OK:OPERATION_MEMORY_STORE_HEAD_KO);
	    }
	}
 
      internal_REEXECUTE_VAL      [0] = val;
      internal_REEXECUTE_NUM_BANK [0] = reg_NUM_BANK_HEAD;
      
      PORT_WRITE(out_REEXECUTE_VAL[0], internal_REEXECUTE_VAL [0]);
    }

    // ===================================================================
    // =====[ BRANCH_COMPLETE ]===========================================
    // ===================================================================
    {
      // Branchement must be send at the prediction unit
      uint32_t nb_scan_bank = 0;

      // for each port, find a valid branchement.
      for (uint32_t i=0; i<_param->_nb_inst_branch_complete; i++)
	{
	  Tcontrol_t  val  = false;
	  
	  for (uint32_t j=nb_scan_bank; j<_param->_nb_bank; j++)
	    {
	      nb_scan_bank ++;

              // translate bank number
	      uint32_t num_bank = (reg_NUM_BANK_HEAD+j)%_param->_nb_bank;
	      
	      if (not _rob [num_bank].empty())
		{
		  entry_t    * entry    = _rob [num_bank].front();
		  rob_state_t  state    = entry->state;
		  
		  if (state == ROB_BRANCH_COMPLETE)
		    {
		      val = true;
		      
		      internal_BRANCH_COMPLETE_NUM_BANK           [i] = num_bank;
		      
		      if (_param->_have_port_context_id)
		      PORT_WRITE(out_BRANCH_COMPLETE_CONTEXT_ID   [i], entry->context_id      );
		      if (_param->_have_port_front_end_id)
		      PORT_WRITE(out_BRANCH_COMPLETE_FRONT_END_ID [i], entry->front_end_id    );
		      if (_param->_have_port_depth)
		      PORT_WRITE(out_BRANCH_COMPLETE_DEPTH        [i], entry->depth           );
		      PORT_WRITE(out_BRANCH_COMPLETE_ADDRESS      [i], entry->data_commit     );
// 		      PORT_WRITE(out_BRANCH_COMPLETE_FLAG         [i],(entry->flags&FLAG_F)!=0);
		      PORT_WRITE(out_BRANCH_COMPLETE_NO_SEQUENCE  [i], entry->no_sequence     );
		      
		      break;
		    }
		}
	    }

	  internal_BRANCH_COMPLETE_VAL [i] = val;
	  PORT_WRITE(out_BRANCH_COMPLETE_VAL [i], internal_BRANCH_COMPLETE_VAL [i]);
	}
    }

    // ===================================================================
    // =====[ UPDATE ]====================================================
    // ===================================================================
    {
      Tcontrol_t val = false;

      if (not _rob[reg_NUM_BANK_HEAD].empty())
	{
	  entry_t    * entry = _rob [reg_NUM_BANK_HEAD].front();
	  rob_state_t  state = entry->state;

	  val   = (state == ROB_END_EXCEPTION);
	  
	  if (val)
	    {
	      throw ERRORMORPHEO(FUNCTION,_("Moore : exception is not yet supported (Coming Soon).\n"));
	    }
	}
    }
 
    // ===================================================================
    // =====[ NB_INST ]===================================================
    // ===================================================================
    for (uint32_t i=0; i<_param->_nb_front_end; i++)
      for (uint32_t j=0; j<_param->_nb_context [i]; j++)
	{
	  PORT_WRITE(out_NB_INST_COMMIT_ALL [i][j], reg_NB_INST_COMMIT_ALL [i][j]);
	  PORT_WRITE(out_NB_INST_COMMIT_MEM [i][j], reg_NB_INST_COMMIT_MEM [i][j]);
	}


    log_end(Commit_unit,FUNCTION);
  };

}; // end namespace commit_unit
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core
}; // end namespace behavioural
}; // end namespace morpheo              
#endif
