/*
 *
 * [desc.]
 */
#include "Tools/Viewer/Parser/include/parser.h"

namespace morpheo{
namespace tools{
namespace viewer{
namespace parser{

  morpheo::tools::viewer::bdd::Param *Parse::createAddP(string namegrp,string nameparam)
  {
    morpheo::tools::viewer::bdd::Param *p;
    morpheo::tools::viewer::bdd::LimitParam lp=base->searchLimitParam(nameparam);
    if(lp.getName()=="")
      p=new morpheo::tools::viewer::bdd::Param(nameparam,0,namegrp);
    else
      p=new morpheo::tools::viewer::bdd::Param(nameparam,lp.getDefault(),namegrp);
    return p;
  }

  void Parse::createParam(){
    int i,j,k,l;
    morpheo::tools::viewer::bdd::LimitParam lp;
    morpheo::tools::viewer::bdd::Group *g;
    morpheo::tools::viewer::bdd::Param *p;
    g=new morpheo::tools::viewer::bdd::Group("core",0);
    g->addParam(createAddP("core","size_data"));
    base->addGroup(g);
    
    g=new morpheo::tools::viewer::bdd::Group("cache_unit",1);
    base->addGroup(g);
    
    g=new morpheo::tools::viewer::bdd::Group("icache",2);
    lp=base->searchLimitParam("nb_icache");
    for(i=0;i<lp.getDefault();i++)
       {
	 p=new morpheo::tools::viewer::bdd::Param("id",i,"icache");
	 g->addParam(p);
	 g->addParam(createAddP("icache","arbiter"));
	 g->addParam(createAddP("icache","nb_port"));
       }
    base->addGroup(g);
    
    g=new morpheo::tools::viewer::bdd::Group("dcache",2);
    lp=base->searchLimitParam("nb_dcache");
    for(i=0;i<lp.getDefault();i++)
      {
	p=new morpheo::tools::viewer::bdd::Param("id",i,"dcache");
	g->addParam(p);
	g->addParam(createAddP("dcache","arbiter"));
	g->addParam(createAddP("dcache","nb_port"));
      }
    base->addGroup(g);
    
    lp=base->searchLimitParam("nb_front_end");
    j=lp.getDefault();
    for(i=0;i<j;i++)
      {
	g=new morpheo::tools::viewer::bdd::Group("front_end",1);
	p=new morpheo::tools::viewer::bdd::Param("id",i,"front_end");
	g->addParam(p);
	g->addParam(createAddP("front_end","link_icache"));
	g->addParam(createAddP("front_end","link_out_of_order_engine"));
	base->addGroup(g);
	//
	g=new morpheo::tools::viewer::bdd::Group("fetch_unit",2);
	base->addGroup(g);
	//
	lp=base->searchLimitParam("nb_ifetch");
	k=lp.getDefault();
	for(l=0;l<k;l++)
	  {
	    g=new morpheo::tools::viewer::bdd::Group("ifetch",3);
	    p=new morpheo::tools::viewer::bdd::Param("id",i,"ifetch");
	    g->addParam(p);
	    g->addParam(createAddP("ifetch","nb_inst"));
	    g->addParam(createAddP("ifetch","size_queue"));
	    g->addParam(createAddP("ifetch","link_decod"));
	    base->addGroup(g);
	  }
	//
	g=new morpheo::tools::viewer::bdd::Group("prediction_unit",2);
	g->addParam(createAddP("prediction_unit","arbiter"));
	g->addParam(createAddP("prediction_unit","nb_prediction"));
	g->addParam(createAddP("prediction_unit","nb_branch_complete"));
	base->addGroup(g);
	//
	g=new morpheo::tools::viewer::bdd::Group("branch_target_buffer",3);
	g->addParam(createAddP("branch_target_buffer","size_queue"));
	g->addParam(createAddP("branch_target_buffer","associativity"));
	base->addGroup(g);
	//
	g=new morpheo::tools::viewer::bdd::Group("return_adress_stack",3);
	g->addParam(createAddP("return_adress_stack","size_queue"));
	base->addGroup(g);
	//
	g=new morpheo::tools::viewer::bdd::Group("branch_context",3);
	g->addParam(createAddP("branch_context","size_queue"));
	base->addGroup(g);
	
	//
	g=new morpheo::tools::viewer::bdd::Group("meta_predictor",3);
	g->addParam(createAddP("meta_predictor","have_meta_predictor"));

	g->addParam(createAddP("meta_predictor","predictor_0_have_bht"));
	g->addParam(createAddP("meta_predictor","predictor_0_bht_size_shifter"));
	g->addParam(createAddP("meta_predictor","predictor_0_bht_nb_shifter"));
	g->addParam(createAddP("meta_predictor","predictor_0_have_pht"));
	g->addParam(createAddP("meta_predictor","predictor_0_pht_size_counter"));
	g->addParam(createAddP("meta_predictor","predictor_0_pht_nb_counter"));
	g->addParam(createAddP("meta_predictor","predictor_0_pht_size_address_share"));
	
	g->addParam(createAddP("meta_predictor","predictor_1_have_bht"));
	g->addParam(createAddP("meta_predictor","predictor_1_bht_size_shifter"));
	g->addParam(createAddP("meta_predictor","predictor_1_bht_nb_shifter"));
	g->addParam(createAddP("meta_predictor","predictor_1_have_pht"));
	g->addParam(createAddP("meta_predictor","predictor_1_pht_size_counter"));
	g->addParam(createAddP("meta_predictor","predictor_1_pht_nb_counter"));
	g->addParam(createAddP("meta_predictor","predictor_1_pht_size_address_share"));
	
	g->addParam(createAddP("meta_predictor","predictor_2_have_bht"));
	g->addParam(createAddP("meta_predictor","predictor_2_bht_size_shifter"));
	g->addParam(createAddP("meta_predictor","predictor_2_bht_nb_shifter"));
	g->addParam(createAddP("meta_predictor","predictor_2_have_pht"));
	g->addParam(createAddP("meta_predictor","predictor_2_pht_size_counter"));
	g->addParam(createAddP("meta_predictor","predictor_2_pht_nb_counter"));
	g->addParam(createAddP("meta_predictor","predictor_2_pht_size_address_share"));
	
	base->addGroup(g);
	//
	g=new morpheo::tools::viewer::bdd::Group("decod_unit",2);
	base->addGroup(g);
	//
	lp=base->searchLimitParam("nb_decod");
	k=lp.getDefault();
	for(l=0;l<k;l++)
	  {
	    g=new morpheo::tools::viewer::bdd::Group("decod",3);
	    p=new morpheo::tools::viewer::bdd::Param("id",i,"decod");
	    g->addParam(p);
	    g->addParam(createAddP("decod","arbiter"));
	    g->addParam(createAddP("decod","nb_branch_decod"));
	    g->addParam(createAddP("decod","nb_inst"));
	    g->addParam(createAddP("decod","size_queue"));
	    g->addParam(createAddP("decod","link_rename"));
	    base->addGroup(g);
	  }
      }//end front_end

    lp=base->searchLimitParam("nb_out_of_order_engine");
    j=lp.getDefault();
    for(i=0;i<j;i++)
      {
	g=new morpheo::tools::viewer::bdd::Group("out_of_order_engine",1);
	p=new morpheo::tools::viewer::bdd::Param("id",i,"out_of_order_engine");
	g->addParam(p);
	g->addParam(createAddP("out_of_order_engine","link_execution_loop"));

	base->addGroup(g);

	g=new morpheo::tools::viewer::bdd::Group("rename",2);
	g->addParam(createAddP("rename","arbiter"));
	g->addParam(createAddP("rename","nb_inst"));
	g->addParam(createAddP("rename","size_queue"));
	g->addParam(createAddP("rename","size_windows"));
	g->addParam(createAddP("rename","nb_gpr_physical"));
	g->addParam(createAddP("rename","nb_gpr_free"));
	g->addParam(createAddP("rename","nb_spr_physical"));
	g->addParam(createAddP("rename","nb_spr_free"));
	base->addGroup(g);

	g=new morpheo::tools::viewer::bdd::Group("commit",2);
	g->addParam(createAddP("commit","arbiter"));
	g->addParam(createAddP("commit","nb_inst"));
	g->addParam(createAddP("commit","size_queue"));
	g->addParam(createAddP("commit","size_windows"));
	g->addParam(createAddP("commit","commit_out_of_order_thread"));
	base->addGroup(g);
	
      }//end out_of_order

    lp=base->searchLimitParam("nb_execution_loop");
    j=lp.getDefault();
    for(i=0;i<j;i++)
      {
	g=new morpheo::tools::viewer::bdd::Group("execution_loop",1);
	p=new morpheo::tools::viewer::bdd::Param("id",i,"execution_loop");
	g->addParam(p);
	g->addParam(createAddP("execution_loop","link_dcache"));
	base->addGroup(g);

	g=new morpheo::tools::viewer::bdd::Group("read_unit",2);
	base->addGroup(g);

	lp=base->searchLimitParam("nb_reservation_station");
	k=lp.getDefault();
	for(l=0;l<k;l++)
	  {
	    g=new morpheo::tools::viewer::bdd::Group("reservation_station",3);
	    p=new morpheo::tools::viewer::bdd::Param("id",i,"reservation_station");
	    g->addParam(p);
	    g->addParam(createAddP("reservation_station","size_queue"));
	    g->addParam(createAddP("reservation_station","one_queue"));
	    base->addGroup(g);
	    
	    g=new morpheo::tools::viewer::bdd::Group("link",4);
	    p=new morpheo::tools::viewer::bdd::Param("id",0,"link");
	    g->addParam(p);
	    base->addGroup(g);
	    
	  }
	    g=new morpheo::tools::viewer::bdd:: Group("memory_unit",2);
	    g->addParam(createAddP("memory_unit","size_queue"));
	    g->addParam(createAddP("memory_unit","one_queue"));
	    g->addParam(createAddP("memory_unit","nb_inst"));
	    g->addParam(createAddP("memory_unit","size_windows"));
	    g->addParam(createAddP("memory_unit","bypass_memory_out"));
	    g->addParam(createAddP("memory_unit","keep_data"));
	    g->addParam(createAddP("memory_unit","speculated_memory_read"));
	    base->addGroup(g);
	    
	    g=new morpheo::tools::viewer::bdd::Group("link",3);
	    p=new morpheo::tools::viewer::bdd::Param("id",0,"link");
	    g->addParam(p);
	    base->addGroup(g);

	g=new morpheo::tools::viewer::bdd::Group("execution_unit",2);
	base->addGroup(g);

	lp=base->searchLimitParam("nb_execution");
	k=lp.getDefault();
	for(l=0;l<k;l++)
	  {
	    g=new morpheo::tools::viewer::bdd::Group("execution",3);
	    p=new morpheo::tools::viewer::bdd::Param("id",i,"execution");
	    g->addParam(p);
	    g->addParam(createAddP("execution","type_mul"));
	    g->addParam(createAddP("execution","type_div"));
	    g->addParam(createAddP("execution","type_ext"));
	    g->addParam(createAddP("execution","type_ff1"));
	    g->addParam(createAddP("execution","type_fl1"));
	    base->addGroup(g);
	    
	  }
	
	g=new morpheo::tools::viewer::bdd:: Group("write_unit",2);
	base->addGroup(g);

	lp=base->searchLimitParam("nb_writeback");
	k=lp.getDefault();
	for(l=0;l<k;l++)
	  {
	    g=new morpheo::tools::viewer::bdd::Group("writeback",3);
	    p=new morpheo::tools::viewer::bdd::Param("id",i,"writeback");
	    g->addParam(p);
	    g->addParam(createAddP("writeback","size_queue"));
	    g->addParam(createAddP("writeback","one_queue"));
	    g->addParam(createAddP("writeback","bypass_execute_gpr"));
	    g->addParam(createAddP("writeback","bypass_execute_spr"));
	    g->addParam(createAddP("writeback","bypass_memory_in"));
	    base->addGroup(g);

	    g=new morpheo::tools::viewer::bdd::Group("link",4);
	    p=new morpheo::tools::viewer::bdd::Param("id",0,"link");
	    g->addParam(p);
	    base->addGroup(g);
	    
	  }
	
	    
	
      }//end execution_loop
    
     
   }


};//end parser
};//end viewer
};//end tools
};//end morpheo
