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

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

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


#undef  FUNCTION
#define FUNCTION "Dependency_checking_unit::genMealy"
  void Dependency_checking_unit::genMealy (void)
  {
    log_printf(FUNC,Dependency_checking_unit,FUNCTION,"Begin");

//     Tcontrol_t         val                [_param->_nb_inst_insert];
//     Tcontrol_t         ack                [_param->_nb_inst_insert];
    Tcontext_t         front_end_id       [_param->_nb_inst_insert];
    Tcontext_t         context_id         [_param->_nb_inst_insert];
    Tcontrol_t         read_ra            [_param->_nb_inst_insert];
    Tgeneral_address_t num_reg_ra_log     [_param->_nb_inst_insert];
    Tgeneral_address_t num_reg_ra_phy     [_param->_nb_inst_insert];
    Tcontrol_t         read_rb            [_param->_nb_inst_insert];
    Tgeneral_address_t num_reg_rb_log     [_param->_nb_inst_insert];
    Tgeneral_address_t num_reg_rb_phy     [_param->_nb_inst_insert];
    Tcontrol_t         read_rc            [_param->_nb_inst_insert];
    Tspecial_address_t num_reg_rc_log     [_param->_nb_inst_insert];
    Tspecial_address_t num_reg_rc_phy     [_param->_nb_inst_insert];
    Tcontrol_t         write_rd           [_param->_nb_inst_insert];
    Tgeneral_address_t num_reg_rd_log     [_param->_nb_inst_insert];
    Tgeneral_address_t num_reg_rd_phy_old [_param->_nb_inst_insert];
    Tgeneral_address_t num_reg_rd_phy_new [_param->_nb_inst_insert];
    Tcontrol_t         write_re           [_param->_nb_inst_insert];
    Tspecial_address_t num_reg_re_log     [_param->_nb_inst_insert];
    Tspecial_address_t num_reg_re_phy_old [_param->_nb_inst_insert];
    Tspecial_address_t num_reg_re_phy_new [_param->_nb_inst_insert];

    // 4 dependency :
    //  * Read  after Read  : it's a false dependency
    //  * Write after Read  : it's inhibt by rename process
    //  * Write after Write : for the num_reg_old
    //  * Read  after Write : dependency
    for (uint32_t i=0; i<_param->_nb_inst_insert; i++)
      {
 	// =====[ Input ]==================================================
// 	val                [i] = PORT_READ(in_RENAME_IN_VAL                [i]);
// 	ack                [i] = PORT_READ(in_RENAME_OUT_ACK               [i]);
	front_end_id       [i] = (_param->_have_port_front_end_id)?PORT_READ(in_RENAME_IN_FRONT_END_ID [i]):0;
	context_id         [i] = (_param->_have_port_context_id  )?PORT_READ(in_RENAME_IN_CONTEXT_ID   [i]):0;
	read_ra            [i] = PORT_READ(in_RENAME_IN_READ_RA            [i]);
	num_reg_ra_log     [i] = PORT_READ(in_RENAME_IN_NUM_REG_RA_LOG     [i]);
	num_reg_ra_phy     [i] = PORT_READ(in_RENAME_IN_NUM_REG_RA_PHY     [i]);
	read_rb            [i] = PORT_READ(in_RENAME_IN_READ_RB            [i]);
	num_reg_rb_log     [i] = PORT_READ(in_RENAME_IN_NUM_REG_RB_LOG     [i]);
	num_reg_rb_phy     [i] = PORT_READ(in_RENAME_IN_NUM_REG_RB_PHY     [i]);
	read_rc            [i] = PORT_READ(in_RENAME_IN_READ_RC            [i]);
	num_reg_rc_log     [i] = PORT_READ(in_RENAME_IN_NUM_REG_RC_LOG     [i]);
	num_reg_rc_phy     [i] = PORT_READ(in_RENAME_IN_NUM_REG_RC_PHY     [i]);
	write_rd           [i] = PORT_READ(in_RENAME_IN_WRITE_RD           [i]);
	num_reg_rd_log     [i] = PORT_READ(in_RENAME_IN_NUM_REG_RD_LOG     [i]);
	num_reg_rd_phy_old [i] = PORT_READ(in_RENAME_IN_NUM_REG_RD_PHY_OLD [i]);
	num_reg_rd_phy_new [i] = PORT_READ(in_RENAME_IN_NUM_REG_RD_PHY_NEW [i]);
	write_re           [i] = PORT_READ(in_RENAME_IN_WRITE_RE           [i]);
	num_reg_re_log     [i] = PORT_READ(in_RENAME_IN_NUM_REG_RE_LOG     [i]);
	num_reg_re_phy_old [i] = PORT_READ(in_RENAME_IN_NUM_REG_RE_PHY_OLD [i]);
	num_reg_re_phy_new [i] = PORT_READ(in_RENAME_IN_NUM_REG_RE_PHY_NEW [i]);
	
	// ================================================================
	// =====[ Write after Write ]======================================
	// ================================================================
	if (write_rd [i])
	  // Inverse scan : with x < y, instruction x is before in the sequential order program that the instruction y
	  for (int32_t j=i-1; j>=0; j--)
	    if ((write_rd       [j] == 1                 ) and
		(num_reg_rd_log [j] == num_reg_rd_log [i]) and
		(front_end_id   [j] == front_end_id   [i]) and
		(context_id     [j] == context_id     [i]) )
	      {
		num_reg_rd_phy_old [i] = num_reg_rd_phy_new [j];
		break; // find the most recently dependency
	      }
	
	if (write_re [i])
	  // Inverse scan : with x < y, instruction x is before in the sequential order program that the instruction y
	  for (int32_t j=i-1; j>=0; j--)
	    if ((write_re       [j] == 1                 ) and
		(num_reg_re_log [j] == num_reg_re_log [i]) and
		(front_end_id   [j] == front_end_id   [i]) and
		(context_id     [j] == context_id     [i]) )
	      {
		num_reg_re_phy_old [i] = num_reg_re_phy_new [j];
		break; // find the most recently dependency
	      }
	// ================================================================
	// =====[ Read  after Write ]======================================
	// ================================================================
	if (read_ra [i])
	  // Inverse scan : with x < y, instruction x is before in the sequential order program that the instruction y
	  for (int32_t j=i-1; j>=0; j--)
	    if ((write_rd       [j] == 1                 ) and
		(num_reg_rd_log [j] == num_reg_ra_log [i]) and
		(front_end_id   [j] == front_end_id   [i]) and
		(context_id     [j] == context_id     [i]) )
	      {
		num_reg_ra_phy [i] = num_reg_rd_phy_new [j];
		break; // find the most recently dependency
	      }

	if (read_rb [i])
	  // Inverse scan : with x < y, instruction x is before in the sequential order program that the instruction y
	  for (int32_t j=i-1; j>=0; j--)
	    if ((write_rd       [j] == 1                 ) and
		(num_reg_rd_log [j] == num_reg_rb_log [i]) and
		(front_end_id   [j] == front_end_id   [i]) and
		(context_id     [j] == context_id     [i]) )
	      {
		num_reg_rb_phy [i] = num_reg_rd_phy_new [j];
		break; // find the most recently dependency
	      }

	if (read_rc [i])
	  // Inverse scan : with x < y, instruction x is before in the sequential order program that the instruction y
	  for (int32_t j=i-1; j>=0; j--)
	    if ((write_re       [j] == 1                 ) and
		(num_reg_re_log [j] == num_reg_rc_log [i]) and
		(front_end_id   [j] == front_end_id   [i]) and
		(context_id     [j] == context_id     [i]) )
	      {
		num_reg_rc_phy [i] = num_reg_re_phy_new [j];
		break; // find the most recently dependency
	      }

 	// =====[ Output ]=================================================
// 	PORT_WRITE(out_RENAME_OUT_VAL                [i], val                [i]);
// 	PORT_WRITE(out_RENAME_IN_ACK                 [i], ack                [i]);
	if (_param->_have_port_front_end_id)
	PORT_WRITE(out_RENAME_OUT_FRONT_END_ID       [i], front_end_id       [i]);
	if (_param->_have_port_context_id)
	PORT_WRITE(out_RENAME_OUT_CONTEXT_ID         [i], context_id         [i]);
	PORT_WRITE(out_RENAME_OUT_READ_RA            [i], read_ra            [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RA_LOG     [i], num_reg_ra_log     [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RA_PHY     [i], num_reg_ra_phy     [i]);
	PORT_WRITE(out_RENAME_OUT_READ_RB            [i], read_rb            [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RB_LOG     [i], num_reg_rb_log     [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RB_PHY     [i], num_reg_rb_phy     [i]);
	PORT_WRITE(out_RENAME_OUT_READ_RC            [i], read_rc            [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RC_LOG     [i], num_reg_rc_log     [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RC_PHY     [i], num_reg_rc_phy     [i]);
	PORT_WRITE(out_RENAME_OUT_WRITE_RD           [i], write_rd           [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RD_LOG     [i], num_reg_rd_log     [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RD_PHY_OLD [i], num_reg_rd_phy_old [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RD_PHY_NEW [i], num_reg_rd_phy_new [i]);
	PORT_WRITE(out_RENAME_OUT_WRITE_RE           [i], write_re           [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RE_LOG     [i], num_reg_re_log     [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RE_PHY_OLD [i], num_reg_re_phy_old [i]);
	PORT_WRITE(out_RENAME_OUT_NUM_REG_RE_PHY_NEW [i], num_reg_re_phy_new [i]);
      }

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

}; // end namespace dependency_checking_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
