/*
 * $Id: Update_Prediction_Table_allocation.cpp 98 2008-12-31 10:18:08Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Update_Prediction_Table/include/Update_Prediction_Table.h"
#include "Behavioural/include/Allocation.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_front_end {
namespace front_end {
namespace prediction_unit {
namespace update_prediction_table {



#undef  FUNCTION
#define FUNCTION "Update_Prediction_Table::allocation"
  void Update_Prediction_Table::allocation (
#ifdef STATISTICS
			       morpheo::behavioural::Parameters_Statistics * param_statistics
#else
			       void
#endif
			       )
  {
    log_printf(FUNC,Update_Prediction_Table,FUNCTION,"Begin");

    _component   = new Component (_usage);

    Entity * entity = _component->set_entity (_name       
					      ,"Update_Prediction_Table"
#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 : "predict" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("predict", IN,SOUTH, "predict", _param->_nb_inst_predict);
      
      ALLOC1_VALACK_IN ( in_PREDICT_VAL                 ,VAL);
      ALLOC1_VALACK_OUT(out_PREDICT_ACK                 ,ACK);
      ALLOC1_SIGNAL_IN ( in_PREDICT_CONTEXT_ID          ,"context_id"          ,Tcontext_t         ,_param->_size_context_id);
      ALLOC1_SIGNAL_OUT(out_PREDICT_UPDATE_PREDICTION_ID,"update_prediction_id",Tprediction_ptr_t  ,_param->_size_depth);
      ALLOC1_SIGNAL_IN ( in_PREDICT_BTB_ADDRESS_SRC     ,"btb_address_src"     ,Taddress_t         ,_param->_size_instruction_address);
      ALLOC1_SIGNAL_IN ( in_PREDICT_BTB_ADDRESS_DEST    ,"btb_address_dest"    ,Taddress_t         ,_param->_size_instruction_address);
      ALLOC1_SIGNAL_IN ( in_PREDICT_BTB_CONDITION       ,"btb_condition"       ,Tbranch_condition_t,_param->_size_branch_condition);
      ALLOC1_SIGNAL_IN ( in_PREDICT_BTB_LAST_TAKE       ,"btb_last_take"       ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_IN ( in_PREDICT_BTB_IS_ACCURATE     ,"btb_is_accurate"     ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_IN ( in_PREDICT_DIR_HISTORY         ,"dir_history"         ,Thistory_t         ,_param->_size_history);
      ALLOC1_SIGNAL_IN ( in_PREDICT_RAS_ADDRESS         ,"ras_address"         ,Taddress_t         ,_param->_size_instruction_address);
      ALLOC1_SIGNAL_IN ( in_PREDICT_RAS_INDEX           ,"ras_index"           ,Tptr_t             ,_param->_max_size_ras_index);
    }

    // ~~~~~[ Interface : "decod" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("decod", IN,SOUTH, "decod", _param->_nb_inst_decod);

      ALLOC1_VALACK_IN ( in_DECOD_VAL                 ,VAL);
      ALLOC1_VALACK_OUT(out_DECOD_ACK                 ,ACK);
      ALLOC1_SIGNAL_IN ( in_DECOD_CONTEXT_ID          ,"context_id"          ,Tcontext_t         ,_param->_size_context_id);
      ALLOC1_SIGNAL_IN ( in_DECOD_BTB_ADDRESS_SRC     ,"btb_address_src"     ,Taddress_t         ,_param->_size_instruction_address);
      ALLOC1_SIGNAL_IN ( in_DECOD_BTB_ADDRESS_DEST    ,"btb_address_dest"    ,Taddress_t         ,_param->_size_instruction_address);
      ALLOC1_SIGNAL_IN ( in_DECOD_BTB_CONDITION       ,"btb_condition"       ,Tbranch_condition_t,_param->_size_branch_condition);
      ALLOC1_SIGNAL_IN ( in_DECOD_BTB_LAST_TAKE       ,"btb_last_take"       ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_IN ( in_DECOD_RAS_ADDRESS         ,"ras_address"         ,Taddress_t         ,_param->_size_instruction_address);
      ALLOC1_SIGNAL_IN ( in_DECOD_RAS_INDEX           ,"ras_index"           ,Tptr_t             ,_param->_max_size_ras_index);
      ALLOC1_SIGNAL_IN ( in_DECOD_MISS_IFETCH         ,"miss_ifetch"         ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_IN ( in_DECOD_MISS_DECOD          ,"miss_decod"          ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_IN ( in_DECOD_UPDATE_PREDICTION_ID,"update_prediction_id",Tprediction_ptr_t  ,_param->_size_depth);
//    ALLOC1_SIGNAL_OUT(out_DECOD_DEPTH               ,"depth"               ,Tdepth_t           ,_param->_size_depth);
      ALLOC1_SIGNAL_IN ( in_DECOD_IS_ACCURATE         ,"is_accurate"         ,Tcontrol_t         ,1);
    }

    // ~~~~~[ Interface : "branch_complete" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("branch_complete", IN,SOUTH, "branch_complete", _param->_nb_inst_branch_complete);
      
      ALLOC1_VALACK_IN ( in_BRANCH_COMPLETE_VAL            ,VAL);
      ALLOC1_VALACK_OUT(out_BRANCH_COMPLETE_ACK            ,ACK);
      ALLOC1_SIGNAL_IN ( in_BRANCH_COMPLETE_CONTEXT_ID     ,"context_id"     ,Tcontext_t,_param->_size_context_id);
      ALLOC1_SIGNAL_IN ( in_BRANCH_COMPLETE_DEPTH          ,"depth"          ,Tdepth_t  ,_param->_size_depth);
      ALLOC1_SIGNAL_IN ( in_BRANCH_COMPLETE_ADDRESS        ,"address"        ,Taddress_t,_param->_size_instruction_address);
      ALLOC1_SIGNAL_IN ( in_BRANCH_COMPLETE_NO_SEQUENCE    ,"no_sequence"    ,Tcontrol_t,1);
      ALLOC1_SIGNAL_OUT(out_BRANCH_COMPLETE_MISS_PREDICTION,"miss_prediction",Tcontrol_t,1);
      ALLOC1_SIGNAL_OUT(out_BRANCH_COMPLETE_TAKE           ,"take"           ,Tcontrol_t,1);
      ALLOC1_SIGNAL_OUT(out_BRANCH_COMPLETE_ADDRESS_SRC    ,"address_src"    ,Taddress_t,_param->_size_instruction_address);
      ALLOC1_SIGNAL_OUT(out_BRANCH_COMPLETE_ADDRESS_DEST   ,"address_dest"   ,Taddress_t,_param->_size_instruction_address);
    }

    // ~~~~~[ Interface : "branch_event" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("branch_event", IN,SOUTH, "branch_event", _param->_nb_context);
      
      ALLOC1_VALACK_OUT(out_BRANCH_EVENT_VAL              ,VAL);
      ALLOC1_VALACK_IN ( in_BRANCH_EVENT_ACK              ,ACK);
//    ALLOC1_SIGNAL_OUT(out_BRANCH_EVENT_CONTEXT_ID       ,"context_id"      ,Tcontext_t,_param->_size_context_id);
      ALLOC1_SIGNAL_OUT(out_BRANCH_EVENT_DEPTH            ,"depth"           ,Tdepth_t  ,_param->_size_depth);
//    ALLOC1_SIGNAL_OUT(out_BRANCH_EVENT_MISS_PREDICTION  ,"miss_prediction" ,Tcontrol_t,1);
      ALLOC1_SIGNAL_OUT(out_BRANCH_EVENT_ADDRESS_SRC      ,"address_src"     ,Taddress_t,_param->_size_instruction_address);
      ALLOC1_SIGNAL_OUT(out_BRANCH_EVENT_ADDRESS_DEST_VAL ,"address_dest_val",Tcontrol_t,1);
      ALLOC1_SIGNAL_OUT(out_BRANCH_EVENT_ADDRESS_DEST     ,"address_dest"    ,Taddress_t,_param->_size_instruction_address);
    }

    // ~~~~~[ Interface : "update" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("update",OUT,SOUTH, "update", _param->_nb_inst_update);

      ALLOC1_VALACK_OUT(out_UPDATE_VAL                  ,VAL);
      ALLOC1_VALACK_IN ( in_UPDATE_ACK                  ,ACK);
      ALLOC1_SIGNAL_OUT(out_UPDATE_CONTEXT_ID           ,"context_id"           ,Tcontext_t         ,_param->_size_context_id);
      ALLOC1_SIGNAL_OUT(out_UPDATE_MISS_PREDICTION      ,"miss_prediction"      ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_OUT(out_UPDATE_DIRECTION_GOOD       ,"direction_good"       ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_OUT(out_UPDATE_BTB_VAL              ,"btb_val"              ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_OUT(out_UPDATE_BTB_ADDRESS_SRC      ,"btb_address_src"      ,Taddress_t         ,_param->_size_instruction_address);
      ALLOC1_SIGNAL_OUT(out_UPDATE_BTB_ADDRESS_DEST     ,"btb_address_dest"     ,Taddress_t         ,_param->_size_instruction_address);
      ALLOC1_SIGNAL_OUT(out_UPDATE_BTB_CONDITION        ,"btb_condition"        ,Tbranch_condition_t,_param->_size_branch_condition);
      ALLOC1_SIGNAL_OUT(out_UPDATE_DIR_VAL              ,"dir_val"              ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_OUT(out_UPDATE_DIR_HISTORY          ,"dir_history"          ,Thistory_t         ,_param->_size_history);
      ALLOC1_SIGNAL_OUT(out_UPDATE_RAS_VAL              ,"ras_val"              ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_OUT(out_UPDATE_RAS_FLUSH            ,"ras_flush"            ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_OUT(out_UPDATE_RAS_PUSH             ,"ras_push"             ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_OUT(out_UPDATE_RAS_ADDRESS          ,"ras_address"          ,Taddress_t         ,_param->_size_instruction_address);
      ALLOC1_SIGNAL_OUT(out_UPDATE_RAS_INDEX            ,"ras_index"            ,Tptr_t             ,_param->_max_size_ras_index);
      ALLOC1_SIGNAL_OUT(out_UPDATE_RAS_PREDICTION_IFETCH,"ras_prediction_ifetch",Tcontrol_t         ,1);
    }

    // ~~~~~[ Interface : "event" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("event", IN,SOUTH,"event", _param->_nb_context);

      ALLOC1_VALACK_IN ( in_EVENT_VAL    ,VAL);
      ALLOC1_VALACK_OUT(out_EVENT_ACK    ,ACK);
      ALLOC1_SIGNAL_IN ( in_EVENT_TYPE   ,"type" ,Tevent_type_t ,_param->_size_event_type );
      ALLOC1_SIGNAL_IN ( in_EVENT_DEPTH  ,"depth",Tdepth_t      ,_param->_size_depth      );
    }

    // ~~~~~[ Interface : "depth" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("depth",OUT,SOUTH, "depth", _param->_nb_context);
      ALLOC1_SIGNAL_OUT(out_DEPTH_CURRENT,"CURRENT",Tdepth_t,_param->_size_depth);
      ALLOC1_SIGNAL_OUT(out_DEPTH_MIN    ,"MIN"    ,Tdepth_t,_param->_size_depth);
      ALLOC1_SIGNAL_OUT(out_DEPTH_MAX    ,"MAX"    ,Tdepth_t,_param->_size_depth+1);
    }

    if (usage_is_set(_usage,USE_SYSTEMC))
      {
    // ~~~~~[ Internal ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ALLOC1(internal_PREDICT_ACK                     ,Tcontrol_t,_param->_nb_inst_predict);
    ALLOC1(internal_PREDICT_UPDATE_PREDICTION_ID    ,Tdepth_t  ,_param->_nb_inst_predict);
    ALLOC1(internal_DECOD_ACK                       ,Tcontrol_t,_param->_nb_inst_decod);
    ALLOC1(internal_DECOD_UPT_PTR_WRITE             ,uint32_t  ,_param->_nb_inst_decod);
    ALLOC1(internal_BRANCH_COMPLETE_ACK             ,Tcontrol_t,_param->_nb_inst_branch_complete);
    ALLOC1(internal_BRANCH_COMPLETE_MISS_PREDICTION ,Tcontrol_t,_param->_nb_inst_branch_complete);
    ALLOC1(internal_BRANCH_COMPLETE_TAKE            ,Tcontrol_t,_param->_nb_inst_branch_complete);
    ALLOC1(internal_BRANCH_COMPLETE_ADDRESS_DEST    ,Taddress_t,_param->_nb_inst_branch_complete);
    ALLOC1(internal_BRANCH_EVENT_VAL                ,Tcontrol_t,_param->_nb_context);
    ALLOC1(internal_BRANCH_EVENT_DEPTH              ,Tdepth_t  ,_param->_nb_context);
    ALLOC1(internal_UPDATE_VAL                      ,Tcontrol_t,_param->_nb_inst_update);
    ALLOC1(internal_UPDATE_VAL_WITHOUT_ACK          ,Tcontrol_t,_param->_nb_inst_update);
    ALLOC1(internal_UPDATE_CONTEXT_ID               ,Tcontext_t,_param->_nb_inst_update);
    ALLOC1(internal_UPDATE_FROM_UFPT                ,bool      ,_param->_nb_inst_update);
    ALLOC1(internal_UPDATE_DEPTH                    ,Tdepth_t  ,_param->_nb_inst_update);
    ALLOC1(internal_UPDATE_RAS                      ,bool      ,_param->_nb_inst_update);
    ALLOC1(internal_EVENT_ACK                       ,Tcontrol_t,_param->_nb_context);

    // ~~~~~[ Register ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    

    ALLOC1(reg_IS_ACCURATE                  ,bool         ,_param->_nb_context);
                                                          
    ALLOC2(reg_UPDATE_FETCH_PREDICTION_TABLE,ufpt_entry_t ,_param->_nb_context,_param->_size_ufpt_queue[it1]);
    ALLOC1(reg_UFPT_BOTTOM                  ,uint32_t     ,_param->_nb_context);
    ALLOC1(reg_UFPT_TOP                     ,uint32_t     ,_param->_nb_context);
    ALLOC1(reg_UFPT_UPDATE                  ,uint32_t     ,_param->_nb_context);
    ALLOC1(reg_UFPT_NB_NEED_UPDATE          ,uint32_t     ,_param->_nb_context);
                                                          
    ALLOC2(reg_UPDATE_PREDICTION_TABLE      ,upt_entry_t  ,_param->_nb_context,_param->_size_upt_queue[it1]);
    ALLOC1(reg_UPT_BOTTOM                   ,uint32_t     ,_param->_nb_context);
    ALLOC1(reg_UPT_TOP                      ,uint32_t     ,_param->_nb_context);
    ALLOC1(reg_UPT_TOP_EVENT                ,uint32_t     ,_param->_nb_context);
    ALLOC1(reg_UPT_UPDATE                   ,uint32_t     ,_param->_nb_context);

    ALLOC1(reg_EVENT_STATE                  ,event_state_t,_param->_nb_context);
    ALLOC1(reg_EVENT_DEPTH                  ,Tdepth_t     ,_param->_nb_context);
    ALLOC1(reg_EVENT_ADDRESS_SRC            ,Taddress_t   ,_param->_nb_context);
    ALLOC1(reg_EVENT_ADDRESS_DEST_VAL       ,Tcontrol_t   ,_param->_nb_context);
    ALLOC1(reg_EVENT_ADDRESS_DEST           ,Taddress_t   ,_param->_nb_context);
      }

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

#ifdef POSITION
    if (usage_is_set(_usage,USE_POSITION))
      _component->generate_file();
#endif

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

}; // end namespace update_prediction_table
}; // end namespace prediction_unit
}; // end namespace front_end
}; // end namespace multi_front_end
}; // end namespace core

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