#ifdef SYSTEMC
//#if defined(STATISTICS) or defined(VHDL_TESTBENCH)
/*
 * $Id$
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_Execute_loop/Execute_loop/Multi_Read_unit/Read_unit/Read_queue/include/Read_queue.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_execute_loop {
namespace execute_loop {
namespace multi_read_unit {
namespace read_unit {
namespace read_queue {


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

    if (PORT_READ(in_NRESET) == 0)
      {
	// Flush queue
	// FIXME "queue reset"
	// > 1) flush one slot by cycle
	// > 2) flush all slot in one cycle

	while (_queue->empty() == false)
	  _queue->pop();
      }
    else
      {
// 	cout << "Transition Begin  : Print queue_head" << endl;
// 	if (_queue->empty ())
// 	  cout << "queue is empty !!!" << endl;
// 	else
// 	  cout << (*_queue_head) << endl;

	log_printf(TRACE,Read_queue,FUNCTION,"Read_queue size (begin) : %d",_queue->size());
	// Write to read_queue

	bool not_full      = not (_queue->size() == _param->_size_queue);
	bool     empty     =     _queue->empty();
	bool need_new_head = false;
	
	log_printf(TRACE,Read_queue,FUNCTION," * test transaction READ_QUEUE_IN  : %d,%d",PORT_READ(in_READ_QUEUE_IN_VAL), not_full);
	if ((PORT_READ(in_READ_QUEUE_IN_VAL) == 1) and not_full)
	  {
	    Tread_queue_entry_t * entry = new Tread_queue_entry_t;

	    if(_param->_have_port_context_id   )
	      entry->_context_id   = PORT_READ(in_READ_QUEUE_IN_CONTEXT_ID  );
	    if(_param->_have_port_front_end_id )
	      entry->_front_end_id = PORT_READ(in_READ_QUEUE_IN_FRONT_END_ID);
	    if(_param->_have_port_ooo_engine_id)
	      entry->_ooo_engine_id= PORT_READ(in_READ_QUEUE_IN_OOO_ENGINE_ID);
	    if(_param->_have_port_rob_id       )
	      entry->_rob_id       = PORT_READ(in_READ_QUEUE_IN_ROB_ID      );
	    entry->_operation    = PORT_READ(in_READ_QUEUE_IN_OPERATION   );
	    entry->_type         = PORT_READ(in_READ_QUEUE_IN_TYPE        );
	    entry->_store_queue_ptr_write = PORT_READ(in_READ_QUEUE_IN_STORE_QUEUE_PTR_WRITE);
	    if (_param->_have_port_load_queue_ptr)
	    entry->_load_queue_ptr_write  = PORT_READ(in_READ_QUEUE_IN_LOAD_QUEUE_PTR_WRITE );
	    entry->_has_immediat = PORT_READ(in_READ_QUEUE_IN_HAS_IMMEDIAT);
	    entry->_immediat     = PORT_READ(in_READ_QUEUE_IN_IMMEDIAT    );
	    entry->_read_ra      = PORT_READ(in_READ_QUEUE_IN_READ_RA     );
	    entry->_num_reg_ra   = PORT_READ(in_READ_QUEUE_IN_NUM_REG_RA  );
	    entry->_read_rb      = PORT_READ(in_READ_QUEUE_IN_READ_RB     );
	    entry->_num_reg_rb   = PORT_READ(in_READ_QUEUE_IN_NUM_REG_RB  );
	    entry->_read_rc      = PORT_READ(in_READ_QUEUE_IN_READ_RC     );
	    entry->_num_reg_rc   = PORT_READ(in_READ_QUEUE_IN_NUM_REG_RC  );
	    entry->_write_rd     = PORT_READ(in_READ_QUEUE_IN_WRITE_RD    );
	    entry->_num_reg_rd   = PORT_READ(in_READ_QUEUE_IN_NUM_REG_RD  );
	    entry->_write_re     = PORT_READ(in_READ_QUEUE_IN_WRITE_RE    );
	    entry->_num_reg_re   = PORT_READ(in_READ_QUEUE_IN_NUM_REG_RE  );

	    log_printf(TRACE,Read_queue,FUNCTION,"   * push (id : %d-%d)",entry->_context_id, entry->_rob_id);
	    _queue->push(entry);


	    // read next new head
	    if (empty)
	      {
		log_printf(TRACE,Read_queue,FUNCTION,"     * queue was    empty");
		need_new_head = true;
	      }
	  }

	// Read from read_queue
	log_printf(TRACE,Read_queue,FUNCTION," * test transaction READ_QUEUE_OUT : %d,%d",internal_READ_QUEUE_OUT_VAL, PORT_READ(in_READ_QUEUE_OUT_ACK));
	if ((    internal_READ_QUEUE_OUT_VAL  == 1) and 
	    (PORT_READ(in_READ_QUEUE_OUT_ACK) == 1))
	  {
	    // Pop the entry
	    log_printf(TRACE,Read_queue,FUNCTION,"   * pop  (id : %d-%d)",_queue->front()->_context_id, _queue->front()->_rob_id);
	    _queue->pop();

	    // read next new head
	    if (_queue->empty() == false)
	      {
		log_printf(TRACE,Read_queue,FUNCTION,"     * queue was not empty");
		need_new_head = true;
	      }
	  }
	else
	  {
	    // no transaction, update queue_head
	    _queue_head->_read_ra_val = internal_READ_QUEUE_OUT_READ_RA_VAL ;
	    _queue_head->_data_ra_val = internal_READ_QUEUE_OUT_DATA_RA_VAL ;
	    _queue_head->_data_ra     = internal_READ_QUEUE_OUT_DATA_RA     ;

	    _queue_head->_read_rb_val = internal_READ_QUEUE_OUT_READ_RB_VAL ;
	    _queue_head->_data_rb_val = internal_READ_QUEUE_OUT_DATA_RB_VAL ;
	    _queue_head->_data_rb     = internal_READ_QUEUE_OUT_DATA_RB     ;

	    _queue_head->_read_rc_val = internal_READ_QUEUE_OUT_READ_RC_VAL ;
	    _queue_head->_data_rc_val = internal_READ_QUEUE_OUT_DATA_RC_VAL ;
	    _queue_head->_data_rc     = internal_READ_QUEUE_OUT_DATA_RC     ;
	  }

	if (need_new_head == true)
	  {
	    log_printf(TRACE,Read_queue,FUNCTION," * new head");
	    (*_queue_head) = (*_queue->front());
	  }
	
// 	cout << "Transition End    : Print queue_head" << endl;
// 	if (_queue->empty ())
// 	  cout << "queue is empty !!!" << endl;
// 	else
// 	  cout << (*_queue_head) << endl;

	log_printf(TRACE,Read_queue,FUNCTION,"Read_queue size (end  ) : %d",_queue->size());
      }

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

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

}; // end namespace read_queue
}; // end namespace read_unit
}; // end namespace multi_read_unit
}; // end namespace execute_loop
}; // end namespace multi_execute_loop
}; // end namespace core

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