#ifdef SYSTEMC
/*
 * $Id: Issue_queue_transition.cpp 88 2008-12-10 18:31:39Z rosiere $
 *
 * [ Description ]
 * 
 */

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

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace issue_queue {


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

    if (PORT_READ(in_NRESET) == 0)
      {
	_priority_in ->reset();
	_priority_out->reset();
	_priority_reg->reset();
	
	for (uint32_t i=0; i<_param->_nb_bank; i++)
	  _issue_queue [i].clear();
      }
    else
      {
	_priority_in ->transition();
	_priority_out->transition();
	_priority_reg->transition();

	// ===================================================================
	// =====[ ISSUE_IN ]==================================================
	// ===================================================================
	for (uint32_t i=0; i<_param->_nb_bank; i++)
	  if (internal_BANK_IN_ACK [i])
	    {
	      entry_t* entry = NULL;

	      if (internal_BANK_IN_IS_REEXECUTE [i])
		{
		  uint32_t y = internal_BANK_IN_NUM_INST [i];
	      
		  if (PORT_READ(in_REEXECUTE_VAL [y]))
		    {
#ifdef STATISTICS
                      if (usage_is_set(_usage,USE_STATISTICS))
                        (*_stat_nb_inst_reexecute) ++;
#endif
		      entry = new entry_t
			(
			 (_param->_have_port_context_id    )?PORT_READ(in_REEXECUTE_CONTEXT_ID            [y]):0,
			 (_param->_have_port_front_end_id  )?PORT_READ(in_REEXECUTE_FRONT_END_ID          [y]):0,
			 (_param->_have_port_rob_ptr       )?PORT_READ(in_REEXECUTE_PACKET_ID             [y]):0,
			 PORT_READ(in_REEXECUTE_OPERATION             [y]),
			 PORT_READ(in_REEXECUTE_TYPE                  [y]),
			 PORT_READ(in_REEXECUTE_STORE_QUEUE_PTR_WRITE [y]),
			 (_param->_have_port_load_queue_ptr)?PORT_READ(in_REEXECUTE_LOAD_QUEUE_PTR_WRITE  [y]):0,
			 PORT_READ(in_REEXECUTE_HAS_IMMEDIAT          [y]),
			 PORT_READ(in_REEXECUTE_IMMEDIAT              [y]),
			 PORT_READ(in_REEXECUTE_READ_RA               [y]),
			 PORT_READ(in_REEXECUTE_NUM_REG_RA            [y]),
			 PORT_READ(in_REEXECUTE_READ_RB               [y]),
			 PORT_READ(in_REEXECUTE_NUM_REG_RB            [y]),
			 PORT_READ(in_REEXECUTE_READ_RC               [y]),
			 PORT_READ(in_REEXECUTE_NUM_REG_RC            [y]),
			 PORT_READ(in_REEXECUTE_WRITE_RD              [y]),
			 PORT_READ(in_REEXECUTE_NUM_REG_RD            [y]),
			 PORT_READ(in_REEXECUTE_WRITE_RE              [y]),
			 PORT_READ(in_REEXECUTE_NUM_REG_RE            [y])
			 );
		    }
		}
	      else
		{
		  uint32_t x = internal_BANK_IN_NUM_RENAME_UNIT [i];
		  uint32_t y = internal_BANK_IN_NUM_INST [i];

		  if (PORT_READ(in_ISSUE_IN_VAL[x][y]))
		    {
#ifdef STATISTICS
                      if (usage_is_set(_usage,USE_STATISTICS))
                        (*_stat_nb_inst_issue_in [x]) ++;
#endif
		      entry = new entry_t
			(
			 (_param->_have_port_context_id    )?PORT_READ(in_ISSUE_IN_CONTEXT_ID            [x][y]):0,
			 (_param->_have_port_front_end_id  )?PORT_READ(in_ISSUE_IN_FRONT_END_ID          [x][y]):0,
			 (_param->_have_port_rob_ptr       )?PORT_READ(in_ISSUE_IN_PACKET_ID             [x][y]):0,
			 PORT_READ(in_ISSUE_IN_OPERATION             [x][y]),
			 PORT_READ(in_ISSUE_IN_TYPE                  [x][y]),
			 PORT_READ(in_ISSUE_IN_STORE_QUEUE_PTR_WRITE [x][y]),
			 (_param->_have_port_load_queue_ptr)?PORT_READ(in_ISSUE_IN_LOAD_QUEUE_PTR_WRITE  [x][y]):0,
			 PORT_READ(in_ISSUE_IN_HAS_IMMEDIAT          [x][y]),
			 PORT_READ(in_ISSUE_IN_IMMEDIAT              [x][y]),
			 PORT_READ(in_ISSUE_IN_READ_RA               [x][y]),
			 PORT_READ(in_ISSUE_IN_NUM_REG_RA            [x][y]),
			 PORT_READ(in_ISSUE_IN_READ_RB               [x][y]),
			 PORT_READ(in_ISSUE_IN_NUM_REG_RB            [x][y]),
			 PORT_READ(in_ISSUE_IN_READ_RC               [x][y]),
			 PORT_READ(in_ISSUE_IN_NUM_REG_RC            [x][y]),
			 PORT_READ(in_ISSUE_IN_WRITE_RD              [x][y]),
			 PORT_READ(in_ISSUE_IN_NUM_REG_RD            [x][y]),
			 PORT_READ(in_ISSUE_IN_WRITE_RE              [x][y]),
			 PORT_READ(in_ISSUE_IN_NUM_REG_RE            [x][y])
			 );
		    }
		}

	      if (entry != NULL)
		_issue_queue [i].push_back(entry);
	    }

	// ===================================================================
	// =====[ ISSUE_OUT ]=================================================
	// ===================================================================
	for (uint32_t i=0; i<_param->_nb_bank; i++)
	  {
// 	    log_printf(TRACE,Issue_queue,FUNCTION,"  * internal_BANK_OUT [%d] val %d, num_inst %d",i,internal_BANK_OUT_VAL [i],internal_BANK_OUT_NUM_INST [i]);

	    if (internal_BANK_OUT_VAL [i])
	      {
#ifdef STATISTICS
                if (usage_is_set(_usage,USE_STATISTICS))
                  (*_stat_nb_inst_issue_out) ++;
#endif

		uint32_t x = internal_BANK_OUT_NUM_INST [i];
// 		log_printf(TRACE,Issue_queue,FUNCTION,"    * ISSUE_OUT_ACK : %d",PORT_READ(in_ISSUE_OUT_ACK [x]));
		
		if (PORT_READ(in_ISSUE_OUT_ACK [x]))
		  {
		    entry_t * entry =  _issue_queue [i].front();
		    _issue_queue [i].pop_front();
		    delete entry;
		  }
	      }
	  }
      }

    log_printf(TRACE,Issue_queue,FUNCTION,"  * Info Issue_queue");
    for (uint32_t i=0; i<_param->_nb_bank; i++)
      {
#ifdef STATISTICS
        if (usage_is_set(_usage,USE_STATISTICS))
          *(_stat_bank_nb_inst [i]) += _issue_queue[i].size();
#endif
	log_printf(TRACE,Issue_queue,FUNCTION,"    * [%d] size : %d",i,(int)_issue_queue[i].size());
      }

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

    log_end(Issue_queue,FUNCTION);
  };

}; // end namespace issue_queue
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core

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