/*
 * $Id$
 *
 * [ Description ]
 * 
 * Test
 */

#define NB_ITERATION 1

#include "Behavioural/Stage_1_Ifetch/Predictor/Meta_Predictor/SelfTest/include/test.h"
#include "Include/Test.h"

void test (string name,
	   morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::Parameters _param)
{
  cout << "<" << name << "> : Simulation SystemC" << endl;
  
  Meta_Predictor * _Meta_Predictor = new Meta_Predictor (name.c_str(),
#ifdef STATISTICS
							 morpheo::behavioural::Parameters_Statistics(5,50),
#endif
							 _param);
  
#ifdef SYSTEMC
  /*********************************************************************
   * Déclarations des signaux
   *********************************************************************/
  sc_clock                         * CLOCK                      ;
  sc_signal<Tcontrol_t>            * NRESET                     ;

    // Interface Predict
  sc_signal<Tcontrol_t>           ** PREDICT_VAL                ;
  sc_signal<Tcontrol_t>           ** PREDICT_ACK                ;
  sc_signal<Taddress_t>           ** PREDICT_ADDRESS            ;
  sc_signal<Thistory_t>           ** PREDICT_HISTORY            ;
  sc_signal<Tcontrol_t>           ** PREDICT_DIRECTION          ;
			
    // Interface Branch_complete
  sc_signal<Tcontrol_t>           ** BRANCH_COMPLETE_VAL        ;
  sc_signal<Tcontrol_t>           ** BRANCH_COMPLETE_ACK        ;
  sc_signal<Taddress_t>           ** BRANCH_COMPLETE_ADDRESS    ;
  sc_signal<Thistory_t>           ** BRANCH_COMPLETE_HISTORY    ;
  sc_signal<Tcontrol_t>           ** BRANCH_COMPLETE_DIRECTION  ;

  string rename;

  CLOCK                       = new sc_clock ("clock", 1.0, 0.5);
  NRESET                      = new sc_signal<Tcontrol_t> ("NRESET");

  PREDICT_VAL                 = new sc_signal<Tcontrol_t>     * [_param._nb_prediction     ];
  PREDICT_ACK                 = new sc_signal<Tcontrol_t>     * [_param._nb_prediction     ];
  PREDICT_ADDRESS             = new sc_signal<Taddress_t>     * [_param._nb_prediction     ];
  PREDICT_HISTORY             = new sc_signal<Thistory_t>     * [_param._nb_prediction     ];
  PREDICT_DIRECTION           = new sc_signal<Tcontrol_t>     * [_param._nb_prediction     ];

  for (uint32_t i=0; i<_param._nb_prediction; i++)
    {
      rename = "PREDICT_VAL_"         +toString(i);
      PREDICT_VAL                 [i] = new sc_signal<Tcontrol_t>     (rename.c_str());
      rename = "PREDICT_ACK_"        +toString(i);
      PREDICT_ACK                 [i] = new sc_signal<Tcontrol_t>     (rename.c_str());
      rename = "PREDICT_ADDRESS_"     +toString(i);
      PREDICT_ADDRESS             [i] = new sc_signal<Taddress_t>     (rename.c_str());
      rename = "PREDICT_HISTORY_"    +toString(i);
      PREDICT_HISTORY             [i] = new sc_signal<Thistory_t>     (rename.c_str());
      rename = "PREDICT_DIRECTION_"  +toString(i);
      PREDICT_DIRECTION           [i] = new sc_signal<Tcontrol_t>     (rename.c_str());
    }
  
  BRANCH_COMPLETE_VAL         = new sc_signal<Tcontrol_t>     * [_param._nb_branch_complete];
  BRANCH_COMPLETE_ACK         = new sc_signal<Tcontrol_t>     * [_param._nb_branch_complete];
  BRANCH_COMPLETE_ADDRESS     = new sc_signal<Taddress_t>     * [_param._nb_branch_complete];
  BRANCH_COMPLETE_HISTORY     = new sc_signal<Thistory_t>     * [_param._nb_branch_complete];
  BRANCH_COMPLETE_DIRECTION   = new sc_signal<Tcontrol_t>     * [_param._nb_branch_complete];
  
  for (uint32_t i=0; i<_param._nb_branch_complete; i++)
    {
      rename = "BRANCH_COMPLETE_VAL_"         +toString(i);
      BRANCH_COMPLETE_VAL         [i] = new sc_signal<Tcontrol_t>     (rename.c_str());
      rename = "BRANCH_COMPLETE_ACK_"        +toString(i);
      BRANCH_COMPLETE_ACK         [i] = new sc_signal<Tcontrol_t>     (rename.c_str());
      rename = "BRANCH_COMPLETE_ADDRESS_"     +toString(i);
      BRANCH_COMPLETE_ADDRESS     [i] = new sc_signal<Taddress_t>     (rename.c_str());
      rename = "BRANCH_COMPLETE_HISTORY_"     +toString(i);
      BRANCH_COMPLETE_HISTORY     [i] = new sc_signal<Thistory_t>     (rename.c_str());
      rename = "BRANCH_COMPLETE_DIRECTION_"   +toString(i);
      BRANCH_COMPLETE_DIRECTION   [i] = new sc_signal<Tcontrol_t>     (rename.c_str());
    }

  /********************************************************
   * Instanciation
   ********************************************************/
  
  cout << "<" << name << "> Instanciation of _Meta_Predictor" << endl;
  
  (*(_Meta_Predictor->in_CLOCK ))        (*(CLOCK ));
  (*(_Meta_Predictor->in_NRESET))        (*(NRESET));

    for (uint32_t i=0; i<_param._nb_prediction; i++)
      {
	(*(_Meta_Predictor-> in_PREDICT_VAL                 [i]))        (*(PREDICT_VAL                 [i]));
	(*(_Meta_Predictor->out_PREDICT_ACK                 [i]))        (*(PREDICT_ACK                 [i]));
	(*(_Meta_Predictor-> in_PREDICT_ADDRESS             [i]))        (*(PREDICT_ADDRESS             [i]));
	(*(_Meta_Predictor->out_PREDICT_HISTORY             [i]))        (*(PREDICT_HISTORY             [i]));
	(*(_Meta_Predictor->out_PREDICT_DIRECTION           [i]))        (*(PREDICT_DIRECTION           [i]));
      }
    for (uint32_t i=0; i<_param._nb_branch_complete; i++)
      {
	(*(_Meta_Predictor-> in_BRANCH_COMPLETE_VAL         [i]))        (*(BRANCH_COMPLETE_VAL         [i]));
	(*(_Meta_Predictor->out_BRANCH_COMPLETE_ACK         [i]))        (*(BRANCH_COMPLETE_ACK         [i]));
	(*(_Meta_Predictor-> in_BRANCH_COMPLETE_ADDRESS     [i]))        (*(BRANCH_COMPLETE_ADDRESS     [i]));
	(*(_Meta_Predictor-> in_BRANCH_COMPLETE_HISTORY     [i]))        (*(BRANCH_COMPLETE_HISTORY     [i]));
	(*(_Meta_Predictor-> in_BRANCH_COMPLETE_DIRECTION   [i]))        (*(BRANCH_COMPLETE_DIRECTION   [i]));
      }

  /********************************************************
   * Simulation - Begin
   ********************************************************/

  cout << "<" << name << "> Start Simulation ............" << endl;

  // Initialisation
  const uint32_t seed = 0;
//const uint32_t seed = static_cast<uint32_t>(time(NULL));

  srand(seed);

  sc_start(0);
  _Meta_Predictor->vhdl_testbench_label("Initialisation");
  cout << "{"+toString(static_cast<uint32_t>(sc_simulation_time()))+"} Initialisation" << endl;


  _Meta_Predictor->vhdl_testbench_label("Loop of Test");
  cout << "{"+toString(static_cast<uint32_t>(sc_simulation_time()))+"} Loop of Test" << endl;

  for (uint32_t iteration=0; iteration<NB_ITERATION; iteration ++)
    {
      _Meta_Predictor->vhdl_testbench_label("Iteration "+toString(iteration));

      sc_start(1);
    }

  /********************************************************
   * Simulation - End
   ********************************************************/

  cout << "<" << name << "> ............ Stop Simulation" << endl;

#endif

  delete _Meta_Predictor;
}
