#ifdef SYSTEMC
/*
 * $Id: Rename_select_genMealy.cpp 115 2009-04-20 21:29:17Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Rename_unit/Rename_select/include/Rename_select.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace rename_unit {
namespace rename_select {


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

    Tcontrol_t val                  [_param->_nb_inst_rename];
    Tcontrol_t ack                  [_param->_nb_front_end][_param->_max_nb_inst_decod];
    Tcontrol_t previous_transaction [_param->_nb_front_end];

    for (uint32_t i=0; i<_param->_nb_inst_rename; ++i)
      val [i] = false;
    for (uint32_t i=0; i<_param->_nb_front_end; i++)
      {
        previous_transaction [i] = true;
        for (uint32_t j=0; j<_param->_nb_inst_decod[i]; j++)
          ack [i][j] = false;
      }

    std::list<generic::priority::select_t> * select = _priority->select();
    std::list<generic::priority::select_t>::iterator it=select->begin();

    for (uint32_t i=0; i<_param->_nb_inst_rename; i++)
      {
        log_printf(TRACE,Rename_select,FUNCTION,"  * RENAME_OUT [%d]",i);

        // Scan all instruction until find
	while ((it != select->end()) and (val [i] == false))
	  {
	    Tcontext_t x = it->grp;
	    uint32_t   y = it->elt;

            log_printf(TRACE,Rename_select,FUNCTION,"    * front_end[%d].inst_decod[%d]",x,y);
            log_printf(TRACE,Rename_select,FUNCTION,"      * in_RENAME_OUT_VAL    : %d",PORT_READ(in_RENAME_IN_VAL[x][y]));
            log_printf(TRACE,Rename_select,FUNCTION,"      * previous_transaction : %d",previous_transaction[x]);

	    // Test if this instruction is valid and if all previous instruction of this front end is an valid transaction
	    if (previous_transaction [x] and
                PORT_READ(in_RENAME_IN_VAL[x][y]))
	      {
		// Find !!!
		val [i]    = true;
		ack [x][y] = PORT_READ(in_RENAME_OUT_ACK [i]);

                log_printf(TRACE,Rename_select,FUNCTION,"      * in_RENAME_OUT_ACK    : %d",PORT_READ(in_RENAME_OUT_ACK[i]));
                Tcontext_t front_end_id = (_param->_have_port_front_end_id)?PORT_READ(in_RENAME_IN_FRONT_END_ID [x][y]):0;
                Tcontext_t context_id   = (_param->_have_port_context_id  )?PORT_READ(in_RENAME_IN_CONTEXT_ID   [x][y]):0;

		log_printf(TRACE,Rename_select,FUNCTION,"      * front_end_id         : %d",front_end_id);
		log_printf(TRACE,Rename_select,FUNCTION,"      * context_id           : %d",context_id);
                
                // Test if ROB is Flushed
                Tevent_state_t event_state         = PORT_READ(in_RETIRE_EVENT_STATE [x][context_id]);
		Tcontrol_t     have_event          = (event_state != EVENT_STATE_NO_EVENT);
		Tcontrol_t     can_register_access = not have_event;
		Tcontrol_t     no_execute          = (PORT_READ(in_RENAME_IN_NO_EXECUTE [x][y]) or have_event);
		Tcontrol_t     read_ra             = (PORT_READ(in_RENAME_IN_READ_RA    [x][y]) and can_register_access);
		Tcontrol_t     read_rb             = (PORT_READ(in_RENAME_IN_READ_RB    [x][y]) and can_register_access);
		Tcontrol_t     read_rc             = (PORT_READ(in_RENAME_IN_READ_RC    [x][y]) and can_register_access);
		Tcontrol_t     write_rd            = (PORT_READ(in_RENAME_IN_WRITE_RD   [x][y]) and can_register_access);
		Tcontrol_t     write_re            = (PORT_READ(in_RENAME_IN_WRITE_RE   [x][y]) and can_register_access);
// 		Tcontrol_t     read_ra             = (PORT_READ(in_RENAME_IN_READ_RA    [x][y]));
// 		Tcontrol_t     read_rb             = (PORT_READ(in_RENAME_IN_READ_RB    [x][y]));
// 		Tcontrol_t     read_rc             = (PORT_READ(in_RENAME_IN_READ_RC    [x][y]));
// 		Tcontrol_t     write_rd            = (PORT_READ(in_RENAME_IN_WRITE_RD   [x][y]));
// 		Tcontrol_t     write_re            = (PORT_READ(in_RENAME_IN_WRITE_RE   [x][y]));

                log_printf(TRACE,Rename_select,FUNCTION,"      * event_state          : %d",event_state);
                log_printf(TRACE,Rename_select,FUNCTION,"      * no_execute (before)  : %d",PORT_READ(in_RENAME_IN_NO_EXECUTE [x][y]));
                log_printf(TRACE,Rename_select,FUNCTION,"      * no_execute (after)   : %d",no_execute);

		if (_param->_have_port_front_end_id)
		PORT_WRITE(out_RENAME_OUT_FRONT_END_ID [i],front_end_id);
		if (_param->_have_port_context_id)
                PORT_WRITE(out_RENAME_OUT_CONTEXT_ID   [i],context_id);
		if (_param->_have_port_depth)
		PORT_WRITE(out_RENAME_OUT_DEPTH        [i],PORT_READ(in_RENAME_IN_DEPTH         [x][y]));
		PORT_WRITE(out_RENAME_OUT_TYPE         [i],PORT_READ(in_RENAME_IN_TYPE          [x][y]));
		PORT_WRITE(out_RENAME_OUT_OPERATION    [i],PORT_READ(in_RENAME_IN_OPERATION     [x][y]));
		PORT_WRITE(out_RENAME_OUT_NO_EXECUTE   [i],no_execute);
		PORT_WRITE(out_RENAME_OUT_IS_DELAY_SLOT[i],PORT_READ(in_RENAME_IN_IS_DELAY_SLOT [x][y]));
#ifdef DEBUG
		PORT_WRITE(out_RENAME_OUT_ADDRESS      [i],PORT_READ(in_RENAME_IN_ADDRESS       [x][y]));
#endif
		PORT_WRITE(out_RENAME_OUT_ADDRESS_NEXT [i],PORT_READ(in_RENAME_IN_ADDRESS_NEXT  [x][y]));
		PORT_WRITE(out_RENAME_OUT_HAS_IMMEDIAT [i],PORT_READ(in_RENAME_IN_HAS_IMMEDIAT  [x][y]));
		PORT_WRITE(out_RENAME_OUT_IMMEDIAT     [i],PORT_READ(in_RENAME_IN_IMMEDIAT      [x][y]));
		PORT_WRITE(out_RENAME_OUT_READ_RA      [i],read_ra);
		PORT_WRITE(out_RENAME_OUT_NUM_REG_RA   [i],PORT_READ(in_RENAME_IN_NUM_REG_RA    [x][y]));
		PORT_WRITE(out_RENAME_OUT_READ_RB      [i],read_rb);
		PORT_WRITE(out_RENAME_OUT_NUM_REG_RB   [i],PORT_READ(in_RENAME_IN_NUM_REG_RB    [x][y]));
		PORT_WRITE(out_RENAME_OUT_READ_RC      [i],read_rc);
		PORT_WRITE(out_RENAME_OUT_NUM_REG_RC   [i],PORT_READ(in_RENAME_IN_NUM_REG_RC    [x][y]));
		PORT_WRITE(out_RENAME_OUT_WRITE_RD     [i],write_rd);
		PORT_WRITE(out_RENAME_OUT_NUM_REG_RD   [i],PORT_READ(in_RENAME_IN_NUM_REG_RD    [x][y]));
		PORT_WRITE(out_RENAME_OUT_WRITE_RE     [i],write_re);
		PORT_WRITE(out_RENAME_OUT_NUM_REG_RE   [i],PORT_READ(in_RENAME_IN_NUM_REG_RE    [x][y]));
		PORT_WRITE(out_RENAME_OUT_EXCEPTION_USE[i],PORT_READ(in_RENAME_IN_EXCEPTION_USE [x][y]));
		PORT_WRITE(out_RENAME_OUT_EXCEPTION    [i],PORT_READ(in_RENAME_IN_EXCEPTION     [x][y]));
	      }

            // ack = 1 if previous_transaction == true and rename_in_val == true and rename_out == true
            previous_transaction [x] = ack [x][y];

	    it ++;
	  }

      }

    for (uint32_t i=0; i<_param->_nb_inst_rename; ++i)
      PORT_WRITE(out_RENAME_OUT_VAL [i], val [i]);

    for (uint32_t i=0; i<_param->_nb_front_end; i++)
      for (uint32_t j=0; j<_param->_nb_inst_decod[i]; j++)
	PORT_WRITE(out_RENAME_IN_ACK [i][j], ack [i][j]);

    log_end(Rename_select,FUNCTION);
  };

}; // end namespace rename_select
}; // end namespace rename_unit
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core

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