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

#define NB_ITERATION 1

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

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

  RegisterFile_Multi_Banked * _RegisterFile_Multi_Banked = new RegisterFile_Multi_Banked (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 Read                
  sc_signal<Tcontrol_t>                 ** READ_VAL     ;
  sc_signal<Tcontrol_t>                 ** READ_ACK     ;
  sc_signal<Taddress_t>                 ** READ_ADDRESS ;
  sc_signal<Tdata_t>                    ** READ_DATA    ;
			                   
    // ----- Interface Write               
  sc_signal<Tcontrol_t>                 ** WRITE_VAL    ;
  sc_signal<Tcontrol_t>                 ** WRITE_ACK    ;
  sc_signal<Taddress_t>                 ** WRITE_ADDRESS;
  sc_signal<Tdata_t>                    ** WRITE_DATA   ;

  string rename;

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

  NRESET = new sc_signal<Tcontrol_t> ("in_NRESET");

  // ----- Interface Read
  READ_VAL     = new sc_signal<Tcontrol_t>     * [_param._nb_port_read];
  READ_ACK     = new sc_signal<Tcontrol_t>     * [_param._nb_port_read];
  READ_ADDRESS = new sc_signal<Taddress_t>     * [_param._nb_port_read];
  READ_DATA    = new sc_signal<Tdata_t>        * [_param._nb_port_read];
  
  for (uint32_t i=0; i<_param._nb_port_read; i++)
    {
	rename = "READ_VAL_"    +toString(i);
	READ_VAL     [i] = new sc_signal<Tcontrol_t> (rename.c_str());
	rename = "READ_ACK_"    +toString(i);
	READ_ACK     [i] = new sc_signal<Tcontrol_t> (rename.c_str());
	rename = "READ_ADDRESS_"+toString(i);
	READ_ADDRESS [i] = new sc_signal<Taddress_t> (rename.c_str());
	rename = "READ_DATA_"   +toString(i);
	READ_DATA    [i] = new sc_signal<Tdata_t>    (rename.c_str());
      }

    // ----- Interface Write
  WRITE_VAL     = new sc_signal<Tcontrol_t>     * [_param._nb_port_write];
  WRITE_ACK     = new sc_signal<Tcontrol_t>     * [_param._nb_port_write];
  WRITE_ADDRESS = new sc_signal<Taddress_t>     * [_param._nb_port_write];
  WRITE_DATA    = new sc_signal<Tdata_t>        * [_param._nb_port_write];
  
  for (uint32_t i=0; i<_param._nb_port_write; i++)
    {
	rename = "WRITE_VAL_"    +toString(i);
	WRITE_VAL     [i] = new sc_signal<Tcontrol_t> (rename.c_str());
	rename = "WRITE_ACK_"    +toString(i);
	WRITE_ACK     [i] = new sc_signal<Tcontrol_t> (rename.c_str());
	rename = "WRITE_ADDRESS_"+toString(i);
	WRITE_ADDRESS [i] = new sc_signal<Taddress_t> (rename.c_str());
	rename = "WRITE_DATA_"   +toString(i);
	WRITE_DATA    [i] = new sc_signal<Tdata_t>    (rename.c_str());
      }
  
  /********************************************************
   * Instanciation
   ********************************************************/
  
  cout << "<" << name << "> Instanciation of _RegisterFile_Multi_Banked" << endl;
  
  (*(_RegisterFile_Multi_Banked->in_CLOCK ))        (*(CLOCK ));
  (*(_RegisterFile_Multi_Banked->in_NRESET))        (*(NRESET));
  
  for (uint32_t i=0; i<_param._nb_port_read; i++)
    {
      (*(_RegisterFile_Multi_Banked-> in_READ_VAL      [i])) (*(READ_VAL      [i]));
      (*(_RegisterFile_Multi_Banked->out_READ_ACK      [i])) (*(READ_ACK      [i]));
      (*(_RegisterFile_Multi_Banked-> in_READ_ADDRESS  [i])) (*(READ_ADDRESS  [i]));
      (*(_RegisterFile_Multi_Banked->out_READ_DATA     [i])) (*(READ_DATA     [i]));
    }
  for (uint32_t i=0; i<_param._nb_port_write; i++)
    {
      (*(_RegisterFile_Multi_Banked-> in_WRITE_VAL     [i])) (*(WRITE_VAL     [i]));
      (*(_RegisterFile_Multi_Banked->out_WRITE_ACK     [i])) (*(WRITE_ACK     [i]));
      (*(_RegisterFile_Multi_Banked-> in_WRITE_ADDRESS [i])) (*(WRITE_ADDRESS [i]));
      (*(_RegisterFile_Multi_Banked-> in_WRITE_DATA    [i])) (*(WRITE_DATA    [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);
  _RegisterFile_Multi_Banked->vhdl_testbench_label("Initialisation");
  cout << "{"+toString(static_cast<uint32_t>(sc_simulation_time()))+"} Initialisation" << endl;


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

      sc_start(1);
    }

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

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

  delete CLOCK;
  delete NRESET;

    // ----- Interface Read
    for (uint32_t i=0; i<_param._nb_port_read; i++)
      {
	delete READ_VAL     [i];
	delete READ_ACK     [i];
	delete READ_ADDRESS [i];
	delete READ_DATA    [i];
      }

    delete READ_VAL    ;
    delete READ_ACK    ;
    delete READ_ADDRESS;
    delete READ_DATA   ;

    // ----- Interface Write
    for (uint32_t i=0; i<_param._nb_port_write; i++)
      {
	delete WRITE_VAL     [i];
	delete WRITE_ACK     [i];
	delete WRITE_ADDRESS [i];
	delete WRITE_DATA    [i];
      }

    delete WRITE_VAL    ;
    delete WRITE_ACK    ;
    delete WRITE_ADDRESS;
    delete WRITE_DATA   ;

#endif

  delete _RegisterFile_Multi_Banked;
}
