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

#define NB_ITERATION 1

#include "Behavioural/Generic/RegisterFile_Multi_Banked/RegisterFile_Multi_Banked_Glue/SelfTest/include/test.h"
#include "Include/Test.h"

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

  RegisterFile_Multi_Banked_Glue * _RegisterFile_Multi_Banked_Glue = new RegisterFile_Multi_Banked_Glue (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>                 ** READ_IN_VAL       ;
  sc_signal<Tcontrol_t>                 ** READ_IN_ACK       ;
  sc_signal<Taddress_t>                 ** READ_IN_ADDRESS   ;
  sc_signal<Tdata_t   >                 ** READ_IN_DATA      ;
  sc_signal<Tcontrol_t>                 ** READ_SELECT_VAL   ;
  sc_signal<Tcontrol_t>                 ** READ_SELECT_ACK   ;
  sc_signal<Tcontrol_t>                *** READ_OUT_VAL      ;
  sc_signal<Tcontrol_t>                *** READ_OUT_ACK      ;
  sc_signal<Taddress_t>                *** READ_OUT_ADDRESS  ;
  sc_signal<Tdata_t   >                *** READ_OUT_DATA     ;
  sc_signal<Tcontrol_t>                 ** WRITE_IN_VAL      ;
  sc_signal<Tcontrol_t>                 ** WRITE_IN_ACK      ;
  sc_signal<Tcontrol_t>                 ** WRITE_SELECT_VAL  ;
  sc_signal<Tcontrol_t>                 ** WRITE_SELECT_ACK  ;
  sc_signal<Taddress_t>                 ** WRITE_IN_ADDRESS  ;
  sc_signal<Tdata_t   >                 ** WRITE_IN_DATA     ;
  sc_signal<Tcontrol_t>                *** WRITE_OUT_VAL     ;
  sc_signal<Tcontrol_t>                *** WRITE_OUT_ACK     ;
  sc_signal<Taddress_t>                *** WRITE_OUT_ADDRESS ;
  sc_signal<Tdata_t   >                *** WRITE_OUT_DATA    ;

  string rename;

  CLOCK                                  = new sc_clock ("clock", 1.0, 0.5);

  READ_IN_VAL       = new sc_signal<Tcontrol_t>           * [_param._nb_port_read];
  READ_IN_ACK       = new sc_signal<Tcontrol_t>           * [_param._nb_port_read];
  READ_IN_ADDRESS   = new sc_signal<Taddress_t>           * [_param._nb_port_read];
  READ_IN_DATA      = new sc_signal<Tdata_t   >           * [_param._nb_port_read];
  READ_SELECT_VAL   = new sc_signal<Tcontrol_t>           * [_param._nb_port_read];
  READ_SELECT_ACK   = new sc_signal<Tcontrol_t>           * [_param._nb_port_read];

  for (uint32_t i=0; i<_param._nb_port_read; i++)
    {
      rename = "READ_IN_VAL_"+toString(i)+"      ";
      READ_IN_VAL       [i] = new sc_signal<Tcontrol_t> (rename.c_str());
      rename = "READ_IN_ACK_"+toString(i)+"      ";
      READ_IN_ACK       [i] = new sc_signal<Tcontrol_t> (rename.c_str());
      rename = "READ_IN_ADDRESS_"+toString(i)+"  ";
      READ_IN_ADDRESS   [i] = new sc_signal<Taddress_t> (rename.c_str());
      rename = "READ_IN_DATA_"+toString(i)+"     ";
      READ_IN_DATA      [i] = new sc_signal<Tdata_t   > (rename.c_str());
      rename = "READ_SELECT_VAL_"+toString(i)+"  ";
      READ_SELECT_VAL       [i] = new sc_signal<Tcontrol_t> (rename.c_str());
      rename = "READ_SELECT_ACK_"+toString(i)+"  ";
      READ_SELECT_ACK       [i] = new sc_signal<Tcontrol_t> (rename.c_str());
    }
   						      
   READ_OUT_VAL      = new sc_signal<Tcontrol_t>          ** [_param._nb_bank];
   READ_OUT_ACK      = new sc_signal<Tcontrol_t>          ** [_param._nb_bank];
   READ_OUT_ADDRESS  = new sc_signal<Taddress_t>          ** [_param._nb_bank];
   READ_OUT_DATA     = new sc_signal<Tdata_t   >          ** [_param._nb_bank];

   for (uint32_t i=0; i<_param._nb_bank; i++)
     {
       READ_OUT_VAL      [i] = new sc_signal<Tcontrol_t>          * [_param._nb_port_read_by_bank];
       READ_OUT_ACK      [i] = new sc_signal<Tcontrol_t>          * [_param._nb_port_read_by_bank];
       READ_OUT_ADDRESS  [i] = new sc_signal<Taddress_t>          * [_param._nb_port_read_by_bank];
       READ_OUT_DATA     [i] = new sc_signal<Tdata_t   >          * [_param._nb_port_read_by_bank];
       
       for (uint32_t j=0; j<_param._nb_port_read_by_bank; j++)
	 {
	   rename="READ_OUT_VAL_"+toString(i)+"_"+toString(j)+"      ";
	   READ_OUT_VAL      [i][j] = new sc_signal<Tcontrol_t> (rename.c_str());
	   rename="READ_OUT_ACK_"+toString(i)+"_"+toString(j)+"      ";
	   READ_OUT_ACK      [i][j] = new sc_signal<Tcontrol_t> (rename.c_str());
	   rename="READ_OUT_ADDRESS_"+toString(i)+"_"+toString(j)+"  ";
	   READ_OUT_ADDRESS  [i][j] = new sc_signal<Taddress_t> (rename.c_str());
	   rename="READ_OUT_DATA_"+toString(i)+"_"+toString(j)+"     ";
	   READ_OUT_DATA     [i][j] = new sc_signal<Tdata_t   > (rename.c_str());
	 }
     }
   
   WRITE_IN_VAL      = new sc_signal<Tcontrol_t>           * [_param._nb_port_write];
   WRITE_IN_ACK      = new sc_signal<Tcontrol_t>           * [_param._nb_port_write];
   WRITE_IN_ADDRESS  = new sc_signal<Taddress_t>           * [_param._nb_port_write];
   WRITE_IN_DATA     = new sc_signal<Tdata_t   >           * [_param._nb_port_write];
   WRITE_SELECT_VAL  = new sc_signal<Tcontrol_t>           * [_param._nb_port_write];
   WRITE_SELECT_ACK  = new sc_signal<Tcontrol_t>           * [_param._nb_port_write];

   for (uint32_t i=0; i<_param._nb_port_write; i++)
     {
       rename = "WRITE_IN_VAL_"+toString(i)+"     ";
       WRITE_IN_VAL      [i] = new sc_signal<Tcontrol_t> (rename.c_str());
       rename = "WRITE_IN_ACK_"+toString(i)+"     ";
       WRITE_IN_ACK      [i] = new sc_signal<Tcontrol_t> (rename.c_str());
       rename = "WRITE_IN_ADDRESS_"+toString(i)+" ";
       WRITE_IN_ADDRESS  [i] = new sc_signal<Taddress_t> (rename.c_str());
       rename = "WRITE_IN_DATA_"+toString(i)+"    ";
       WRITE_IN_DATA     [i] = new sc_signal<Tdata_t   > (rename.c_str());

       rename = "WRITE_SELECT_VAL_"+toString(i)+" ";
       WRITE_SELECT_VAL  [i] = new sc_signal<Tcontrol_t> (rename.c_str());
       rename = "WRITE_SELECT_ACK_"+toString(i)+" ";
       WRITE_SELECT_ACK  [i] = new sc_signal<Tcontrol_t> (rename.c_str());
     }
      
   WRITE_OUT_VAL     = new sc_signal<Tcontrol_t>          ** [_param._nb_bank];
   WRITE_OUT_ACK     = new sc_signal<Tcontrol_t>          ** [_param._nb_bank];
   WRITE_OUT_ADDRESS = new sc_signal<Taddress_t>          ** [_param._nb_bank];
   WRITE_OUT_DATA    = new sc_signal<Tdata_t   >          ** [_param._nb_bank];
   
   for (uint32_t i=0; i<_param._nb_bank; i++)
     {
       WRITE_OUT_VAL     [i] = new sc_signal<Tcontrol_t>          * [_param._nb_port_write_by_bank];
       WRITE_OUT_ACK     [i] = new sc_signal<Tcontrol_t>          * [_param._nb_port_write_by_bank];
       WRITE_OUT_ADDRESS [i] = new sc_signal<Taddress_t>          * [_param._nb_port_write_by_bank];
       WRITE_OUT_DATA    [i] = new sc_signal<Tdata_t   >          * [_param._nb_port_write_by_bank];
       
       for (uint32_t j=0; j<_param._nb_port_write_by_bank; j++)
	 {
	   rename = "WRITE_OUT_VAL_"+toString(i)+"_"+toString(j)+"     ";
	   WRITE_OUT_VAL     [i][j] = new sc_signal<Tcontrol_t> (rename.c_str());
	   rename = "WRITE_OUT_ACK_"+toString(i)+"_"+toString(j)+"     ";
	   WRITE_OUT_ACK     [i][j] = new sc_signal<Tcontrol_t> (rename.c_str());
	   rename = "WRITE_OUT_ADDRESS_"+toString(i)+"_"+toString(j)+" ";
	   WRITE_OUT_ADDRESS [i][j] = new sc_signal<Taddress_t> (rename.c_str());
	   rename = "WRITE_OUT_DATA_"+toString(i)+"_"+toString(j)+"    ";
	   WRITE_OUT_DATA    [i][j] = new sc_signal<Tdata_t   > (rename.c_str());
	 }
     }
  
  /********************************************************
   * Instanciation
   ********************************************************/
  
  cout << "<" << name << "> Instanciation of _RegisterFile_Multi_Banked_Glue" << endl;
  
  (*(_RegisterFile_Multi_Banked_Glue->in_CLOCK))        (*(CLOCK));

   for (uint32_t i=0; i<_param._nb_port_read; i++)
     {
       (*(_RegisterFile_Multi_Banked_Glue-> in_READ_IN_VAL       [i]))       (*(READ_IN_VAL       [i]));
       (*(_RegisterFile_Multi_Banked_Glue->out_READ_IN_ACK       [i]))       (*(READ_IN_ACK       [i]));
       (*(_RegisterFile_Multi_Banked_Glue-> in_READ_IN_ADDRESS   [i]))       (*(READ_IN_ADDRESS   [i]));
       (*(_RegisterFile_Multi_Banked_Glue->out_READ_IN_DATA      [i]))       (*(READ_IN_DATA      [i]));
       (*(_RegisterFile_Multi_Banked_Glue-> in_READ_SELECT_VAL   [i]))       (*(READ_SELECT_VAL   [i]));
       (*(_RegisterFile_Multi_Banked_Glue->out_READ_SELECT_ACK   [i]))       (*(READ_SELECT_ACK   [i]));
     }
   for (uint32_t i=0; i<_param._nb_bank; i++)
       for (uint32_t j=0; j<_param._nb_port_read_by_bank; j++)
	 {
	   (*(_RegisterFile_Multi_Banked_Glue->out_READ_OUT_VAL      [i][j]))       (*(READ_OUT_VAL      [i][j]));
	   (*(_RegisterFile_Multi_Banked_Glue-> in_READ_OUT_ACK      [i][j]))       (*(READ_OUT_ACK      [i][j]));
	   (*(_RegisterFile_Multi_Banked_Glue->out_READ_OUT_ADDRESS  [i][j]))       (*(READ_OUT_ADDRESS  [i][j]));
	   (*(_RegisterFile_Multi_Banked_Glue-> in_READ_OUT_DATA     [i][j]))       (*(READ_OUT_DATA     [i][j]));
	 }

   for (uint32_t i=0; i<_param._nb_port_write; i++)
     {
       (*(_RegisterFile_Multi_Banked_Glue-> in_WRITE_IN_VAL      [i]))       (*(WRITE_IN_VAL      [i]));
       (*(_RegisterFile_Multi_Banked_Glue->out_WRITE_IN_ACK      [i]))       (*(WRITE_IN_ACK      [i]));
       (*(_RegisterFile_Multi_Banked_Glue-> in_WRITE_IN_ADDRESS  [i]))       (*(WRITE_IN_ADDRESS  [i]));
       (*(_RegisterFile_Multi_Banked_Glue-> in_WRITE_IN_DATA     [i]))       (*(WRITE_IN_DATA     [i]));
       (*(_RegisterFile_Multi_Banked_Glue-> in_WRITE_SELECT_VAL  [i]))       (*(WRITE_SELECT_VAL  [i]));
       (*(_RegisterFile_Multi_Banked_Glue->out_WRITE_SELECT_ACK  [i]))       (*(WRITE_SELECT_ACK  [i]));
     }

   for (uint32_t i=0; i<_param._nb_bank; i++)
       for (uint32_t j=0; j<_param._nb_port_write_by_bank; j++)
	 {
	   (*(_RegisterFile_Multi_Banked_Glue->out_WRITE_OUT_VAL     [i][j]))       (*(WRITE_OUT_VAL     [i][j]));
	   (*(_RegisterFile_Multi_Banked_Glue-> in_WRITE_OUT_ACK     [i][j]))       (*(WRITE_OUT_ACK     [i][j]));
	   (*(_RegisterFile_Multi_Banked_Glue->out_WRITE_OUT_ADDRESS [i][j]))       (*(WRITE_OUT_ADDRESS [i][j]));
	   (*(_RegisterFile_Multi_Banked_Glue->out_WRITE_OUT_DATA    [i][j]))       (*(WRITE_OUT_DATA    [i][j]));
	 }


  /********************************************************
   * 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);
  _RegisterFile_Multi_Banked_Glue->vhdl_testbench_label("Initialisation");
  cout << "{"+toString(static_cast<uint32_t>(sc_simulation_time()))+"} Initialisation" << endl;


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

      sc_start(1);
    }

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

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

  delete CLOCK;

  for (uint32_t i=0; i<_param._nb_port_read; i++)
    {
      delete READ_IN_VAL       [i];
      delete READ_IN_ACK       [i];
      delete READ_IN_ADDRESS   [i];
      delete READ_IN_DATA      [i];
      delete READ_SELECT_VAL   [i];
      delete READ_SELECT_ACK   [i];
    }
  						      
  delete READ_IN_VAL    ;
  delete READ_IN_ACK    ;
  delete READ_IN_ADDRESS;
  delete READ_IN_DATA   ;
  delete READ_SELECT_VAL;
  delete READ_SELECT_ACK;

   for (uint32_t i=0; i<_param._nb_bank; i++)
     {
  	for (uint32_t j=0; j<_param._nb_port_read_by_bank; j++)
  	  {
  	    delete READ_OUT_VAL      [i][j];
  	    delete READ_OUT_ACK      [i][j];
  	    delete READ_OUT_ADDRESS  [i][j];
  	    delete READ_OUT_DATA     [i][j];
  	  }

  	delete READ_OUT_VAL      [i];
  	delete READ_OUT_ACK      [i];
  	delete READ_OUT_ADDRESS  [i];
  	delete READ_OUT_DATA     [i];
     }

  delete READ_OUT_VAL    ;
  delete READ_OUT_ACK    ;
  delete READ_OUT_ADDRESS;
  delete READ_OUT_DATA   ;

  for (uint32_t i=0; i<_param._nb_port_write; i++)
    {
      delete WRITE_IN_VAL      [i];
      delete WRITE_IN_ACK      [i];
      delete WRITE_IN_ADDRESS  [i];
      delete WRITE_IN_DATA     [i];
      delete WRITE_SELECT_VAL  [i];
      delete WRITE_SELECT_ACK  [i];
    }

  delete WRITE_IN_VAL    ;
  delete WRITE_IN_ACK    ;
  delete WRITE_IN_ADDRESS;
  delete WRITE_IN_DATA   ;
  delete WRITE_SELECT_VAL;
  delete WRITE_SELECT_ACK;
  
  for (uint32_t i=0; i<_param._nb_bank; i++)
    {
      for (uint32_t j=0; j<_param._nb_port_write_by_bank; j++)
  	 {
  	   delete WRITE_OUT_VAL     [i][j];
  	   delete WRITE_OUT_ACK     [i][j];
  	   delete WRITE_OUT_ADDRESS [i][j];
  	   delete WRITE_OUT_DATA    [i][j];
  	 }
      
      delete WRITE_OUT_VAL     [i];
      delete WRITE_OUT_ACK     [i];
      delete WRITE_OUT_ADDRESS [i];
      delete WRITE_OUT_DATA    [i];
    }
     
  delete WRITE_OUT_VAL    ;
  delete WRITE_OUT_ACK    ;
  delete WRITE_OUT_ADDRESS;
  delete WRITE_OUT_DATA   ;

#endif

  delete _RegisterFile_Multi_Banked_Glue;
}
