/*
 * $Id: Issue_queue_allocation.cpp 122 2009-06-03 08:15:51Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Issue_queue/include/Issue_queue.h"
#include "Behavioural/include/Allocation.h"
#include "Common/include/Max.h"

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



#undef  FUNCTION
#define FUNCTION "Issue_queue::allocation"
  void Issue_queue::allocation (
#ifdef STATISTICS
			       morpheo::behavioural::Parameters_Statistics * param_statistics
#else
			       void
#endif
			       )
  {
    log_begin(Issue_queue,FUNCTION);

    _component   = new Component (_usage);

    Entity * entity = _component->set_entity (_name       
					      ,"Issue_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 : "issue_in" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC2_INTERFACE_BEGIN("issue_in", IN, WEST, _("Rename_out / Insert Rob interface"),_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
    
      _ALLOC2_VALACK_IN ( in_ISSUE_IN_VAL                  ,VAL,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_VALACK_OUT(out_ISSUE_IN_ACK                  ,ACK,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_CONTEXT_ID           ,"context_id"           ,Tcontext_t        ,_param->_size_context_id      ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_FRONT_END_ID         ,"front_end_id"         ,Tcontext_t        ,_param->_size_front_end_id    ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_PACKET_ID            ,"packet_id"            ,Tpacket_t         ,_param->_size_rob_ptr         ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_OPERATION            ,"operation"            ,Toperation_t      ,_param->_size_operation       ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_TYPE                 ,"type"                 ,Ttype_t           ,_param->_size_type            ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_STORE_QUEUE_PTR_WRITE,"store_queue_ptr_write",Tlsq_ptr_t        ,_param->_size_store_queue_ptr ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_STORE_QUEUE_PTR_READ ,"store_queue_ptr_read" ,Tlsq_ptr_t        ,_param->_size_store_queue_ptr ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_STORE_QUEUE_EMPTY    ,"store_queue_empty"    ,Tcontrol_t        ,1                             ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_LOAD_QUEUE_PTR_WRITE ,"load_queue_ptr_write" ,Tlsq_ptr_t        ,_param->_size_load_queue_ptr  ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_HAS_IMMEDIAT         ,"has_immediat"         ,Tcontrol_t        ,1                             ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_IMMEDIAT             ,"immediat"             ,Tgeneral_data_t   ,_param->_size_general_data    ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_READ_RA              ,"read_ra"              ,Tcontrol_t        ,1                             ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_NUM_REG_RA           ,"num_reg_ra"           ,Tgeneral_address_t,_param->_size_general_register,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_READ_RB              ,"read_rb"              ,Tcontrol_t        ,1                             ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_NUM_REG_RB           ,"num_reg_rb"           ,Tgeneral_address_t,_param->_size_general_register,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_READ_RC              ,"read_rc"              ,Tcontrol_t        ,1                             ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_NUM_REG_RC           ,"num_reg_rc"           ,Tspecial_address_t,_param->_size_special_register,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_WRITE_RD             ,"write_rd"             ,Tcontrol_t        ,1                             ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_NUM_REG_RD           ,"num_reg_rd"           ,Tgeneral_address_t,_param->_size_general_register,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_WRITE_RE             ,"write_re"             ,Tcontrol_t        ,1                             ,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
      _ALLOC2_SIGNAL_IN ( in_ISSUE_IN_NUM_REG_RE           ,"num_reg_re"           ,Tspecial_address_t,_param->_size_special_register,_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);

      ALLOC2_INTERFACE_END(_param->_nb_rename_unit, _param->_nb_inst_rename[it1]);
    }

    // ~~~~~[ Interface : "reexecute" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE_BEGIN("reexecute", IN, NORTH, _("Instruction reexecute (store head/ spr access)"),_param->_nb_inst_reexecute);
      
      ALLOC1_VALACK_IN ( in_REEXECUTE_VAL                  ,VAL);
      ALLOC1_VALACK_OUT(out_REEXECUTE_ACK                  ,ACK);
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_CONTEXT_ID           ,"context_id"           ,Tcontext_t        ,_param->_size_context_id      );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_FRONT_END_ID         ,"front_end_id"         ,Tcontext_t        ,_param->_size_front_end_id    );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_PACKET_ID            ,"packet_id"            ,Tpacket_t         ,_param->_size_rob_ptr         );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_OPERATION            ,"operation"            ,Toperation_t      ,_param->_size_operation       );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_TYPE                 ,"type"                 ,Ttype_t           ,_param->_size_type            );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_STORE_QUEUE_PTR_WRITE,"store_queue_ptr_write",Tlsq_ptr_t        ,_param->_size_store_queue_ptr );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_STORE_QUEUE_PTR_READ ,"store_queue_ptr_read" ,Tlsq_ptr_t        ,_param->_size_store_queue_ptr );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_STORE_QUEUE_EMPTY    ,"store_queue_empty"    ,Tcontrol_t        ,1);
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_LOAD_QUEUE_PTR_WRITE ,"load_queue_ptr_write" ,Tlsq_ptr_t        ,_param->_size_load_queue_ptr  );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_HAS_IMMEDIAT         ,"has_immediat"         ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_IMMEDIAT             ,"immediat"             ,Tgeneral_data_t   ,_param->_size_general_data    );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_READ_RA              ,"read_ra"              ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_NUM_REG_RA           ,"num_reg_ra"           ,Tgeneral_address_t,_param->_size_general_register);
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_READ_RB              ,"read_rb"              ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_NUM_REG_RB           ,"num_reg_rb"           ,Tgeneral_address_t,_param->_size_general_register);
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_READ_RC              ,"read_rc"              ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_NUM_REG_RC           ,"num_reg_rc"           ,Tspecial_address_t,_param->_size_special_register);
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_WRITE_RD             ,"write_rd"             ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_NUM_REG_RD           ,"num_reg_rd"           ,Tgeneral_address_t,_param->_size_general_register);
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_WRITE_RE             ,"write_re"             ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_IN ( in_REEXECUTE_NUM_REG_RE           ,"num_reg_re"           ,Tspecial_address_t,_param->_size_special_register);

      ALLOC1_INTERFACE_END(_param->_nb_inst_reexecute);
    }

    // ~~~~~[ Interface : "issue_out" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE_BEGIN("issue_out",OUT, EAST, _("Go to issue network"),_param->_nb_inst_issue);
      
      ALLOC1_VALACK_OUT(out_ISSUE_OUT_VAL                  ,VAL);
      ALLOC1_VALACK_IN ( in_ISSUE_OUT_ACK                  ,ACK);
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_CONTEXT_ID           ,"context_id"           ,Tcontext_t        ,_param->_size_context_id      );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_FRONT_END_ID         ,"front_end_id"         ,Tcontext_t        ,_param->_size_front_end_id    );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_PACKET_ID            ,"packet_id"            ,Tpacket_t         ,_param->_size_rob_ptr         );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_OPERATION            ,"operation"            ,Toperation_t      ,_param->_size_operation       );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_TYPE                 ,"type"                 ,Ttype_t           ,_param->_size_type            );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_STORE_QUEUE_PTR_WRITE,"store_queue_ptr_write",Tlsq_ptr_t        ,_param->_size_store_queue_ptr );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_STORE_QUEUE_PTR_READ ,"store_queue_ptr_read" ,Tlsq_ptr_t        ,_param->_size_store_queue_ptr );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_STORE_QUEUE_EMPTY    ,"store_queue_empty"    ,Tcontrol_t        ,1);
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_LOAD_QUEUE_PTR_WRITE ,"load_queue_ptr_write" ,Tlsq_ptr_t        ,_param->_size_load_queue_ptr  );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_HAS_IMMEDIAT         ,"has_immediat"         ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_IMMEDIAT             ,"immediat"             ,Tgeneral_data_t   ,_param->_size_general_data    );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_READ_RA              ,"read_ra"              ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_NUM_REG_RA           ,"num_reg_ra"           ,Tgeneral_address_t,_param->_size_general_register);
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_READ_RB              ,"read_rb"              ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_NUM_REG_RB           ,"num_reg_rb"           ,Tgeneral_address_t,_param->_size_general_register);
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_READ_RC              ,"read_rc"              ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_NUM_REG_RC           ,"num_reg_rc"           ,Tspecial_address_t,_param->_size_special_register);
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_WRITE_RD             ,"write_rd"             ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_NUM_REG_RD           ,"num_reg_rd"           ,Tgeneral_address_t,_param->_size_general_register);
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_WRITE_RE             ,"write_re"             ,Tcontrol_t        ,1                             );
      ALLOC1_SIGNAL_OUT(out_ISSUE_OUT_NUM_REG_RE           ,"num_reg_re"           ,Tspecial_address_t,_param->_size_special_register);

      ALLOC1_INTERFACE_END(_param->_nb_inst_issue);
    }

    if (usage_is_set(_usage,USE_SYSTEMC))
      {
    // ~~~~~[ Registers ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    ALLOC1(_issue_queue                     ,std::list<entry_t*>,_param->_nb_bank);

    // ~~~~~[ Internal ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ALLOC1(internal_BANK_IN_ACK             ,Tcontrol_t,_param->_nb_bank);
    ALLOC1(internal_BANK_IN_NUM_RENAME_UNIT ,uint32_t  ,_param->_nb_bank);
    ALLOC1(internal_BANK_IN_NUM_INST        ,uint32_t  ,_param->_nb_bank);

    ALLOC1(internal_ISSUE_OUT_VAL           ,Tcontrol_t,_param->_nb_inst_issue);
    ALLOC1(internal_ISSUE_OUT_FROM_REEXECUTE,Tcontrol_t,_param->_nb_inst_issue);
    ALLOC1(internal_ISSUE_OUT_NUM_BANK      ,uint32_t  ,_param->_nb_inst_issue);
    ALLOC1(internal_ISSUE_OUT_ENTRY         ,entry_t * ,_param->_nb_inst_issue);

    ALLOC1(internal_REEXECUTE_ACK           ,Tcontrol_t,_param->_nb_inst_reexecute);

    if (_param->_queue_scheme == ISSUE_QUEUE_SCHEME_OUT_OF_ORDER)
      {
    ALLOC1(internal_BANK_IN_ACK             ,Tcontrol_t,_param->_nb_bank);
    ALLOC1(internal_BANK_IN_NUM_RENAME_UNIT ,uint32_t  ,_param->_nb_bank);
    ALLOC1(internal_BANK_IN_NUM_INST        ,uint32_t  ,_param->_nb_bank);
      }
    if (_param->_queue_scheme == ISSUE_QUEUE_SCHEME_IN_ORDER)
      {
    ALLOC2(internal_ISSUE_IN_ACK            ,Tcontrol_t,_param->_nb_rename_unit,_param->_nb_inst_rename[it1]);
      }
      }

    // ~~~~~[ Component ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    _priority_in  = new generic::priority::Priority (_name+"_priority_in"   ,
						     _param->_priority      ,
						     _param->_load_balancing,
						     _param->_nb_rename_unit,
						     _param->_nb_inst_rename,
						     _param->_nb_rename_unit_select);

    if (_param->_queue_scheme == ISSUE_QUEUE_SCHEME_OUT_OF_ORDER)
      {
    _priority_out = new generic::priority::Priority (_name+"_priority_out"  ,
						     _param->_priority      ,
						     _param->_nb_bank,
						     _param->_nb_bank);

    _priority_reg = new generic::priority::Priority (_name+"_priority_reg"  ,
						     _param->_priority      ,
						     _param->_nb_bank,
						     _param->_nb_bank);
      }

#ifdef POSITION
    if (usage_is_set(_usage,USE_POSITION))
      _component->generate_file();
#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              
