#ifdef SYSTEMC
/*
 * $Id: Write_queue_genMoore.cpp 118 2009-05-20 22:01:32Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_Execute_loop/Execute_loop/Multi_Write_unit/Write_unit/Write_queue/include/Write_queue.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_execute_loop {
namespace execute_loop {
namespace multi_write_unit {
namespace write_unit {
namespace write_queue {


#undef  FUNCTION
#define FUNCTION "Write_queue::genMoore"
  void Write_queue::genMoore (void)
  {
    log_begin(Write_queue,FUNCTION);
    log_function(Write_queue,FUNCTION,_name.c_str());
    
    // -----[ Interface "bypass_write" ]----------------------------------
    {
      std::list<write_queue_entry_t *>::iterator it = _queue->begin();

      // first bypass is the write_queue_in
      uint32_t first_index = ((_param->_bypass_write_scheme == BYPASS_WRITE_FROM_ALU)?1:0);
      for (uint32_t i=first_index; i<_param->_nb_bypass_write; i++)
	{
          // before because first slot is on {GPR|SPR}_WRITE. Also, take next
	  if (it != _queue->end())
	    it++;

          uint32_t index = i;
// 	  bool val = (i+1) < _queue->size();
	  bool val = (it != _queue->end());

	  if (val)
	    {
	      if (_param->_have_port_ooo_engine_id)
	      PORT_WRITE(out_BYPASS_WRITE_OOO_ENGINE_ID [index], (*it)->_ooo_engine_id);
	      PORT_WRITE(out_BYPASS_WRITE_GPR_NUM_REG   [index], (*it)->_num_reg_rd);
	      PORT_WRITE(out_BYPASS_WRITE_GPR_DATA      [index], (*it)->_data_rd   );
	      PORT_WRITE(out_BYPASS_WRITE_SPR_NUM_REG   [index], (*it)->_num_reg_re);
	      PORT_WRITE(out_BYPASS_WRITE_SPR_DATA      [index], (*it)->_data_re   );
	    }
#ifdef SYSTEMC_VHDL_COMPATIBILITY
          else
            {
	      if (_param->_have_port_ooo_engine_id)
	      PORT_WRITE(out_BYPASS_WRITE_OOO_ENGINE_ID [index], 0);
	      PORT_WRITE(out_BYPASS_WRITE_GPR_NUM_REG   [index], 0);
	      PORT_WRITE(out_BYPASS_WRITE_GPR_DATA      [index], 0);
	      PORT_WRITE(out_BYPASS_WRITE_SPR_NUM_REG   [index], 0);
	      PORT_WRITE(out_BYPASS_WRITE_SPR_DATA      [index], 0);
            }
#endif

	  PORT_WRITE(out_BYPASS_WRITE_GPR_VAL       [index], val and (*it)->_write_rd  );
	  PORT_WRITE(out_BYPASS_WRITE_SPR_VAL       [index], val and (*it)->_write_re  );
	}
    }

    // -----[ Interface "Write_queue_in" ]--------------------------------
    {
      internal_WRITE_QUEUE_IN_ACK = _queue->size() < _param->_size_queue;
      
      PORT_WRITE(out_WRITE_QUEUE_IN_ACK, internal_WRITE_QUEUE_IN_ACK);
    }

    if (_param->_queue_scheme == WRITE_QUEUE_SCHEME_MOORE)
      {
    // -----[ Interface "gpr_write" ]-------------------------------------
    // -----[ Interface "spr_write" ]-------------------------------------
    {
      bool val = not _queue->empty();

      internal_GPR_WRITE_VAL = val and _queue->front()->_write_rd;
      internal_SPR_WRITE_VAL = val and _queue->front()->_write_re;
      
      PORT_WRITE(out_GPR_WRITE_VAL [0], internal_GPR_WRITE_VAL);
      PORT_WRITE(out_SPR_WRITE_VAL [0], internal_SPR_WRITE_VAL);

      if (val)
	{
	  if (_param->_have_port_ooo_engine_id)
	  {
	  PORT_WRITE(out_GPR_WRITE_OOO_ENGINE_ID [0], _queue->front()->_ooo_engine_id);
	  PORT_WRITE(out_SPR_WRITE_OOO_ENGINE_ID [0], _queue->front()->_ooo_engine_id);
	  }
	  PORT_WRITE(out_GPR_WRITE_NUM_REG       [0], _queue->front()->_num_reg_rd);
	  PORT_WRITE(out_GPR_WRITE_DATA          [0], _queue->front()->_data_rd   );
	  PORT_WRITE(out_SPR_WRITE_NUM_REG       [0], _queue->front()->_num_reg_re);
	  PORT_WRITE(out_SPR_WRITE_DATA          [0], _queue->front()->_data_re   );
	}
    }

    // -----[ Interface "Write_queue_out" ]--------------------------------
    {
      internal_WRITE_QUEUE_OUT_VAL = ((not _queue->empty()           ) and
				      (not _queue->front()->_write_rd) and
				      (not _queue->front()->_write_re) and
                                      (_queue->front()->_exception != EXCEPTION_MEMORY_LOAD_SPECULATIVE)
                                      );
      
      PORT_WRITE(out_WRITE_QUEUE_OUT_VAL, internal_WRITE_QUEUE_OUT_VAL);

      if (internal_WRITE_QUEUE_OUT_VAL)
	{
	  if (_param->_have_port_context_id)
      	  PORT_WRITE(out_WRITE_QUEUE_OUT_CONTEXT_ID   , _queue->front()->_context_id   );
	  if (_param->_have_port_front_end_id)
      	  PORT_WRITE(out_WRITE_QUEUE_OUT_FRONT_END_ID , _queue->front()->_front_end_id );
	  if (_param->_have_port_ooo_engine_id)
      	  PORT_WRITE(out_WRITE_QUEUE_OUT_OOO_ENGINE_ID, _queue->front()->_ooo_engine_id);
	  if (_param->_have_port_rob_ptr  )
      	  PORT_WRITE(out_WRITE_QUEUE_OUT_PACKET_ID    , _queue->front()->_packet_id    );
//    	  PORT_WRITE(out_WRITE_QUEUE_OUT_OPERATION    , _queue->front()->_operation    );
//    	  PORT_WRITE(out_WRITE_QUEUE_OUT_TYPE         , _queue->front()->_type         );
      	  PORT_WRITE(out_WRITE_QUEUE_OUT_FLAGS        , _queue->front()->_data_re      );
      	  PORT_WRITE(out_WRITE_QUEUE_OUT_EXCEPTION    , _queue->front()->_exception    );
      	  PORT_WRITE(out_WRITE_QUEUE_OUT_NO_SEQUENCE  , _queue->front()->_no_sequence  );
      	  PORT_WRITE(out_WRITE_QUEUE_OUT_ADDRESS      , _queue->front()->_address      );
      	  PORT_WRITE(out_WRITE_QUEUE_OUT_DATA         , _queue->front()->_data_rd      );
	}
    }

      } // end WRITE_QUEUE_SCHEME_MOORE
    log_end(Write_queue,FUNCTION);
  };

}; // end namespace write_queue
}; // end namespace write_unit
}; // end namespace multi_write_unit
}; // end namespace execute_loop
}; // end namespace multi_execute_loop
}; // end namespace core

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