#ifndef morpheo_behavioural_core_multi_ooo_engine_ooo_engine_issue_queue_Issue_queue_h
#define morpheo_behavioural_core_multi_ooo_engine_ooo_engine_issue_queue_Issue_queue_h

/*
 * $Id: Issue_queue.h 111 2009-02-27 18:37:40Z rosiere $
 *
 * [ Description ]
 * 
 */

#ifdef SYSTEMC
#include "systemc.h"
#endif


#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Issue_queue/include/Parameters.h"
#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Issue_queue/include/Types.h"
#ifdef STATISTICS
#include "Behavioural/include/Stat.h"
#endif
#include "Behavioural/include/Component.h"
#ifdef VHDL
#include "Behavioural/include/Vhdl.h"
#endif
#include "Behavioural/include/Usage.h"

#include "Common/include/ToString.h"
#include "Common/include/Debug.h"

#include "Behavioural/Generic/Priority/include/Priority.h"
#include <iostream>

namespace morpheo {
namespace behavioural {

namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace issue_queue {


  class Issue_queue 
#if SYSTEMC
    : public sc_module
#endif
  {
    // -----[ fields ]----------------------------------------------------
    // Parameters
  protected : const std::string  _name;
  protected : const Parameters * _param;
  private   : const Tusage_t     _usage;

#ifdef STATISTICS
  public    : Stat                           * _stat;
  private   : counter_t                     ** _stat_bank_nb_inst;
  private   : counter_t                      * _stat_nb_inst_reexecute;
  private   : counter_t                     ** _stat_nb_inst_issue_in;
  private   : counter_t                      * _stat_nb_inst_issue_out;
#endif

  public    : Component                      * _component;
  private   : Interfaces                     * _interfaces;

#ifdef SYSTEMC
    // ~~~~~[ Interface ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // ~~~~~[ Interface : "" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  public    : SC_CLOCK                      *  in_CLOCK        ;
  public    : SC_IN (Tcontrol_t)            *  in_NRESET       ;

    // ~~~~~[ Interface : "issue_in" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  public    : SC_IN (Tcontrol_t        )  ***  in_ISSUE_IN_VAL                   ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_OUT(Tcontrol_t        )  *** out_ISSUE_IN_ACK                   ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tcontext_t        )  ***  in_ISSUE_IN_CONTEXT_ID            ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tcontext_t        )  ***  in_ISSUE_IN_FRONT_END_ID          ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tpacket_t         )  ***  in_ISSUE_IN_PACKET_ID             ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Toperation_t      )  ***  in_ISSUE_IN_OPERATION             ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Ttype_t           )  ***  in_ISSUE_IN_TYPE                  ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tlsq_ptr_t        )  ***  in_ISSUE_IN_STORE_QUEUE_PTR_WRITE ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tlsq_ptr_t        )  ***  in_ISSUE_IN_LOAD_QUEUE_PTR_WRITE  ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tcontrol_t        )  ***  in_ISSUE_IN_HAS_IMMEDIAT          ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tgeneral_data_t   )  ***  in_ISSUE_IN_IMMEDIAT              ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tcontrol_t        )  ***  in_ISSUE_IN_READ_RA               ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tgeneral_address_t)  ***  in_ISSUE_IN_NUM_REG_RA            ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tcontrol_t        )  ***  in_ISSUE_IN_READ_RB               ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tgeneral_address_t)  ***  in_ISSUE_IN_NUM_REG_RB            ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tcontrol_t        )  ***  in_ISSUE_IN_READ_RC               ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tspecial_address_t)  ***  in_ISSUE_IN_NUM_REG_RC            ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tcontrol_t        )  ***  in_ISSUE_IN_WRITE_RD              ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tgeneral_address_t)  ***  in_ISSUE_IN_NUM_REG_RD            ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tcontrol_t        )  ***  in_ISSUE_IN_WRITE_RE              ;//[nb_rename_unit][nb_inst_rename]
  public    : SC_IN (Tspecial_address_t)  ***  in_ISSUE_IN_NUM_REG_RE            ;//[nb_rename_unit][nb_inst_rename]

    // ~~~~~[ Interface : "reexecute" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  public    : SC_IN (Tcontrol_t        )   **  in_REEXECUTE_VAL                  ;//[nb_inst_reexecute]
  public    : SC_OUT(Tcontrol_t        )   ** out_REEXECUTE_ACK                  ;//[nb_inst_reexecute]
  public    : SC_IN (Tcontext_t        )   **  in_REEXECUTE_CONTEXT_ID           ;//[nb_inst_reexecute]
  public    : SC_IN (Tcontext_t        )   **  in_REEXECUTE_FRONT_END_ID         ;//[nb_inst_reexecute]
  public    : SC_IN (Tpacket_t         )   **  in_REEXECUTE_PACKET_ID            ;//[nb_inst_reexecute]
  public    : SC_IN (Toperation_t      )   **  in_REEXECUTE_OPERATION            ;//[nb_inst_reexecute]
  public    : SC_IN (Ttype_t           )   **  in_REEXECUTE_TYPE                 ;//[nb_inst_reexecute]
  public    : SC_IN (Tlsq_ptr_t        )   **  in_REEXECUTE_STORE_QUEUE_PTR_WRITE;//[nb_inst_reexecute]
  public    : SC_IN (Tlsq_ptr_t        )   **  in_REEXECUTE_LOAD_QUEUE_PTR_WRITE ;//[nb_inst_reexecute]
  public    : SC_IN (Tcontrol_t        )   **  in_REEXECUTE_HAS_IMMEDIAT         ;//[nb_inst_reexecute]
  public    : SC_IN (Tgeneral_data_t   )   **  in_REEXECUTE_IMMEDIAT             ;//[nb_inst_reexecute]
  public    : SC_IN (Tcontrol_t        )   **  in_REEXECUTE_READ_RA              ;//[nb_inst_reexecute]
  public    : SC_IN (Tgeneral_address_t)   **  in_REEXECUTE_NUM_REG_RA           ;//[nb_inst_reexecute]
  public    : SC_IN (Tcontrol_t        )   **  in_REEXECUTE_READ_RB              ;//[nb_inst_reexecute]
  public    : SC_IN (Tgeneral_address_t)   **  in_REEXECUTE_NUM_REG_RB           ;//[nb_inst_reexecute]
  public    : SC_IN (Tcontrol_t        )   **  in_REEXECUTE_READ_RC              ;//[nb_inst_reexecute]
  public    : SC_IN (Tspecial_address_t)   **  in_REEXECUTE_NUM_REG_RC           ;//[nb_inst_reexecute]
  public    : SC_IN (Tcontrol_t        )   **  in_REEXECUTE_WRITE_RD             ;//[nb_inst_reexecute]
  public    : SC_IN (Tgeneral_address_t)   **  in_REEXECUTE_NUM_REG_RD           ;//[nb_inst_reexecute]
  public    : SC_IN (Tcontrol_t        )   **  in_REEXECUTE_WRITE_RE             ;//[nb_inst_reexecute]
  public    : SC_IN (Tspecial_address_t)   **  in_REEXECUTE_NUM_REG_RE           ;//[nb_inst_reexecute]

    // ~~~~~[ Interface : "issue_out" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  public    : SC_OUT(Tcontrol_t        )   ** out_ISSUE_OUT_VAL                  ;//[nb_inst_issue]
  public    : SC_IN (Tcontrol_t        )   **  in_ISSUE_OUT_ACK                  ;//[nb_inst_issue]
  public    : SC_OUT(Tcontext_t        )   ** out_ISSUE_OUT_CONTEXT_ID           ;//[nb_inst_issue]
  public    : SC_OUT(Tcontext_t        )   ** out_ISSUE_OUT_FRONT_END_ID         ;//[nb_inst_issue]
  public    : SC_OUT(Tpacket_t         )   ** out_ISSUE_OUT_PACKET_ID            ;//[nb_inst_issue]
  public    : SC_OUT(Toperation_t      )   ** out_ISSUE_OUT_OPERATION            ;//[nb_inst_issue]
  public    : SC_OUT(Ttype_t           )   ** out_ISSUE_OUT_TYPE                 ;//[nb_inst_issue]
  public    : SC_OUT(Tlsq_ptr_t        )   ** out_ISSUE_OUT_STORE_QUEUE_PTR_WRITE;//[nb_inst_issue]
  public    : SC_OUT(Tlsq_ptr_t        )   ** out_ISSUE_OUT_LOAD_QUEUE_PTR_WRITE ;//[nb_inst_issue]
  public    : SC_OUT(Tcontrol_t        )   ** out_ISSUE_OUT_HAS_IMMEDIAT         ;//[nb_inst_issue]
  public    : SC_OUT(Tgeneral_data_t   )   ** out_ISSUE_OUT_IMMEDIAT             ;//[nb_inst_issue]
  public    : SC_OUT(Tcontrol_t        )   ** out_ISSUE_OUT_READ_RA              ;//[nb_inst_issue]
  public    : SC_OUT(Tgeneral_address_t)   ** out_ISSUE_OUT_NUM_REG_RA           ;//[nb_inst_issue]
  public    : SC_OUT(Tcontrol_t        )   ** out_ISSUE_OUT_READ_RB              ;//[nb_inst_issue]
  public    : SC_OUT(Tgeneral_address_t)   ** out_ISSUE_OUT_NUM_REG_RB           ;//[nb_inst_issue]
  public    : SC_OUT(Tcontrol_t        )   ** out_ISSUE_OUT_READ_RC              ;//[nb_inst_issue]
  public    : SC_OUT(Tspecial_address_t)   ** out_ISSUE_OUT_NUM_REG_RC           ;//[nb_inst_issue]
  public    : SC_OUT(Tcontrol_t        )   ** out_ISSUE_OUT_WRITE_RD             ;//[nb_inst_issue]
  public    : SC_OUT(Tgeneral_address_t)   ** out_ISSUE_OUT_NUM_REG_RD           ;//[nb_inst_issue]
  public    : SC_OUT(Tcontrol_t        )   ** out_ISSUE_OUT_WRITE_RE             ;//[nb_inst_issue]
  public    : SC_OUT(Tspecial_address_t)   ** out_ISSUE_OUT_NUM_REG_RE           ;//[nb_inst_issue]

    // ~~~~~[ Component ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
  private   : generic::priority::Priority   * _priority_in ;

    // in_order implementation only
    // out_of_order implementation only
  private   : generic::priority::Priority   * _priority_reg;
  private   : generic::priority::Priority   * _priority_out;

    // ~~~~~[ Register ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    // common implementation
  private   : std::list<entry_t*>           * _issue_queue;
  private   : std::list<entry_t*>             _reexecute_queue;

    // in_order implementation only
  private   : uint32_t                        reg_NUM_BANK_HEAD;
  private   : uint32_t                        reg_NUM_BANK_TAIL;
    // out_of_order implementation only
  
    // ~~~~~[ Internal ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // common implementation
  private   : Tcontrol_t                    * internal_ISSUE_OUT_VAL            ;//[nb_inst_issue]
  private   : Tcontrol_t                    * internal_ISSUE_OUT_FROM_REEXECUTE ;//[nb_inst_issue]
  private   : uint32_t                      * internal_ISSUE_OUT_NUM_BANK       ;//[nb_inst_issue]
  private   : entry_t *                     * internal_ISSUE_OUT_ENTRY          ;//[nb_inst_issue]

  private   : Tcontrol_t                    * internal_REEXECUTE_ACK            ;//[nb_inst_reexecute]

    // in_order implementation only
  private   : Tcontrol_t                    * internal_BANK_IN_ACK              ;//[nb_bank]
  private   : uint32_t                      * internal_BANK_IN_NUM_RENAME_UNIT  ;//[nb_bank]
  private   : uint32_t                      * internal_BANK_IN_NUM_INST         ;//[nb_bank]
    // out_of_order implementation only
  public    : Tcontrol_t                   ** internal_ISSUE_IN_ACK             ;//[nb_rename_unit][nb_inst_rename]

    // function pointer
  public    : void (morpheo::behavioural::core::multi_ooo_engine::ooo_engine::issue_queue::Issue_queue::*function_transition) (void);
  public    : void (morpheo::behavioural::core::multi_ooo_engine::ooo_engine::issue_queue::Issue_queue::*function_genMoore  ) (void);
  public    : void (morpheo::behavioural::core::multi_ooo_engine::ooo_engine::issue_queue::Issue_queue::*function_genMealy_issue_in ) (void);
  public    : void (morpheo::behavioural::core::multi_ooo_engine::ooo_engine::issue_queue::Issue_queue::*function_genMealy_issue_out) (void);
#endif

    // -----[ Methods ]---------------------------------------------------

#ifdef SYSTEMC
    SC_HAS_PROCESS (Issue_queue);
#endif
  public  :          Issue_queue              
  (
#ifdef SYSTEMC
   sc_module_name                                name,
#else					       
   std::string                                   name,
#endif					       
#ifdef STATISTICS
   morpheo::behavioural::Parameters_Statistics * param_statistics,
#endif
   Parameters                                  * param,
   morpheo::behavioural::Tusage_t                usage
   );
  public  :          ~Issue_queue             (void);
					       
  private : void        allocation                (
#ifdef STATISTICS
						   morpheo::behavioural::Parameters_Statistics * param_statistics
#else
						   void
#endif
						   );
  private : void        deallocation              (void);
					       
#ifdef SYSTEMC				       
  public  : void        transition                          (void);
  public  : void        genMoore                            (void);
  public  : void        genMealy_issue_in                   (void);
  public  : void        genMealy_issue_out                  (void);

  public  : void        function_in_order_transition        (void);
  public  : void        function_in_order_genMealy_issue_out(void);
  public  : void        function_in_order_genMoore          (void);

  public  : void        function_out_of_order_transition    (void);
  public  : void        function_out_of_order_genMoore      (void);
#endif					       

#if VHDL				       
  public  : void        vhdl                      (void);
  private : void        vhdl_declaration          (Vhdl * & vhdl);
  private : void        vhdl_body                 (Vhdl * & vhdl);
#endif					       

#ifdef STATISTICS
  public  : void        statistics_allocation     (morpheo::behavioural::Parameters_Statistics * param_statistics);
  public  : void        statistics_deallocation   (void);
#endif
#if defined(STATISTICS) or defined(VHDL_TESTBENCH)
  private : void        end_cycle                 (void);
#endif
  };

}; // end namespace issue_queue
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core

}; // end namespace behavioural
}; // end namespace morpheo              

#endif
