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

#define NB_ITERATION 16

#define TEXT(str)  do {cout << "<" << name << "> : " << str << endl;} while (0)
#define LABEL(str) do {cout << "{"+toString(static_cast<uint32_t>(sc_simulation_time()))+"} " << str << endl; _RegisterFile_Multi_Banked_Glue->vhdl_testbench_label(str);} while (0)

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

void test (string name,
	   morpheo::behavioural::generic::registerfile::registerfile_multi_banked::registerfile_multi_banked_glue::Parameters _param)
{
  TEXT("Simulation SystemC");

  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<Taddress_t>                 ** WRITE_IN_ADDRESS  ;
  sc_signal<Tdata_t   >                 ** WRITE_IN_DATA     ;
  sc_signal<Tcontrol_t>               **** WRITE_SELECT_VAL  ;
  sc_signal<Tcontrol_t>               **** WRITE_SELECT_ACK  ;
  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];

  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());
    }

   READ_SELECT_VAL  = new sc_signal<Tcontrol_t> *** [_param._nb_bank];
   READ_SELECT_ACK  = new sc_signal<Tcontrol_t> *** [_param._nb_bank];

    for (uint32_t i=0; i<_param._nb_bank; i++)
      {
	READ_SELECT_VAL [i] = new sc_signal<Tcontrol_t>  ** [_param._nb_port_read_by_bank];
	READ_SELECT_ACK [i] = new sc_signal<Tcontrol_t>  ** [_param._nb_port_read_by_bank];

	 for (uint32_t j=0; j<_param._nb_port_read_by_bank; j++)
	   {
	     READ_SELECT_VAL [i][j] = new sc_signal<Tcontrol_t>   * [_param._nb_port_select_by_bank_read_port [j]];
	     READ_SELECT_ACK [i][j] = new sc_signal<Tcontrol_t>   * [_param._nb_port_select_by_bank_read_port [j]];
	     
	     for (uint32_t k=0; k<_param._nb_port_select_by_bank_read_port [j]; k++)
	       {
		 rename="READ_SELECT_VAL_"+toString(i)+"_"+toString(j)+"_"+toString(k)+" ";
		 READ_SELECT_VAL [i][j][k] = new sc_signal<Tcontrol_t> (rename.c_str());
		 
		 rename="READ_SELECT_ACK_"+toString(i)+"_"+toString(j)+"_"+toString(k)+" ";
		 READ_SELECT_ACK [i][j][k] = 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];
   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());
     }

   WRITE_SELECT_VAL  = new sc_signal<Tcontrol_t> *** [_param._nb_bank];
   WRITE_SELECT_ACK  = new sc_signal<Tcontrol_t> *** [_param._nb_bank];

    for (uint32_t i=0; i<_param._nb_bank; i++)
      {
	WRITE_SELECT_VAL [i] = new sc_signal<Tcontrol_t>  ** [_param._nb_port_write_by_bank];
	WRITE_SELECT_ACK [i] = new sc_signal<Tcontrol_t>  ** [_param._nb_port_write_by_bank];

	 for (uint32_t j=0; j<_param._nb_port_write_by_bank; j++)
	   {
	     WRITE_SELECT_VAL [i][j] = new sc_signal<Tcontrol_t>   * [_param._nb_port_select_by_bank_write_port [j]];
	     WRITE_SELECT_ACK [i][j] = new sc_signal<Tcontrol_t>   * [_param._nb_port_select_by_bank_write_port [j]];
	     
	     for (uint32_t k=0; k<_param._nb_port_select_by_bank_write_port [j]; k++)
	       {
		 rename="WRITE_SELECT_VAL_"+toString(i)+"_"+toString(j)+"_"+toString(k)+" ";
		 WRITE_SELECT_VAL [i][j][k] = new sc_signal<Tcontrol_t> (rename.c_str());
		 
		 rename="WRITE_SELECT_ACK_"+toString(i)+"_"+toString(j)+"_"+toString(k)+" ";
		 WRITE_SELECT_ACK [i][j][k] = 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
   ********************************************************/
  
   TEXT("Instanciation of _RegisterFile_Multi_Banked_Glue");
  
  (*(_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]));
     }

   for (uint32_t i=0; i<_param._nb_bank; i++)
     for (uint32_t j=0; j<_param._nb_port_read_by_bank; j++)
       for (uint32_t k=0; k<_param._nb_port_select_by_bank_read_port[j]; k++)
	 {
	   (*(_RegisterFile_Multi_Banked_Glue->out_READ_SELECT_VAL [i][j][k])) (*(READ_SELECT_VAL [i][j][k]));
	   (*(_RegisterFile_Multi_Banked_Glue-> in_READ_SELECT_ACK [i][j][k])) (*(READ_SELECT_ACK [i][j][k]));
	 }

   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]));
     }

   for (uint32_t i=0; i<_param._nb_bank; i++)
     for (uint32_t j=0; j<_param._nb_port_write_by_bank; j++)
       for (uint32_t k=0; k<_param._nb_port_select_by_bank_write_port[j]; k++)
	 {
	   (*(_RegisterFile_Multi_Banked_Glue->out_WRITE_SELECT_VAL [i][j][k])) (*(WRITE_SELECT_VAL [i][j][k]));
	   (*(_RegisterFile_Multi_Banked_Glue-> in_WRITE_SELECT_ACK [i][j][k])) (*(WRITE_SELECT_ACK [i][j][k]));
	 }

   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]));
	 }


   TEXT("Start Simulation ............");
  
  /********************************************************
   * Simulation - Begin
   ********************************************************/

  // Initialisation

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

  srand(seed);

  sc_start(0);

  LABEL("Initialisation");

  uint32_t   read_in_num_bank [_param._nb_port_read]; // Number of bank
  Tcontrol_t read_is_busy     [_param._nb_port_read];
  bool       read_out_find    [_param._nb_bank][_param._nb_port_read_by_bank];  
  uint32_t   read_out_port    [_param._nb_bank][_param._nb_port_read_by_bank];  

  Tcontrol_t read_in_ack      [_param._nb_port_read]; // to test
  Tdata_t    read_in_data     [_param._nb_port_read]; // to test
  Tcontrol_t read_out_val     [_param._nb_bank][_param._nb_port_read_by_bank];  
  Taddress_t read_out_address [_param._nb_bank][_param._nb_port_read_by_bank];  
  Tcontrol_t read_select_val  [_param._nb_bank][_param._nb_port_read_by_bank][_param._nb_port_read];

  LABEL("Loop of Test");

  for (uint32_t iteration=0; iteration<NB_ITERATION; iteration ++)
    {
      LABEL("Iteration "+toString(iteration));
      
      //LABEL("Test read_in");
      
      // Write in interface "read_in"
      for (uint32_t i=0; i<_param._nb_port_read; i++)
	{
	  read_in_num_bank  [i] =  rand() % _param._nb_bank;
	  Tcontrol_t read_in_val = (rand() % 2) != 0;

	  Taddress_t address    = (read_in_num_bank[i] << _param._shift_address) | (gen_mask<Taddress_t>(_param._size_address-_param._shift_address) & i);

	  read_is_busy      [i] = (read_in_val == 0);   // invalid = busy
	  read_in_ack       [i] = 0;                    // init
	  read_in_data      [i] = 0;                    // init
	  READ_IN_VAL       [i]->write(read_in_val);    // write signal
	  READ_IN_ADDRESS   [i]->write(address);        // write signal
	}

      // compute the good read_select
      for (uint32_t i=0; i<_param._nb_bank; i++)
	for (uint32_t j=0; j<_param._nb_port_read_by_bank; j++)
	  {
	    Tcontrol_t read_out_ack = (rand() % 2) != 0;
	    READ_OUT_ACK     [i][j]->write(read_out_ack);
	    READ_OUT_DATA    [i][j]->write((j<<1)|1);            // (j<<1)|1 afin de n'avoir jamais 0

	    read_out_find    [i][j] = false;
	    read_out_port    [i][j] = 0;

	    read_out_val     [i][j] = 0;
	    read_out_address [i][j] = 0;

	    bool find = false; // have find a port_in to link with this port_out
	    for (uint32_t k=0; k<_param._nb_port_select_by_bank_read_port[j]; k++)
	      {
		uint32_t num_port; // number of port
		
		// compute the good number of port
		if (_param._crossbar == FULL_CROSSBAR)
		  num_port = k;
		else
		  num_port = k*_param._nb_port_read_by_bank+j;

		read_select_val [i][j][k] = read_out_ack and not read_is_busy [num_port] and (read_in_num_bank[num_port] == i); // select val if port is not busy and out accept a data
		Tcontrol_t read_select_ack = 0;

		// test a previous find
		if (not ((read_out_ack == 0) || find))
		  {
		    // find a busy port?
		    find                      = read_select_val;
		    read_is_busy   [num_port]|= find; // port became busy if find
		    read_select_ack           = find; // ack if find

		    if (find)
		      {
			read_out_find    [i][j] = true;
			read_out_port    [i][j] = num_port;

			// know the good output
			read_in_ack      [num_port] = 1;
			read_in_data     [num_port] = ((j<<1)|1);
			read_out_val     [i][j]     = 1;
			read_out_address [i][j]     = (i << _param._shift_address) | (gen_mask<Taddress_t>(_param._size_address-_param._shift_address) & num_port);
		      }
		  }
		
		READ_SELECT_ACK [i][j][k]->write(read_select_ack);
	      }
	  }

      // next cycle
      sc_start(1);

      // test output

      TEXT ("===== Test Output =====");
      for (uint32_t i=0; i<_param._nb_port_read; i++)
	{
	  TEXT ("Read_in         [" << i << "]       : "
		<< READ_IN_VAL [i]->read() << ","
		<< read_in_ack [i]         << " - "
		<< "Reg[" << READ_IN_ADDRESS [i]->read() << "] -> "
		<< read_in_data [i] << " "
		<< "{bank : " << read_in_num_bank[i] << "}"
		);

	  TEST (Tcontrol_t, read_in_ack  [i], READ_IN_ACK  [i]->read());
	  if (READ_IN_VAL [i]->read() and READ_IN_ACK [i]->read())
	  TEST (Tdata_t   , read_in_data [i], READ_IN_DATA [i]->read());
	}

      cout << endl;
      for (uint32_t i=0; i<_param._nb_bank; i++)
	for (uint32_t j=0; j<_param._nb_port_read_by_bank; j++)
	  {
	    TEXT ("Read_out        [" << i << "][" << j << "]    : "
		  << read_out_val [i][j]         << ","
		  << READ_OUT_ACK [i][j]->read() << " - "
		  << "Reg[" << read_out_address [i][j] << "] -> "
		  << READ_OUT_DATA [i][j]->read() << " - "
		  << "[" << read_out_find [i][j]<< " , "
		  << read_out_port    [i][j] << "]"		  
		  );

	    TEST (Tcontrol_t, read_out_val     [i][j], READ_OUT_VAL     [i][j]->read());
	    if (READ_OUT_VAL [i][j]->read() and READ_OUT_ACK [i][j]->read())
	    TEST (Taddress_t, read_out_address [i][j], READ_OUT_ADDRESS [i][j]->read());

	    for (uint32_t k=0; k<_param._nb_port_select_by_bank_read_port[j]; k++)
	      {
		uint32_t num_port; // number of port
		
		// compute the good number of port
		if (_param._crossbar == FULL_CROSSBAR)
		  num_port = k;
		else
		  num_port = k*_param._nb_port_read_by_bank+j;
		
		TEXT (" * Read_select  [" << i << "][" << j << "][" << k << "] : "
		      << read_select_val [i][j][k]         << ","
		      << READ_SELECT_ACK [i][j][k]->read() << " - "
		      << "link with read_in[" << num_port << "]"
		      );
		
		TEST (Tcontrol_t, read_select_val  [i][j][k], READ_SELECT_VAL  [i][j][k]->read());
	      }
	    
	    
	    
	  }

    }

  sc_start(0);

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

  TEXT("............ Stop Simulation");

  delete CLOCK;

  TEXT("delete read_in");
  for (uint32_t i=0; i<_param._nb_port_read; i++)
    {
//       TEXT("1, i " << i);
      delete READ_IN_VAL       [i];
//       TEXT("2");
      delete READ_IN_ACK       [i];
//       TEXT("3");
      delete READ_IN_ADDRESS   [i];
//       TEXT("4");
      delete READ_IN_DATA      [i];
//       TEXT("5");
    }
  						      
  delete READ_IN_VAL    ;
  delete READ_IN_ACK    ;
  delete READ_IN_ADDRESS;
  delete READ_IN_DATA   ;

  TEXT("delete read_select");
   for (uint32_t i=0; i<_param._nb_bank; i++)
     {
       for (uint32_t j=0; j<_param._nb_port_read_by_bank; j++)
	 {
	   for (uint32_t k=0; k<_param._nb_port_select_by_bank_read_port[j]; k++)
	     {
	       delete READ_SELECT_VAL [i][j][k];
	       delete READ_SELECT_ACK [i][j][k];
	     }
	   delete READ_SELECT_VAL [i][j];
	   delete READ_SELECT_ACK [i][j];
	 }
       delete READ_SELECT_VAL [i];
       delete READ_SELECT_ACK [i];
     }
   delete READ_SELECT_VAL;
   delete READ_SELECT_ACK;

  TEXT("delete read_out");
   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   ;

  TEXT("delete write_in");
  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_IN_VAL    ;
  delete WRITE_IN_ACK    ;
  delete WRITE_IN_ADDRESS;
  delete WRITE_IN_DATA   ;

  TEXT("delete write_select");
  for (uint32_t i=0; i<_param._nb_bank; i++)
    {
      for (uint32_t j=0; j<_param._nb_port_write_by_bank; j++)
	{
	  for (uint32_t k=0; k<_param._nb_port_select_by_bank_write_port[j]; k++)
	    {
	      delete WRITE_SELECT_VAL [i][j][k];
	      delete WRITE_SELECT_ACK [i][j][k];
	    }
	  delete WRITE_SELECT_VAL [i][j];
	  delete WRITE_SELECT_ACK [i][j];
	}
      delete WRITE_SELECT_VAL [i];
      delete WRITE_SELECT_ACK [i];
    }
  delete WRITE_SELECT_VAL;
  delete WRITE_SELECT_ACK;
  
  TEXT("delete write_out");
  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;
}
