#ifdef SYSTEMC
/*
 * $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 {


  void Read_queue::allocation (void)
  {
    log_printf(FUNC,Read_queue,"allocation","Begin");

    _component   = new Component ();

    Entity * entity = _component->set_entity (_name       
					      ,"Read_queue"
#ifdef POSITION
					      ,COMBINATORY 
#endif
					      );

    _interfaces = entity->set_interfaces();

    // ~~~~~[ Interface : "" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    {
      Interface * interface = _interfaces->set_interface(""
#ifdef POSITION
							 ,IN
							 ,SOUTH,
							 "Generalist interface"
#endif
							 );

     in_CLOCK        = interface->set_signal_clk              ("clock" ,1, CLOCK_VHDL_YES);
     in_NRESET       = interface->set_signal_in  <Tcontrol_t> ("nreset",1, RESET_VHDL_YES);
    }
    // ~~~~~[ Interface : "read_queue_in" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      Interface_fifo * interface = _interfaces->set_interface("read_queue_in"
#ifdef POSITION
							      ,IN
							      ,EAST
							      ,"Input of read_queue"
#endif
							      );

       in_READ_QUEUE_IN_VAL            = interface->set_signal_valack_in        ("val"    , VAL);
      out_READ_QUEUE_IN_ACK            = interface->set_signal_valack_out       ("ack"    , ACK);
      if(_param->_have_port_context_id  )
       in_READ_QUEUE_IN_CONTEXT_ID     = interface->set_signal_in  <Tcontext_t        > ("context_id"   ,_param->_size_context_id       );
      if(_param->_have_port_front_end_id)
       in_READ_QUEUE_IN_FRONT_END_ID   = interface->set_signal_in  <Tcontext_t        > ("front_end_id" ,_param->_size_front_end_id     );
       if(_param->_have_port_ooo_engine_id)
	 in_READ_QUEUE_IN_OOO_ENGINE_ID  = interface->set_signal_in  <Tcontext_t        > ("ooo_engine_id",_param->_size_ooo_engine_id    );
      if(_param->_have_port_rob_id      )
       in_READ_QUEUE_IN_ROB_ID         = interface->set_signal_in  <Tpacket_t         > ("rob_id"      ,_param->_size_rob_id           );
       in_READ_QUEUE_IN_OPERATION      = interface->set_signal_in  <Toperation_t      > ("operation"   ,_param->_size_operation        );
       in_READ_QUEUE_IN_TYPE           = interface->set_signal_in  <Ttype_t           > ("type"        ,_param->_size_type             );
       in_READ_QUEUE_IN_STORE_QUEUE_PTR_WRITE = interface->set_signal_in  <Tlsq_ptr_t> ("store_queue_ptr_write", log2(_param->_size_store_queue));
       if (_param->_have_port_load_queue_ptr)
       in_READ_QUEUE_IN_LOAD_QUEUE_PTR_WRITE  = interface->set_signal_in  <Tlsq_ptr_t> ("load_queue_ptr_write" , log2(_param->_size_load_queue ));
       in_READ_QUEUE_IN_HAS_IMMEDIAT   = interface->set_signal_in  <Tcontrol_t        > ("has_immediat",1                             );
       in_READ_QUEUE_IN_IMMEDIAT       = interface->set_signal_in  <Tgeneral_data_t   > ("immediat"    ,_param->_size_general_data     );
       in_READ_QUEUE_IN_READ_RA        = interface->set_signal_in  <Tcontrol_t        > ("read_ra"     ,1                             );
       in_READ_QUEUE_IN_NUM_REG_RA     = interface->set_signal_in  <Tgeneral_address_t> ("num_reg_ra"  ,_param->_size_general_register );
       in_READ_QUEUE_IN_READ_RB        = interface->set_signal_in  <Tcontrol_t        > ("read_rb"     ,1                             );
       in_READ_QUEUE_IN_NUM_REG_RB     = interface->set_signal_in  <Tgeneral_address_t> ("num_reg_rb"  ,_param->_size_general_register );
       in_READ_QUEUE_IN_READ_RC        = interface->set_signal_in  <Tcontrol_t        > ("read_rc"     ,1                             );
       in_READ_QUEUE_IN_NUM_REG_RC     = interface->set_signal_in  <Tspecial_address_t> ("num_reg_rc"  ,_param->_size_special_register );
       in_READ_QUEUE_IN_WRITE_RD       = interface->set_signal_in  <Tcontrol_t        > ("write_rd"    ,1                             );
       in_READ_QUEUE_IN_NUM_REG_RD     = interface->set_signal_in  <Tgeneral_address_t> ("num_reg_rd"  ,_param->_size_general_register );
       in_READ_QUEUE_IN_WRITE_RE       = interface->set_signal_in  <Tcontrol_t        > ("write_re"    ,1                             );
       in_READ_QUEUE_IN_NUM_REG_RE     = interface->set_signal_in  <Tspecial_address_t> ("num_reg_re"  ,_param->_size_special_register );      
     }

    // ~~~~~[ Interface : "read_queue_out" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      Interface_fifo * interface = _interfaces->set_interface("read_queue_out"
#ifdef POSITION
							       ,OUT
							       ,EAST
							       ,"Input of read_queue"
#endif
							       );
      
      out_READ_QUEUE_OUT_VAL            = interface->set_signal_valack_out       ("val"    , VAL);
       in_READ_QUEUE_OUT_ACK            = interface->set_signal_valack_in        ("ack"    , ACK);

      if(_param->_have_port_context_id  )
	out_READ_QUEUE_OUT_CONTEXT_ID     = interface->set_signal_out <Tcontext_t        > ("context_id"   ,_param->_size_context_id       );
      if(_param->_have_port_front_end_id)
	out_READ_QUEUE_OUT_FRONT_END_ID   = interface->set_signal_out <Tcontext_t        > ("front_end_id" ,_param->_size_front_end_id     );
      if(_param->_have_port_ooo_engine_id)
	out_READ_QUEUE_OUT_OOO_ENGINE_ID  = interface->set_signal_out <Tcontext_t        > ("ooo_engine_id",_param->_size_ooo_engine_id    );
      if(_param->_have_port_rob_id      )
	out_READ_QUEUE_OUT_ROB_ID         = interface->set_signal_out <Tpacket_t         > ("rob_id"      ,_param->_size_rob_id           );
      out_READ_QUEUE_OUT_OPERATION      = interface->set_signal_out <Toperation_t      > ("operation"   ,_param->_size_operation        );
      out_READ_QUEUE_OUT_TYPE           = interface->set_signal_out <Ttype_t           > ("type"        ,_param->_size_type             );
      out_READ_QUEUE_OUT_STORE_QUEUE_PTR_WRITE = interface->set_signal_out <Tlsq_ptr_t> ("store_queue_ptr_write", log2(_param->_size_store_queue));
      if (_param->_have_port_load_queue_ptr)
      out_READ_QUEUE_OUT_LOAD_QUEUE_PTR_WRITE  = interface->set_signal_out <Tlsq_ptr_t> ("load_queue_ptr_write" , log2(_param->_size_load_queue ));
      out_READ_QUEUE_OUT_HAS_IMMEDIAT   = interface->set_signal_out <Tcontrol_t        > ("has_immediat",1                             );
      out_READ_QUEUE_OUT_IMMEDIAT       = interface->set_signal_out <Tgeneral_data_t   > ("immediat"    ,_param->_size_general_data     );
//       out_READ_QUEUE_OUT_READ_RA        = interface->set_signal_out <Tcontrol_t        > ("read_ra"     ,1                             );
      out_READ_QUEUE_OUT_NUM_REG_RA     = interface->set_signal_out <Tgeneral_address_t> ("num_reg_ra"  ,_param->_size_general_register );
      out_READ_QUEUE_OUT_DATA_RA_VAL    = interface->set_signal_out <Tcontrol_t        > ("data_ra_val" ,1                             );
      out_READ_QUEUE_OUT_DATA_RA        = interface->set_signal_out <Tgeneral_data_t   > ("data_ra"     ,_param->_size_general_data     );
//       out_READ_QUEUE_OUT_READ_RB        = interface->set_signal_out <Tcontrol_t        > ("read_rb"     ,1                             );
      out_READ_QUEUE_OUT_NUM_REG_RB     = interface->set_signal_out <Tgeneral_address_t> ("num_reg_rb"  ,_param->_size_general_register );
      out_READ_QUEUE_OUT_DATA_RB_VAL    = interface->set_signal_out <Tcontrol_t        > ("data_rb_val" ,1                             );
      out_READ_QUEUE_OUT_DATA_RB        = interface->set_signal_out <Tgeneral_data_t   > ("data_rb"     ,_param->_size_general_data     );
//       out_READ_QUEUE_OUT_READ_RC        = interface->set_signal_out <Tcontrol_t        > ("read_rc"     ,1                             );
      out_READ_QUEUE_OUT_NUM_REG_RC     = interface->set_signal_out <Tspecial_address_t> ("num_reg_rc"  ,_param->_size_special_register );
      out_READ_QUEUE_OUT_DATA_RC_VAL    = interface->set_signal_out <Tcontrol_t        > ("data_rc_val" ,1                             );
      out_READ_QUEUE_OUT_DATA_RC        = interface->set_signal_out <Tspecial_data_t   > ("data_rc"     ,_param->_size_special_data     );
      out_READ_QUEUE_OUT_WRITE_RD       = interface->set_signal_out <Tcontrol_t        > ("write_rd"    ,1                             );
      out_READ_QUEUE_OUT_NUM_REG_RD     = interface->set_signal_out <Tgeneral_address_t> ("num_reg_rd"  ,_param->_size_general_register );
      out_READ_QUEUE_OUT_WRITE_RE       = interface->set_signal_out <Tcontrol_t        > ("write_re"    ,1                             );
      out_READ_QUEUE_OUT_NUM_REG_RE     = interface->set_signal_out <Tspecial_address_t> ("num_reg_re"  ,_param->_size_special_register );      
     }

    // ~~~~~[ Interface : "gpr_read" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    out_GPR_READ_VAL          = new SC_OUT(Tcontrol_t        ) * [_param->_nb_gpr_read];
     in_GPR_READ_ACK          = new SC_IN (Tcontrol_t        ) * [_param->_nb_gpr_read];
    if(_param->_have_port_ooo_engine_id)
      out_GPR_READ_OOO_ENGINE_ID= new SC_OUT(Tcontext_t        ) * [_param->_nb_gpr_read];
    out_GPR_READ_NUM_REG      = new SC_OUT(Tgeneral_address_t) * [_param->_nb_gpr_read];
     in_GPR_READ_DATA         = new SC_IN (Tgeneral_data_t   ) * [_param->_nb_gpr_read];
     in_GPR_READ_DATA_VAL     = new SC_IN (Tcontrol_t        ) * [_param->_nb_gpr_read];

    for (uint32_t i=0; i<_param->_nb_gpr_read; i++)
      {
        Interface_fifo * interface = _interfaces->set_interface("gpr_read_"+toString(i)
#ifdef POSITION
                                                                , IN  
                                                                ,SOUTH
                                                                , "Interface with the General RegisterFile."
#endif
                                                                );

	out_GPR_READ_VAL           [i] = interface->set_signal_valack_out       ("val"    , VAL);
	 in_GPR_READ_ACK           [i] = interface->set_signal_valack_in        ("ack"    , ACK);
	if(_param->_have_port_ooo_engine_id)
	  out_GPR_READ_OOO_ENGINE_ID [i] = interface->set_signal_out <Tcontext_t        > ("ooo_engine_id",_param->_size_ooo_engine_id);
	out_GPR_READ_NUM_REG       [i] = interface->set_signal_out <Tgeneral_address_t> ("num_reg"  ,_param->_size_general_register);
	 in_GPR_READ_DATA          [i] = interface->set_signal_in  <Tgeneral_data_t   > ("data"     ,_param->_size_general_data);
	 in_GPR_READ_DATA_VAL      [i] = interface->set_signal_in  <Tcontrol_t        > ("data_val" ,1);
      }
     
    // ~~~~~[ Interface : "spr_read" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    out_SPR_READ_VAL          = new SC_OUT(Tcontrol_t        ) * [_param->_nb_spr_read];
     in_SPR_READ_ACK          = new SC_IN (Tcontrol_t        ) * [_param->_nb_spr_read];
    if(_param->_have_port_ooo_engine_id) 
      out_SPR_READ_OOO_ENGINE_ID= new SC_OUT(Tcontext_t        ) * [_param->_nb_spr_read];
    out_SPR_READ_NUM_REG      = new SC_OUT(Tspecial_address_t) * [_param->_nb_spr_read];
     in_SPR_READ_DATA         = new SC_IN (Tspecial_data_t   ) * [_param->_nb_spr_read];
     in_SPR_READ_DATA_VAL     = new SC_IN (Tcontrol_t        ) * [_param->_nb_spr_read];

    for (uint32_t i=0; i<_param->_nb_spr_read; i++)
      {
        Interface_fifo * interface = _interfaces->set_interface("spr_read_"+toString(i)
#ifdef POSITION
                                                                , IN  
                                                                ,SOUTH
                                                                , "Interface with the Special RegisterFile."
#endif
                                                                );

	out_SPR_READ_VAL           [i] = interface->set_signal_valack_out       ("val"    , VAL);
	 in_SPR_READ_ACK           [i] = interface->set_signal_valack_in        ("ack"    , ACK);
	if(_param->_have_port_ooo_engine_id)
	  out_SPR_READ_OOO_ENGINE_ID [i] = interface->set_signal_out <Tcontext_t        > ("ooo_engine_id",_param->_size_ooo_engine_id);
	out_SPR_READ_NUM_REG       [i] = interface->set_signal_out <Tspecial_address_t> ("num_reg"   ,_param->_size_special_register);
	 in_SPR_READ_DATA          [i] = interface->set_signal_in  <Tspecial_data_t   > ("data"      ,_param->_size_special_data);
	 in_SPR_READ_DATA_VAL      [i] = interface->set_signal_in  <Tcontrol_t        > ("data_val"  ,1);
      }

    // ~~~~~[ Interface : "gpr_write" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
     in_GPR_WRITE_VAL          = new SC_IN (Tcontrol_t        ) * [_param->_nb_gpr_write];
     if(_param->_have_port_ooo_engine_id)
       in_GPR_WRITE_OOO_ENGINE_ID= new SC_IN (Tcontext_t        ) * [_param->_nb_gpr_write];
     in_GPR_WRITE_NUM_REG      = new SC_IN (Tgeneral_address_t) * [_param->_nb_gpr_write];
     in_GPR_WRITE_DATA         = new SC_IN (Tgeneral_data_t   ) * [_param->_nb_gpr_write];

    for (uint32_t i=0; i<_param->_nb_gpr_write; i++)
      {
        Interface_fifo * interface = _interfaces->set_interface("gpr_write_"+toString(i)
#ifdef POSITION
                                                                , IN  
                                                                ,SOUTH
                                                                , "Interface with write queue to bypass the write in the RegisterFile."
#endif
                                                                );

	 in_GPR_WRITE_VAL           [i] = interface->set_signal_valack_in        ("val"    , VAL);
	 if(_param->_have_port_ooo_engine_id)
	   in_GPR_WRITE_OOO_ENGINE_ID [i] = interface->set_signal_in  <Tcontext_t        > ("ooo_engine_id",_param->_size_ooo_engine_id);
	 in_GPR_WRITE_NUM_REG       [i] = interface->set_signal_in  <Tgeneral_address_t> ("num_reg"   ,_param->_size_general_register);
	 in_GPR_WRITE_DATA          [i] = interface->set_signal_in  <Tgeneral_data_t   > ("data"      ,_param->_size_general_data);
      }

    // ~~~~~[ Interface : "spr_write" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
     in_SPR_WRITE_VAL          = new SC_IN (Tcontrol_t        ) * [_param->_nb_spr_write];
     if(_param->_have_port_ooo_engine_id)
       in_SPR_WRITE_OOO_ENGINE_ID= new SC_IN (Tcontext_t        ) * [_param->_nb_spr_write];
     in_SPR_WRITE_NUM_REG      = new SC_IN (Tspecial_address_t) * [_param->_nb_spr_write];
     in_SPR_WRITE_DATA         = new SC_IN (Tspecial_data_t   ) * [_param->_nb_spr_write];

    for (uint32_t i=0; i<_param->_nb_spr_write; i++)
      {
        Interface_fifo * interface = _interfaces->set_interface("spr_write_"+toString(i)
#ifdef POSITION
                                                                , IN  
                                                                ,SOUTH
                                                                , "Interface with write queue to bypass the write in the RegisterFile."
#endif
                                                                );

	 in_SPR_WRITE_VAL           [i] = interface->set_signal_valack_in ("val"    , VAL);
	 if(_param->_have_port_ooo_engine_id)
	   in_SPR_WRITE_OOO_ENGINE_ID [i] = interface->set_signal_in  <Tcontext_t        > ("ooo_engine_id",_param->_size_ooo_engine_id);
	 in_SPR_WRITE_NUM_REG       [i] = interface->set_signal_in  <Tspecial_address_t> ("num_reg"   ,_param->_size_special_register);
	 in_SPR_WRITE_DATA          [i] = interface->set_signal_in  <Tspecial_data_t   > ("data"      ,_param->_size_special_data);
      }

    // ~~~~~[ Component ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    _queue      = new std::queue<Tread_queue_entry_t *>;
    _queue_head = new Tread_queue_head_entry_t;

#ifdef POSITION
    _component->generate_file();
#endif

    log_printf(FUNC,Read_queue,"allocation","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
