#ifdef SYSTEMC
/*
 * $Id: Commit_unit_genMoore.cpp 88 2008-12-10 18:31:39Z 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 ]=================================================
    // ===================================================================
    {
      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_STORE_HEAD_OK) or
		   (state == ROB_STORE_HEAD_KO));
	  
	  if (val)
	    {
	      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 ]===========================================
    // ===================================================================
    {
      uint32_t nb_scan_bank = 0;

      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 ++;

	      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    );
		      
		      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"));
	    }
	}
    }

//   public    : SC_OUT(Tcontrol_t         )   * out_UPDATE_VAL                        ;
//   public    : SC_IN (Tcontrol_t         )   *  in_UPDATE_ACK                        ;
//   public    : SC_OUT(Tcontext_t         )   * out_UPDATE_CONTEXT_ID                 ;
//   public    : SC_OUT(Tcontext_t         )   * out_UPDATE_FRONT_END_ID               ;
//   public    : SC_OUT(Tdepth_t           )   * out_UPDATE_DEPTH                      ;
//   public    : SC_OUT(Tevent_type_t      )   * out_UPDATE_TYPE                       ;
//   public    : SC_OUT(Tcontrol_t         )   * out_UPDATE_IS_DELAY_SLOT              ;
//   public    : SC_OUT(Taddress_t         )   * out_UPDATE_ADDRESS                    ;
//   public    : SC_OUT(Taddress_t         )   * out_UPDATE_ADDRESS_EPCR               ;
//   public    : SC_OUT(Tcontrol_t         )   * out_UPDATE_ADDRESS_EEAR_VAL           ;
//   public    : SC_OUT(Taddress_t         )   * out_UPDATE_ADDRESS_EEAR               ;
 
    // ===================================================================
    // =====[ 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
