#ifdef SYSTEMC
/*
 * $Id$
 *
 * [ Description ]
 * 
 */

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

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



#undef  FUNCTION
#define FUNCTION "Reservation_station::allocation"
  void Reservation_station::allocation (void)
  {
    string rename;

    log_printf(FUNC,Reservation_station,FUNCTION,"Begin");

    _component   = new Component ();

    Entity * entity = _component->set_entity (_name       
					      ,"Reservation_station"
#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 : "insert" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      Interface_fifo * interface = _interfaces->set_interface("insert"
#ifdef POSITION
							       ,IN
							       ,EAST
							       ,"Input of reservation_station"
#endif
							       );
      
       in_INSERT_VAL            = interface->set_signal_valack_in  (VAL);
      out_INSERT_ACK            = interface->set_signal_valack_out (ACK);
      if (_param->_have_port_context_id)
       in_INSERT_CONTEXT_ID     = interface->set_signal_in <Tcontext_t        > ("context_id"     ,_param->_size_context_id       );
      if (_param->_have_port_front_end_id)
       in_INSERT_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_INSERT_OOO_ENGINE_ID  = interface->set_signal_in <Tcontext_t        > ("ooo_engine_id"  ,_param->_size_ooo_engine_id    );
      if (_param->_have_port_rob_id)
       in_INSERT_ROB_ID         = interface->set_signal_in <Tpacket_t         > ("rob_id"         ,_param->_size_rob_id        );
       in_INSERT_OPERATION      = interface->set_signal_in <Toperation_t      > ("operation"      ,_param->_size_operation        );
       in_INSERT_TYPE           = interface->set_signal_in <Ttype_t           > ("type"           ,_param->_size_type             );
       in_INSERT_HAS_IMMEDIAT   = interface->set_signal_in <Tcontrol_t        > ("has_immediat"   ,1                             );
       in_INSERT_IMMEDIAT       = interface->set_signal_in <Tgeneral_data_t   > ("immediat"       ,_param->_size_general_data     );
//     in_INSERT_READ_RA        = interface->set_signal_in <Tcontrol_t        > ("read_ra"        ,1                             );
       in_INSERT_NUM_REG_RA     = interface->set_signal_in <Tgeneral_address_t> ("num_reg_ra"     ,_param->_size_general_register );
       in_INSERT_DATA_RA_VAL    = interface->set_signal_in <Tcontrol_t        > ("data_ra_val"    ,1                             );
       in_INSERT_DATA_RA        = interface->set_signal_in <Tgeneral_data_t   > ("data_ra"        ,_param->_size_general_data     );
//     in_INSERT_READ_RB        = interface->set_signal_in <Tcontrol_t        > ("read_rb"        ,1                             );
       in_INSERT_NUM_REG_RB     = interface->set_signal_in <Tgeneral_address_t> ("num_reg_rb"     ,_param->_size_general_register );
       in_INSERT_DATA_RB_VAL    = interface->set_signal_in <Tcontrol_t        > ("data_rb_val"    ,1                             );
       in_INSERT_DATA_RB        = interface->set_signal_in <Tgeneral_data_t   > ("data_rb"        ,_param->_size_general_data     );
//     in_INSERT_READ_RC        = interface->set_signal_in <Tcontrol_t        > ("read_rc"        ,1                             );
       in_INSERT_NUM_REG_RC     = interface->set_signal_in <Tspecial_address_t> ("num_reg_rc"     ,_param->_size_special_register );
       in_INSERT_DATA_RC_VAL    = interface->set_signal_in <Tcontrol_t        > ("data_rc_val"    ,1                             );
       in_INSERT_DATA_RC        = interface->set_signal_in <Tspecial_data_t   > ("data_rc"        ,_param->_size_special_data     );
       in_INSERT_WRITE_RD       = interface->set_signal_in <Tcontrol_t        > ("write_rd"       ,1                             );
       in_INSERT_NUM_REG_RD     = interface->set_signal_in <Tgeneral_address_t> ("num_reg_rd"     ,_param->_size_general_register );
       in_INSERT_WRITE_RE       = interface->set_signal_in <Tcontrol_t        > ("write_re"       ,1                             );
       in_INSERT_NUM_REG_RE     = interface->set_signal_in <Tspecial_address_t> ("num_reg_re"     ,_param->_size_special_register );      
     }

    // ~~~~~[ Interface : "retire" ]~~~~~~~~~~~~~~~~~~~~~~~~~~
    out_RETIRE_VAL            = new SC_OUT(Tcontrol_t        ) * [_param->_nb_inst_retire];
     in_RETIRE_ACK            = new SC_IN (Tcontrol_t        ) * [_param->_nb_inst_retire];
    if (_param->_have_port_context_id)
    out_RETIRE_CONTEXT_ID     = new SC_OUT(Tcontext_t        ) * [_param->_nb_inst_retire];
    if (_param->_have_port_front_end_id)
    out_RETIRE_FRONT_END_ID   = new SC_OUT(Tcontext_t        ) * [_param->_nb_inst_retire];
    if (_param->_have_port_ooo_engine_id)
    out_RETIRE_OOO_ENGINE_ID  = new SC_OUT(Tcontext_t        ) * [_param->_nb_inst_retire];
    if (_param->_have_port_rob_id)
    out_RETIRE_ROB_ID         = new SC_OUT(Tpacket_t         ) * [_param->_nb_inst_retire];
    out_RETIRE_OPERATION      = new SC_OUT(Toperation_t      ) * [_param->_nb_inst_retire];
    out_RETIRE_TYPE           = new SC_OUT(Ttype_t           ) * [_param->_nb_inst_retire];
    out_RETIRE_HAS_IMMEDIAT   = new SC_OUT(Tcontrol_t        ) * [_param->_nb_inst_retire];
    out_RETIRE_IMMEDIAT       = new SC_OUT(Tgeneral_data_t   ) * [_param->_nb_inst_retire];
    out_RETIRE_DATA_RA        = new SC_OUT(Tgeneral_data_t   ) * [_param->_nb_inst_retire];
    out_RETIRE_DATA_RB        = new SC_OUT(Tgeneral_data_t   ) * [_param->_nb_inst_retire];
    out_RETIRE_DATA_RC        = new SC_OUT(Tspecial_data_t   ) * [_param->_nb_inst_retire];
    out_RETIRE_WRITE_RD       = new SC_OUT(Tcontrol_t        ) * [_param->_nb_inst_retire];
    out_RETIRE_NUM_REG_RD     = new SC_OUT(Tgeneral_address_t) * [_param->_nb_inst_retire];
    out_RETIRE_WRITE_RE       = new SC_OUT(Tcontrol_t        ) * [_param->_nb_inst_retire];
    out_RETIRE_NUM_REG_RE     = new SC_OUT(Tspecial_address_t) * [_param->_nb_inst_retire];
    
    for (uint32_t i=0; i<_param->_nb_inst_retire; i++)
      {
	Interface_fifo * interface = _interfaces->set_interface("retire_"+toString(i)
#ifdef POSITION
								,OUT
								,WEST
								,"Output of reservation_station"
#endif
								);
	out_RETIRE_VAL          [i] = interface->set_signal_valack_out(VAL);
	 in_RETIRE_ACK          [i] = interface->set_signal_valack_in (ACK);
	if (_param->_have_port_context_id)
	out_RETIRE_CONTEXT_ID   [i] = interface->set_signal_out<Tcontext_t        > ("context_id"   ,_param->_size_context_id);
	if (_param->_have_port_front_end_id)
	out_RETIRE_FRONT_END_ID [i] = interface->set_signal_out<Tcontext_t        > ("front_end_id" ,_param->_size_front_end_id);
	if (_param->_have_port_ooo_engine_id)
	out_RETIRE_OOO_ENGINE_ID[i] = interface->set_signal_out<Tcontext_t        > ("ooo_engine_id",_param->_size_ooo_engine_id);
	if (_param->_have_port_rob_id)
	out_RETIRE_ROB_ID       [i] = interface->set_signal_out<Tpacket_t         > ("rob_id"       ,_param->_size_rob_id);
	out_RETIRE_OPERATION    [i] = interface->set_signal_out<Toperation_t      > ("operation"    ,_param->_size_operation);
	out_RETIRE_TYPE         [i] = interface->set_signal_out<Ttype_t           > ("type"         ,_param->_size_type);
	out_RETIRE_HAS_IMMEDIAT [i] = interface->set_signal_out<Tcontrol_t        > ("has_immediat" ,1);
	out_RETIRE_IMMEDIAT     [i] = interface->set_signal_out<Tgeneral_data_t   > ("immediat"     ,_param->_size_general_data);
	out_RETIRE_DATA_RA      [i] = interface->set_signal_out<Tgeneral_data_t   > ("data_ra"      ,_param->_size_general_data);
	out_RETIRE_DATA_RB      [i] = interface->set_signal_out<Tgeneral_data_t   > ("data_rb"      ,_param->_size_general_data);
	out_RETIRE_DATA_RC      [i] = interface->set_signal_out<Tspecial_data_t   > ("data_rc"      ,_param->_size_special_data);
	out_RETIRE_WRITE_RD     [i] = interface->set_signal_out<Tcontrol_t        > ("write_rd"     ,1);
	out_RETIRE_NUM_REG_RD   [i] = interface->set_signal_out<Tgeneral_address_t> ("num_reg_rd"   ,_param->_size_general_register);
	out_RETIRE_WRITE_RE     [i] = interface->set_signal_out<Tcontrol_t        > ("write_re"     ,1);
	out_RETIRE_NUM_REG_RE   [i] = interface->set_signal_out<Tspecial_address_t> ("num_reg_re"   ,_param->_size_special_register);
      }

    // ~~~~~[ 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);
	 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);
	 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);
      }

    // ~~~~~[ Interface : "bypass_write" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (_param->_have_port_ooo_engine_id)
     in_BYPASS_WRITE_OOO_ENGINE_ID  = new SC_IN (Tcontext_t        ) * [_param->_nb_bypass_write];
     in_BYPASS_WRITE_GPR_VAL        = new SC_IN (Tcontrol_t        ) * [_param->_nb_bypass_write];
     in_BYPASS_WRITE_GPR_NUM_REG    = new SC_IN (Tgeneral_address_t) * [_param->_nb_bypass_write];
     in_BYPASS_WRITE_GPR_DATA       = new SC_IN (Tgeneral_data_t   ) * [_param->_nb_bypass_write];
     in_BYPASS_WRITE_SPR_VAL        = new SC_IN (Tcontrol_t        ) * [_param->_nb_bypass_write];
     in_BYPASS_WRITE_SPR_NUM_REG    = new SC_IN (Tspecial_address_t) * [_param->_nb_bypass_write];
     in_BYPASS_WRITE_SPR_DATA       = new SC_IN (Tspecial_data_t   ) * [_param->_nb_bypass_write];

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

	 if (_param->_have_port_ooo_engine_id)
         in_BYPASS_WRITE_OOO_ENGINE_ID [i] = interface->set_signal_in  <Tcontext_t        > ("ooo_engine_id" ,_param->_size_ooo_engine_id);
	 in_BYPASS_WRITE_GPR_VAL       [i] = interface->set_signal_valack_in ("gpr_val",VAL);		     
	 in_BYPASS_WRITE_GPR_NUM_REG   [i] = interface->set_signal_in  <Tgeneral_address_t> ("gpr_num_reg"   ,_param->_size_general_register);
	 in_BYPASS_WRITE_GPR_DATA      [i] = interface->set_signal_in  <Tgeneral_data_t   > ("gpr_data"      ,_param->_size_general_data);
	 in_BYPASS_WRITE_SPR_VAL       [i] = interface->set_signal_valack_in ("spr_val",VAL);		     
	 in_BYPASS_WRITE_SPR_NUM_REG   [i] = interface->set_signal_in  <Tspecial_address_t> ("spr_num_reg"   ,_param->_size_general_register);
	 in_BYPASS_WRITE_SPR_DATA      [i] = interface->set_signal_in  <Tspecial_data_t   > ("spr_data"      ,_param->_size_general_data);
      }

    // ~~~~~[ Interface : "bypass_memory" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     in_BYPASS_MEMORY_VAL          = new SC_IN (Tcontrol_t        ) * [_param->_nb_bypass_memory];
     if (_param->_have_port_ooo_engine_id)
     in_BYPASS_MEMORY_OOO_ENGINE_ID= new SC_IN (Tcontext_t        ) * [_param->_nb_bypass_memory];
     in_BYPASS_MEMORY_NUM_REG      = new SC_IN (Tgeneral_address_t) * [_param->_nb_bypass_memory];
     in_BYPASS_MEMORY_DATA         = new SC_IN (Tgeneral_data_t   ) * [_param->_nb_bypass_memory];

    for (uint32_t i=0; i<_param->_nb_bypass_memory; i++)
      {
        Interface_fifo * interface = _interfaces->set_interface("bypass_memory_"+toString(i)
#ifdef POSITION
                                                                , IN  
                                                                , NORTH
                                                                , "Interface with load/store unit to bypass the write in the RegisterFile."
#endif
                                                                );

	 in_BYPASS_MEMORY_VAL          [i] = interface->set_signal_valack_in (VAL);
	 if (_param->_have_port_ooo_engine_id)
         in_BYPASS_MEMORY_OOO_ENGINE_ID[i] = interface->set_signal_in  <Tcontext_t        > ("ooo_engine_id",_param->_size_ooo_engine_id);
	 in_BYPASS_MEMORY_NUM_REG      [i] = interface->set_signal_in  <Tgeneral_address_t> ("num_reg"      ,_param->_size_general_register);
	 in_BYPASS_MEMORY_DATA         [i] = interface->set_signal_in  <Tgeneral_data_t   > ("data"         ,_param->_size_general_data);
      }


    // ~~~~~[ internal ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    internal_RETIRE_VAL  = new Tcontrol_t [_param->_nb_inst_retire];
    internal_RETIRE_SLOT = new uint32_t   [_param->_nb_inst_retire];

    // ~~~~~[ Component ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    

#ifdef POSITION
    _component->generate_file();
#endif
#ifdef  SYSTEMC_VHDL_COMPATIBILITY
    _queue_valid   = new bool [_param->_size_queue];
#else
    _queue_control = new morpheo::behavioural::generic::queue_control::Queue_Control::Queue_Control(_param->_size_queue);
#endif
    _queue         = new Treservation_station_entry_t [_param->_size_queue];

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

}; // end namespace reservation_station
}; // 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
