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

#include "Behavioural/Stage_1_Ifetch/Predictor/Meta_Predictor/Two_Level_Branch_Predictor/include/Two_Level_Branch_Predictor.h"

namespace morpheo                    {
namespace behavioural {
namespace stage_1_ifetch {
namespace predictor {
namespace meta_predictor {
namespace two_level_branch_predictor {

  void Two_Level_Branch_Predictor::allocation (void)
  {
    string rename;

    log_printf(FUNC,Two_Level_Branch_Predictor,"allocation","Begin");

     in_CLOCK  = new SC_CLOCK           ("in_CLOCK");

     in_PREDICT_VAL                 = new SC_IN (Tcontrol_t)     * [_param._nb_prediction     ];
    out_PREDICT_ACK                 = new SC_OUT(Tcontrol_t)     * [_param._nb_prediction     ];
     in_PREDICT_ADDRESS             = new SC_IN (Taddress_t)     * [_param._nb_prediction     ];
    if (_param._have_bht)
    out_PREDICT_BHT_HISTORY         = new SC_OUT(Tbht_history_t) * [_param._nb_prediction     ];
    if (_param._have_pht)
    out_PREDICT_PHT_HISTORY         = new SC_OUT(Tpht_history_t) * [_param._nb_prediction     ];
    if (_param._have_bht)
      {
    signal_PREDICT_BHT_ACK          = new SC_SIGNAL(Tcontrol_t)     * [_param._nb_prediction];
    signal_PREDICT_BHT_ADDRESS      = new SC_SIGNAL(Taddress_t)     * [_param._nb_prediction];
      }
    if (_param._have_pht)
      {
    signal_PREDICT_PHT_ACK          = new SC_SIGNAL(Tcontrol_t)     * [_param._nb_prediction];
    signal_PREDICT_PHT_ADDRESS      = new SC_SIGNAL(Taddress_t)     * [_param._nb_prediction];
      }

    for (uint32_t i=0; i<_param._nb_prediction; i++)
      {
	rename = "in_PREDICT_VAL_"         +toString(i);
	 in_PREDICT_VAL                 [i] = new SC_IN (Tcontrol_t)     (rename.c_str());

	rename = "out_PREDICT_ACK_"        +toString(i);
	out_PREDICT_ACK                 [i] = new SC_OUT(Tcontrol_t)     (rename.c_str());

	rename = "in_PREDICT_ADDRESS_"     +toString(i);
	 in_PREDICT_ADDRESS             [i] = new SC_IN (Taddress_t)     (rename.c_str());

	if (_param._have_bht)
	  {
	rename = "out_PREDICT_BHT_HISTORY_"+toString(i);
	out_PREDICT_BHT_HISTORY         [i] = new SC_OUT(Tbht_history_t) (rename.c_str());
	  }

	if (_param._have_pht)
	  {
    	rename = "out_PREDICT_PHT_HISTORY_"+toString(i);
	out_PREDICT_PHT_HISTORY         [i] = new SC_OUT(Tpht_history_t) (rename.c_str());
	  }

	if (_param._have_bht)
	  {
	rename = "signal_PREDICT_BHT_ACK_"    +toString(i);
	signal_PREDICT_BHT_ACK          [i] = new SC_SIGNAL(Tcontrol_t)     (rename.c_str());

	rename = "signal_PREDICT_BHT_ADDRESS_"+toString(i);
	signal_PREDICT_BHT_ADDRESS      [i] = new SC_SIGNAL(Taddress_t)     (rename.c_str());
	  }

	if (_param._have_pht)
	  {
	rename = "signal_PREDICT_PHT_ACK_"    +toString(i);
	signal_PREDICT_PHT_ACK          [i] = new SC_SIGNAL(Tcontrol_t)     (rename.c_str());

	rename = "signal_PREDICT_PHT_ADDRESS_"+toString(i);
	signal_PREDICT_PHT_ADDRESS      [i] = new SC_SIGNAL(Taddress_t)     (rename.c_str());
	  }
      }

     in_BRANCH_COMPLETE_VAL         = new SC_IN (Tcontrol_t)     * [_param._nb_branch_complete];
    out_BRANCH_COMPLETE_ACK         = new SC_OUT(Tcontrol_t)     * [_param._nb_branch_complete];
     in_BRANCH_COMPLETE_ADDRESS     = new SC_IN (Taddress_t)     * [_param._nb_branch_complete];
    if (_param._have_bht)
     in_BRANCH_COMPLETE_BHT_HISTORY = new SC_IN (Tbht_history_t) * [_param._nb_branch_complete];
    if (_param._have_pht)
     in_BRANCH_COMPLETE_PHT_HISTORY = new SC_IN (Tpht_history_t) * [_param._nb_branch_complete];
     in_BRANCH_COMPLETE_DIRECTION   = new SC_IN (Tcontrol_t)     * [_param._nb_branch_complete];
    if (_param._have_bht)
      {
    signal_BRANCH_COMPLETE_BHT_ACK     = new SC_SIGNAL(Tcontrol_t) * [_param._nb_branch_complete];
    signal_BRANCH_COMPLETE_BHT_ADDRESS = new SC_SIGNAL(Taddress_t) * [_param._nb_branch_complete]; 
      }
    if (_param._have_pht)
      {
    signal_BRANCH_COMPLETE_PHT_ACK     = new SC_SIGNAL(Tcontrol_t) * [_param._nb_branch_complete];
    signal_BRANCH_COMPLETE_PHT_ADDRESS = new SC_SIGNAL(Taddress_t) * [_param._nb_branch_complete]; 
      }

    for (uint32_t i=0; i<_param._nb_branch_complete; i++)
      {
	rename = "in_BRANCH_COMPLETE_VAL_"         +toString(i);
	 in_BRANCH_COMPLETE_VAL         [i] = new SC_IN (Tcontrol_t)     (rename.c_str());

	rename = "out_BRANCH_COMPLETE_ACK_"        +toString(i);
	out_BRANCH_COMPLETE_ACK         [i] = new SC_OUT(Tcontrol_t)     (rename.c_str());

	rename = "in_BRANCH_COMPLETE_ADDRESS_"     +toString(i);
	 in_BRANCH_COMPLETE_ADDRESS     [i] = new SC_IN (Taddress_t)     (rename.c_str());

	if (_param._have_bht)
	  {
    	rename = "in_BRANCH_COMPLETE_BHT_HISTORY_"+toString(i);
	 in_BRANCH_COMPLETE_BHT_HISTORY [i] = new SC_IN (Tbht_history_t) (rename.c_str());
	  }
	if (_param._have_pht)
	  {
	rename = "in_BRANCH_COMPLETE_PHT_HISTORY_"+toString(i);
	 in_BRANCH_COMPLETE_PHT_HISTORY [i] = new SC_IN (Tpht_history_t) (rename.c_str());
	  }
	rename = "in_BRANCH_COMPLETE_DIRECTION_"  +toString(i);
	 in_BRANCH_COMPLETE_DIRECTION   [i] = new SC_IN (Tcontrol_t)     (rename.c_str());
	if (_param._have_bht)
	  {
	rename = "signal_BRANCH_COMPLETE_BHT_ACK_"    +toString(i);
	signal_BRANCH_COMPLETE_BHT_ACK     [i] = new SC_SIGNAL(Tcontrol_t) (rename.c_str());

	rename = "signal_BRANCH_COMPLETE_BHT_ADDRESS_"+toString(i); 
	signal_BRANCH_COMPLETE_BHT_ADDRESS [i] = new SC_SIGNAL(Taddress_t) (rename.c_str()); 
	  }
	if (_param._have_pht)
	  {
	rename = "signal_BRANCH_COMPLETE_PHT_ACK_"    +toString(i);
	signal_BRANCH_COMPLETE_PHT_ACK     [i] = new SC_SIGNAL(Tcontrol_t) (rename.c_str());

	rename = "signal_BRANCH_COMPLETE_PHT_ADDRESS_"+toString(i); 
	signal_BRANCH_COMPLETE_PHT_ADDRESS [i] = new SC_SIGNAL(Taddress_t) (rename.c_str()); 
	  }
      }

    // ~~~~~[ Component ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    string name_component;

    // =====[ component_Branch_History_Table ]============================    
    if (_param._have_bht)
      {
	name_component = _name+"_Branch_History_Table";

	log_printf(INFO,Two_Level_Branch_Predictor,"allocation","Allocation : %s",name_component.c_str());
	
	component_Branch_History_Table = new morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::two_level_branch_predictor::branch_history_table ::Branch_History_Table (name_component.c_str()               ,
#ifdef STATISTICS
																						       _param_statistics                    ,
#endif
																						       *(_param._param_branch_history_table));
	
	// Instantiation
	(*(component_Branch_History_Table->in_CLOCK))        (*(in_CLOCK));

	for (uint32_t i=0; i<_param._nb_prediction; i++)
	  {
	    (*(component_Branch_History_Table-> in_PREDICT_VAL             [i]))    (*(    in_PREDICT_VAL          [i]));
	    (*(component_Branch_History_Table->out_PREDICT_ACK             [i]))    (*(signal_PREDICT_BHT_ACK      [i]));
	    (*(component_Branch_History_Table-> in_PREDICT_ADDRESS         [i]))    (*(signal_PREDICT_BHT_ADDRESS  [i]));
	    (*(component_Branch_History_Table->out_PREDICT_HISTORY         [i]))    (*(   out_PREDICT_BHT_HISTORY  [i]));
	  }
	
	for (uint32_t i=0; i<_param._nb_branch_complete; i++)
	  {
	    (*(component_Branch_History_Table-> in_BRANCH_COMPLETE_VAL       [i]))    (*(    in_BRANCH_COMPLETE_VAL         [i]));
	    (*(component_Branch_History_Table->out_BRANCH_COMPLETE_ACK       [i]))    (*(signal_BRANCH_COMPLETE_BHT_ACK     [i]));
	    (*(component_Branch_History_Table-> in_BRANCH_COMPLETE_ADDRESS   [i]))    (*(signal_BRANCH_COMPLETE_BHT_ADDRESS [i]));
	    (*(component_Branch_History_Table-> in_BRANCH_COMPLETE_HISTORY   [i]))    (*(    in_BRANCH_COMPLETE_BHT_HISTORY [i]));
	    (*(component_Branch_History_Table-> in_BRANCH_COMPLETE_DIRECTION [i]))    (*(    in_BRANCH_COMPLETE_DIRECTION   [i]));
	  }
      }

    // =====[ component_Pattern_History_Table ]===========================    
    if (_param._have_pht)
      {
	name_component = _name+"_Pattern_History_Table";
	
	log_printf(INFO,Two_Level_Branch_Predictor,"allocation","Allocation : %s",name_component.c_str());
	
	component_Pattern_History_Table = new morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::two_level_branch_predictor::pattern_history_table::Pattern_History_Table (name_component.c_str()               ,
#ifdef STATISTICS
																							 _param_statistics                    ,
#endif
																							 *(_param._param_pattern_history_table));
	
	// Instantiation
	(*(component_Pattern_History_Table->in_CLOCK))        (*(in_CLOCK));
	
	for (uint32_t i=0; i<_param._nb_prediction; i++)
	  {
	    (*(component_Pattern_History_Table-> in_PREDICT_VAL             [i]))    (*(    in_PREDICT_VAL          [i]));
	    (*(component_Pattern_History_Table->out_PREDICT_ACK             [i]))    (*(signal_PREDICT_PHT_ACK      [i]));
	    (*(component_Pattern_History_Table-> in_PREDICT_ADDRESS         [i]))    (*(signal_PREDICT_PHT_ADDRESS  [i]));
	    (*(component_Pattern_History_Table->out_PREDICT_HISTORY         [i]))    (*(   out_PREDICT_PHT_HISTORY  [i]));
	  }
	
	for (uint32_t i=0; i<_param._nb_branch_complete; i++)
	  {
	    (*(component_Pattern_History_Table-> in_BRANCH_COMPLETE_VAL       [i]))    (*(    in_BRANCH_COMPLETE_VAL         [i]));
	    (*(component_Pattern_History_Table->out_BRANCH_COMPLETE_ACK       [i]))    (*(signal_BRANCH_COMPLETE_PHT_ACK     [i]));
	    (*(component_Pattern_History_Table-> in_BRANCH_COMPLETE_ADDRESS   [i]))    (*(signal_BRANCH_COMPLETE_PHT_ADDRESS [i]));
	    (*(component_Pattern_History_Table-> in_BRANCH_COMPLETE_HISTORY   [i]))    (*(    in_BRANCH_COMPLETE_PHT_HISTORY [i]));
	    (*(component_Pattern_History_Table-> in_BRANCH_COMPLETE_DIRECTION [i]))    (*(    in_BRANCH_COMPLETE_DIRECTION   [i]));
	  }
      }

    // =====[ component_Two_Level_Branch_Predictor_Glue ]===========================    
    name_component = _name+"_Two_Level_Branch_Predictor_Glue";
    
    log_printf(INFO,Two_Level_Branch_Predictor,"allocation","Allocation : %s",name_component.c_str());
    
    component_Two_Level_Branch_Predictor_Glue = new morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::two_level_branch_predictor::two_level_branch_predictor_glue::Two_Level_Branch_Predictor_Glue (name_component.c_str()               ,
#ifdef STATISTICS
																										   _param_statistics                    ,
#endif
																										   *(_param._param_two_level_branch_predictor_glue));
    
    // Instantiation
#if defined(STATISTICS) or defined(VHDL_TESTBENCH)
    (*(component_Two_Level_Branch_Predictor_Glue->in_CLOCK))        (*(in_CLOCK));
#endif	
    for (uint32_t i=0; i<_param._nb_prediction; i++)
      {
	if (_param._have_bht)
	  {
	    (*(component_Two_Level_Branch_Predictor_Glue-> in_PREDICT_BHT_ACK             [i])) (*(signal_PREDICT_BHT_ACK              [i]));
	    (*(component_Two_Level_Branch_Predictor_Glue->out_PREDICT_BHT_ADDRESS         [i])) (*(signal_PREDICT_BHT_ADDRESS          [i]));
	  }											   										  
	if (_param._have_pht)								   							  
	  {											   										  
	    (*(component_Two_Level_Branch_Predictor_Glue-> in_PREDICT_PHT_ACK             [i])) (*(signal_PREDICT_PHT_ACK              [i]));
	    (*(component_Two_Level_Branch_Predictor_Glue->out_PREDICT_PHT_ADDRESS         [i])) (*(signal_PREDICT_PHT_ADDRESS          [i]));
	  }											   										  
	if (_param._have_bht and _param._have_pht)						   					  
	  {											   										  
	    (*(component_Two_Level_Branch_Predictor_Glue-> in_PREDICT_BHT_HISTORY         [i])) (*(   out_PREDICT_BHT_HISTORY          [i]));
	  }											   										  
	(*(component_Two_Level_Branch_Predictor_Glue->out_PREDICT_ACK                 [i])) (*(   out_PREDICT_ACK                  [i]));
	(*(component_Two_Level_Branch_Predictor_Glue-> in_PREDICT_ADDRESS             [i])) (*(    in_PREDICT_ADDRESS              [i]));
      }
    
    for (uint32_t i=0; i<_param._nb_branch_complete; i++)
      {
	if (_param._have_bht)
	  {
	    (*(component_Two_Level_Branch_Predictor_Glue-> in_BRANCH_COMPLETE_BHT_ACK     [i])) (*(signal_BRANCH_COMPLETE_BHT_ACK      [i]));
	    (*(component_Two_Level_Branch_Predictor_Glue->out_BRANCH_COMPLETE_BHT_ADDRESS [i])) (*(signal_BRANCH_COMPLETE_BHT_ADDRESS  [i]));
	  }										   					       				  
	if (_param._have_pht)							   					       	  
	  {										   					       				  
	    (*(component_Two_Level_Branch_Predictor_Glue-> in_BRANCH_COMPLETE_PHT_ACK     [i])) (*(signal_BRANCH_COMPLETE_PHT_ACK      [i]));
	    (*(component_Two_Level_Branch_Predictor_Glue->out_BRANCH_COMPLETE_PHT_ADDRESS [i])) (*(signal_BRANCH_COMPLETE_PHT_ADDRESS  [i]));
	  }										   					       				  
	if (_param._have_bht and _param._have_pht)					   					  
	  {										   					       				  
	    (*(component_Two_Level_Branch_Predictor_Glue-> in_BRANCH_COMPLETE_BHT_HISTORY [i])) (*(    in_BRANCH_COMPLETE_BHT_HISTORY  [i]));
	  }										   					       				  
	(*(component_Two_Level_Branch_Predictor_Glue->out_BRANCH_COMPLETE_ACK         [i])) (*(   out_BRANCH_COMPLETE_ACK          [i]));
	(*(component_Two_Level_Branch_Predictor_Glue-> in_BRANCH_COMPLETE_ADDRESS     [i])) (*(    in_BRANCH_COMPLETE_ADDRESS      [i]));
      }
  
    log_printf(FUNC,Two_Level_Branch_Predictor,"allocation","End");
  };
  
}; // end namespace two_level_branch_predictor
}; // end namespace meta_predictor
}; // end namespace predictor
}; // end namespace stage_1_ifetch
}; // end namespace behavioural
}; // end namespace morpheo              
#endif
