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

#define NB_ITERATION 512

#include "Behavioural/Generic/Select/Select_Priority_Fixed/SelfTest/include/test.h"
#include "Include/Test.h"

void test (string name,
	   morpheo::behavioural::generic::select::select_priority_fixed::Parameters _param)
{
  cout << "<" << name << "> : Simulation SystemC" << endl;

  Select_Priority_Fixed * _Select_Priority_Fixed = new Select_Priority_Fixed (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;
  sc_signal<Tcontrol_t>           ** VAL   ;
  sc_signal<Tcontrol_t>           ** ACK   ;
  sc_signal<Tentity_t >            * ENTITY;
  sc_signal<Tcontrol_t>            * ENTITY_ACK;

  string rename;

  CLOCK        = new sc_clock ("clock", 1.0, 0.5);
  NRESET       = new sc_signal<Tcontrol_t> ("NRESET");
  VAL          = new sc_signal<Tcontrol_t> * [_param._nb_entity];
  ACK          = new sc_signal<Tcontrol_t> * [_param._nb_entity];

  for (uint32_t i=0; i<_param._nb_entity; i++)
    {
      rename = "VAL_"+toString(i);
      VAL [i] = new sc_signal<Tcontrol_t> (rename.c_str());
      rename = "ACK_"+toString(i);
      ACK [i] = new sc_signal<Tcontrol_t> (rename.c_str());
    }
  
  ENTITY       = new sc_signal<Tentity_t>  ("entity");
  ENTITY_ACK   = new sc_signal<Tcontrol_t> ("entity_ack");
  
  /********************************************************
   * Instanciation
   ********************************************************/
  
  cout << "<" << name << "> Instanciation of _Select_Priority_Fixed" << endl;
  
  (*(_Select_Priority_Fixed->in_CLOCK ))       (*(CLOCK ));
  (*(_Select_Priority_Fixed->in_NRESET))       (*(NRESET));

    for (uint32_t i=0; i<_param._nb_entity; i++)
      {
	(*(_Select_Priority_Fixed-> in_VAL [i]))        (*(VAL [i]));
	if (_param._encoding_one_hot)
	(*(_Select_Priority_Fixed->out_ACK [i]))        (*(ACK [i]));
      }
    if (_param._encoding_compact)
      {
    (*(_Select_Priority_Fixed->out_ENTITY    ))        (*(ENTITY    ));
    (*(_Select_Priority_Fixed->out_ENTITY_ACK))        (*(ENTITY_ACK));
      }
  /********************************************************
   * Simulation - Begin
   ********************************************************/

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

  if (_param._nb_entity > (8*sizeof (Tentity_t)))
    throw ErrorMorpheo("No Selftest with nb_entity higher at "+toString(8*sizeof (Tentity_t)));

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

  srand(seed);

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

  _Select_Priority_Fixed->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 ++)
    {
      _Select_Priority_Fixed->vhdl_testbench_label("Iteration "+toString(iteration));

      entity    = 0;
      bool find = false;
      
      for (uint32_t i=0; i<_param._nb_entity; i++)
	{
	  Tcontrol_t val = rand() % 2;

	  VAL [i]->write(val);
	  
	  if (not find and val)
	    {
	      find   = true;
	      entity = i;
	    }
	}

      sc_start(1);
 
      cout << "wait entity : " << entity << endl;
    
      entity = (find)?entity:0;

      if (_param._encoding_one_hot)
	TEST(Tcontrol_t, ACK   [entity]->read(), find  );
      if (_param._encoding_compact)
	{
	TEST(Tentity_t , ENTITY        ->read(), entity); // burk
	TEST(Tcontrol_t, ENTITY_ACK    ->read(), find  ); // burk
	}
    }

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

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

  delete CLOCK;
  delete NRESET;

  for (uint32_t i=0; i<_param._nb_entity; i++)
    {
      delete VAL [i];
      delete ACK [i];
    }
  
  delete VAL       ;
  delete ACK       ;
  delete ENTITY    ;
  delete ENTITY_ACK;
#endif

  delete _Select_Priority_Fixed;
}
