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

#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Direction/Meta_Predictor/Two_Level_Branch_Predictor/Pattern_History_Table/include/Pattern_History_Table.h"

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

namespace meta_predictor {
namespace two_level_branch_predictor {
namespace pattern_history_table {


  void Pattern_History_Table::allocation (void)
  {
    log_printf(FUNC,Pattern_History_Table,"allocation","Begin");

    _component   = new Component ();

    Entity * entity = _component->set_entity (_name                 
					     ,"Pattern_History_Table"
#ifdef POSITION
					     ,MIXTE                
#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);
      in_NRESET             = interface->set_signal_in  <Tcontrol_t> ("nreset",1,RESET_VHDL_YES);
    }

    // ~~~~~[ Interface : "predict" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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];
    out_PREDICT_HISTORY = new SC_OUT(Thistory_t) * [_param._nb_prediction];

    for (uint32_t i=0; i<_param._nb_prediction; i++)
      {
	Interface_fifo * interface = _interfaces->set_interface("predict_"+toString(i)
#ifdef POSITION
								, IN  
								, WEST
								, "Interface Predict"
#endif
								);

	 in_PREDICT_VAL     [i] = interface->set_signal_valack_in        ("val"    , VAL);
	out_PREDICT_ACK     [i] = interface->set_signal_valack_out       ("ack"    , ACK);
	 in_PREDICT_ADDRESS [i] = interface->set_signal_in  <Taddress_t> ("address", static_cast<uint32_t>(ceil(log2(_param._nb_counter))));
	out_PREDICT_HISTORY [i] = interface->set_signal_out <Thistory_t> ("history", _param._size_counter);
      }
    
    // ~~~~~[ Interface : "branch_complete" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        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];
        in_BRANCH_COMPLETE_HISTORY   = new SC_IN     (Thistory_t) * [_param._nb_branch_complete];
        in_BRANCH_COMPLETE_DIRECTION = new SC_IN     (Tcontrol_t) * [_param._nb_branch_complete];

    for (uint32_t i=0; i<_param._nb_branch_complete; i++)
      {
	Interface_fifo * interface = _interfaces->set_interface("branch_complete_"+toString(i)
#ifdef POSITION
								, IN  
								, EAST
								, "Interface branch complete"
#endif
								);

	 in_BRANCH_COMPLETE_VAL        [i] = interface->set_signal_valack_in        ("val"      , VAL);
	out_BRANCH_COMPLETE_ACK        [i] = interface->set_signal_valack_out       ("ack"      , ACK);
	 in_BRANCH_COMPLETE_ADDRESS    [i] = interface->set_signal_in  <Taddress_t> ("address"  , static_cast<uint32_t>(ceil(log2(_param._nb_counter))));
	 in_BRANCH_COMPLETE_HISTORY    [i] = interface->set_signal_in  <Thistory_t> ("history"  , _param._size_counter);
	 in_BRANCH_COMPLETE_DIRECTION  [i] = interface->set_signal_in  <Tcontrol_t> ("direction", 1);
      }

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

    // =====[ component_Counter ]=========================================    
    
    name_component = _name+"_Counter";

    component_Counter = new morpheo::behavioural::generic::counter::Counter (name_component.c_str()
#ifdef STATISTICS
									     ,_param_statistics
#endif
									     ,*(_param._param_counter));

    _component->set_component (component_Counter->_component
#ifdef POSITION
			       , 25
			       , 25
			       , 10
			       , 10
#endif
			       );

     // =====[ component_RegisterFile ]====================================    
    
    name_component = _name+"_RegisterFile";
    
    component_RegisterFile = new morpheo::behavioural::generic::registerfile::registerfile_monolithic::RegisterFile_Monolithic(name_component.c_str(),
#ifdef STATISTICS
															       _param_statistics            ,
#endif
															       *(_param._param_registerfile));

    _component->set_component (component_RegisterFile->_component
#ifdef POSITION
			       , 75
			       , 75
			       , 10
			       , 10
#endif
			       );
     
    // ~~~~~[ Component - Instanciation ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    

    // =====[ component_RegisterFile - Instanciation ]====================    

#ifdef POSITION
    _component->interface_map (_name+"_RegisterFile","",
			       _name                ,"");
#endif

    _component->port_map(_name+"_RegisterFile", "in_CLOCK" , _name,"in_CLOCK" );
    _component->port_map(_name+"_RegisterFile", "in_NRESET", _name,"in_NRESET");
    
    for (uint32_t i=0; i<_param._nb_prediction; i++)
      {
#ifdef POSITION
	_component->interface_map (_name+"_RegisterFile","read_"   +toString(i),
				   _name                ,"predict_"+toString(i));
#endif

 	_component->port_map(_name+"_RegisterFile", "in_READ_"+toString(i)+"_VAL"    , _name, "in_PREDICT_"+toString(i)+"_VAL"    );
 	_component->port_map(_name+"_RegisterFile","out_READ_"+toString(i)+"_ACK"    , _name,"out_PREDICT_"+toString(i)+"_ACK"    );
 	_component->port_map(_name+"_RegisterFile", "in_READ_"+toString(i)+"_ADDRESS", _name, "in_PREDICT_"+toString(i)+"_ADDRESS");
 	_component->port_map(_name+"_RegisterFile","out_READ_"+toString(i)+"_DATA"   , _name,"out_PREDICT_"+toString(i)+"_HISTORY");
      }
    
    for (uint32_t i=0; i<_param._nb_branch_complete; i++)
      {
#ifdef POSITION
	_component->interface_map (_name+"_RegisterFile","write_"  +toString(i),
				   _name+"_Counter"     ,"counter_"+toString(i));
#endif

 	_component->port_map(_name+"_RegisterFile", "in_WRITE_"+toString(i)+"_VAL"    , _name           , "in_BRANCH_COMPLETE_"+toString(i)+"_VAL"    );
 	_component->port_map(_name+"_RegisterFile","out_WRITE_"+toString(i)+"_ACK"    , _name           ,"out_BRANCH_COMPLETE_"+toString(i)+"_ACK"    );
 	_component->port_map(_name+"_RegisterFile", "in_WRITE_"+toString(i)+"_ADDRESS", _name           , "in_BRANCH_COMPLETE_"+toString(i)+"_ADDRESS");
 	_component->port_map(_name+"_RegisterFile", "in_WRITE_"+toString(i)+"_DATA"   , _name+"_Counter","out_COUNTER_"        +toString(i)+"_DATA");
      }

    // =====[ component_Counter - Instanciation ]=========================    

#if (defined(STATISTICS) || defined (VHDL_TESTBENCH))

#ifdef POSITION
    _component->interface_map (_name+"_Counter","",
			       _name           ,"");
#endif

    _component->port_map(_name+"_Counter", "in_CLOCK" , _name,"in_CLOCK" );
    _component->port_map(_name+"_Counter", "in_NRESET", _name,"in_NRESET");

#endif

    for (uint32_t i=0; i<_param._nb_branch_complete; i++)
      {
#ifdef POSITION
	_component->interface_map (_name+"_Counter","counter_"+toString(i),
				   _name           ,"branch_complete_"+toString(i));

#endif

 	_component->port_map(_name+"_Counter", "in_COUNTER_" +toString(i)+"_DATA"    , _name                , "in_BRANCH_COMPLETE_"+toString(i)+"_HISTORY");
 	_component->port_map(_name+"_Counter", "in_COUNTER_" +toString(i)+"_ADDSUB"  , _name                , "in_BRANCH_COMPLETE_"+toString(i)+"_DIRECTION");
 	_component->port_map(_name+"_Counter", "out_COUNTER_"+toString(i)+"_DATA"    , _name+"_RegisterFile", "in_WRITE_"+toString(i)+"_DATA");
      }

#ifdef POSITION
    _component->generate_file();
#endif

    log_printf(FUNC,Pattern_History_Table,"allocation","End");
  };

}; // end namespace pattern_history_table
}; // end namespace two_level_branch_predictor
}; // end namespace meta_predictor

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


}; // end namespace behavioural
}; // end namespace morpheo              
#endif
