#ifdef SYSTEMC
/*
 * $Id$
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Rename_unit/Register_translation_unit/Stat_List_unit/include/Stat_List_unit.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace rename_unit {
namespace register_translation_unit {
namespace stat_list_unit {


#undef  FUNCTION
#define FUNCTION "Stat_List_unit::transition"
  void Stat_List_unit::transition (void)
  {
    log_printf(FUNC,Stat_List_unit,FUNCTION,"Begin");

    if (PORT_READ(in_NRESET) == 0)
      {
	uint32_t gpr = 0;
	uint32_t spr = 0;
	
	for (uint32_t i=0; i<_param->_nb_bank; i++)
	  {
	    for (uint32_t j=0; j<_param->_nb_general_register_by_bank; j++)
	      gpr_stat_list [i][j].reset((gpr++)<_param->_nb_gpr_use_init);
	    for (uint32_t j=0; j<_param->_nb_special_register_by_bank; j++)
	      spr_stat_list [i][j].reset((spr++)<_param->_nb_spr_use_init);
	  }
	internal_GPR_PTR_FREE = 0;
	internal_SPR_PTR_FREE = 0;
      }
    else
      {
	// =====================================================
	// =====[ INSERT ]======================================
	// =====================================================
	for (uint32_t i=0; i<_param->_nb_inst_insert; i++)
	  if (PORT_READ(in_INSERT_VAL[i]) and internal_INSERT_ACK[i])
	    {
	      if (PORT_READ(in_INSERT_READ_RA [i]))
		{
		  Tgeneral_address_t num_reg = PORT_READ(in_INSERT_NUM_REG_RA_PHY [i]);
		  uint32_t bank = num_reg >> _param->_shift_gpr;
		  uint32_t reg  = num_reg  & _param->_mask_gpr ;
		  gpr_stat_list [bank][reg].insert_read();
		}

	      if (PORT_READ(in_INSERT_READ_RB [i]))
		{
		  Tgeneral_address_t num_reg = PORT_READ(in_INSERT_NUM_REG_RB_PHY [i]);
		  uint32_t bank = num_reg >> _param->_shift_gpr;
		  uint32_t reg  = num_reg  & _param->_mask_gpr ;
		  gpr_stat_list [bank][reg].insert_read();
		}

	      if (PORT_READ(in_INSERT_READ_RC [i]))
		{
		  Tgeneral_address_t num_reg = PORT_READ(in_INSERT_NUM_REG_RC_PHY [i]);
		  uint32_t bank = num_reg >> _param->_shift_spr;
		  uint32_t reg  = num_reg  & _param->_mask_spr ;
		  spr_stat_list [bank][reg].insert_read();
		}

	      if (PORT_READ(in_INSERT_WRITE_RD [i]))
		{
		  Tgeneral_address_t num_reg = PORT_READ(in_INSERT_NUM_REG_RD_PHY_NEW [i]);
		  uint32_t bank = num_reg >> _param->_shift_gpr;
		  uint32_t reg  = num_reg  & _param->_mask_gpr ;
		  gpr_stat_list [bank][reg].insert_write();
		}

	      if (PORT_READ(in_INSERT_WRITE_RE [i]))
		{
		  Tgeneral_address_t num_reg = PORT_READ(in_INSERT_NUM_REG_RE_PHY_NEW [i]);
		  uint32_t bank = num_reg >> _param->_shift_spr;
		  uint32_t reg  = num_reg  & _param->_mask_spr ;
		  spr_stat_list [bank][reg].insert_write();
		}
	    }

	// =====================================================
	// =====[ RETIRE ]======================================
	// =====================================================
	for (uint32_t i=0; i<_param->_nb_inst_retire; i++)
	  if (PORT_READ(in_RETIRE_VAL[i]) and internal_RETIRE_ACK[i])
	    {
	      if (PORT_READ(in_RETIRE_READ_RA [i]))
		{
		  Tgeneral_address_t num_reg = PORT_READ(in_RETIRE_NUM_REG_RA_PHY [i]);
		  uint32_t bank = num_reg >> _param->_shift_gpr;
		  uint32_t reg  = num_reg  & _param->_mask_gpr ;
		  gpr_stat_list [bank][reg].retire_read();
		}

	      if (PORT_READ(in_RETIRE_READ_RB [i]))
		{
		  Tgeneral_address_t num_reg = PORT_READ(in_RETIRE_NUM_REG_RB_PHY [i]);
		  uint32_t bank = num_reg >> _param->_shift_gpr;
		  uint32_t reg  = num_reg  & _param->_mask_gpr ;
		  gpr_stat_list [bank][reg].retire_read();
		}

	      if (PORT_READ(in_RETIRE_READ_RC [i]))
		{
		  Tgeneral_address_t num_reg = PORT_READ(in_RETIRE_NUM_REG_RC_PHY [i]);
		  uint32_t bank = num_reg >> _param->_shift_spr;
		  uint32_t reg  = num_reg  & _param->_mask_spr ;
		  spr_stat_list [bank][reg].retire_read();
		}

	      if (PORT_READ(in_RETIRE_WRITE_RD [i]))
		{
		  {
		    Tgeneral_address_t num_reg = PORT_READ(in_RETIRE_NUM_REG_RD_PHY_OLD [i]);
		    uint32_t bank = num_reg >> _param->_shift_gpr;
		    uint32_t reg  = num_reg  & _param->_mask_gpr ;
		    gpr_stat_list [bank][reg].retire_write_old();
		  }
		  {
		    Tgeneral_address_t num_reg = PORT_READ(in_RETIRE_NUM_REG_RD_PHY_NEW [i]);
		    uint32_t bank = num_reg >> _param->_shift_gpr;
		    uint32_t reg  = num_reg  & _param->_mask_gpr ;
		    gpr_stat_list [bank][reg].retire_write_new();
		  }
		}

	      if (PORT_READ(in_RETIRE_WRITE_RE [i]))
		{
		  {
		    Tgeneral_address_t num_reg = PORT_READ(in_RETIRE_NUM_REG_RE_PHY_OLD [i]);
		    uint32_t bank = num_reg >> _param->_shift_spr;
		    uint32_t reg  = num_reg  & _param->_mask_spr ;
		    spr_stat_list [bank][reg].retire_write_old();
		  }
		  {
		    Tgeneral_address_t num_reg = PORT_READ(in_RETIRE_NUM_REG_RE_PHY_NEW [i]);
		    uint32_t bank = num_reg >> _param->_shift_spr;
		    uint32_t reg  = num_reg  & _param->_mask_spr ;
		    spr_stat_list [bank][reg].retire_write_new();
		  }
		}
	    }

	for (uint32_t i=0; i<_param->_nb_reg_free; i++)
	  {
	    // =====================================================
	    // =====[ PUSH_GPR ]====================================
	    // =====================================================
	    if (internal_PUSH_GPR_VAL [i] and PORT_READ(in_PUSH_GPR_ACK [i]))
	      gpr_stat_list[internal_PUSH_GPR_NUM_BANK [i]][internal_GPR_PTR_FREE].free();
	    
	    // =====================================================
	    // =====[ PUSH_SPR ]====================================
	    // =====================================================
	    if (internal_PUSH_SPR_VAL [i] and PORT_READ(in_PUSH_SPR_ACK [i]))
	      spr_stat_list[internal_PUSH_SPR_NUM_BANK [i]][internal_SPR_PTR_FREE].free();
	  }

	// Update pointer
	internal_GPR_PTR_FREE = ((internal_GPR_PTR_FREE==0)?_param->_nb_general_register_by_bank:internal_GPR_PTR_FREE)-1;
	internal_SPR_PTR_FREE = ((internal_SPR_PTR_FREE==0)?_param->_nb_special_register_by_bank:internal_SPR_PTR_FREE)-1;
      }
    
//     log_printf(TRACE,Stat_List_unit,FUNCTION,"Print gpr_stat_list :");
//     for (uint32_t i=0; i<_param->_nb_bank; i++)
//       {
// 	log_printf(TRACE,Stat_List_unit,FUNCTION," * Bank : %d",i);
// 	for (uint32_t j=0; j<_param->_nb_general_register_by_bank; j++)
// 	  {
// 	    std::ostringstream str;
// 	    str << gpr_stat_list [i][j];
// 	    log_printf(TRACE,Stat_List_unit,FUNCTION,"   [%d] %s",j,str.str().c_str());

// 	  }
//       }
//     log_printf(TRACE,Stat_List_unit,FUNCTION,"Print spr_stat_list :");
//     for (uint32_t i=0; i<_param->_nb_bank; i++)
//       {
// 	log_printf(TRACE,Stat_List_unit,FUNCTION," * Bank : %d",i);
// 	for (uint32_t j=0; j<_param->_nb_special_register_by_bank; j++)
// 	  {
// 	    std::ostringstream str;
// 	    str << spr_stat_list [i][j];
// 	    log_printf(TRACE,Stat_List_unit,FUNCTION,"   [%d] %s",j,str.str().c_str());
// 	  }
//       }

#if defined(STATISTICS) or defined(VHDL_TESTBENCH)
    end_cycle ();
#endif

    log_printf(FUNC,Stat_List_unit,FUNCTION,"End");
  };

}; // end namespace stat_list_unit
}; // end namespace register_translation_unit
}; // end namespace rename_unit
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core

}; // end namespace behavioural
}; // end namespace morpheo              
#endif
