#include <iostream>
#include "../include/Environment.h"

using namespace std;
using namespace environment;
using namespace morpheo;

#define _TEST_IMEMORY_ true
#define _TEST_DMEMORY_ true
#define _TEST_TTY_     true
#define _TEST_RAMLOCK_ true
#define _TEST_SIM2OS_  true 

#define TEST(x,y)				\
  {						\
    cout << "Line " << __LINE__ << " : ";	\
    if (x==y)					\
      {						\
	cout << "Test OK" << endl;		\
      }						\
    else					\
      {						\
	cout << "Test KO" << endl;		\
	exit (EXIT_FAILURE);			\
      }						\
  } while (0)

int sc_main (int argc, char * argv[])
{
  cout << "<main> Begin" << endl;

  {
    uint32_t    nb_entity = 2;
    
    uint32_t  * iaccess_nb_context    = new uint32_t [nb_entity];
    uint32_t  * iaccess_nb_instruction= new uint32_t [nb_entity];
    uint32_t  * iaccess_nb_packet     = new uint32_t [nb_entity];
    uint32_t  * iaccess_size_address  = new uint32_t [nb_entity];
    uint32_t  * iaccess_size_data     = new uint32_t [nb_entity];
    
    uint32_t  * daccess_nb_context    = new uint32_t [nb_entity];
    uint32_t  * daccess_nb_packet     = new uint32_t [nb_entity];
    uint32_t  * daccess_size_address  = new uint32_t [nb_entity];
    uint32_t  * daccess_size_data     = new uint32_t [nb_entity];

    uint32_t  * buffer_irsp_size      = new uint32_t [nb_entity];
    uint32_t  * buffer_drsp_size      = new uint32_t [nb_entity];

    for (uint32_t i=0; i<nb_entity; i++)
      {
	iaccess_nb_context     [i] = 4;
	iaccess_nb_instruction [i] = 4;
	iaccess_nb_packet      [i] = 4;
	iaccess_size_address   [i] = 32;
	iaccess_size_data      [i] = 32;

	daccess_nb_context     [i] =  4;
	daccess_nb_packet      [i] =  4;
	daccess_size_address   [i] = 32;
	daccess_size_data      [i] = 32;

	buffer_irsp_size       [i] = 8;
	buffer_drsp_size       [i] = 8;
      }
    
    uint32_t * cache_shared_nb_line       = new uint32_t [1];
    uint32_t * cache_shared_size_line     = new uint32_t [1];
    uint32_t * cache_shared_size_word     = new uint32_t [1];
    uint32_t * cache_shared_associativity = new uint32_t [1];
    uint32_t * cache_shared_hit_latence   = new uint32_t [1];
    uint32_t * cache_shared_miss_penality = new uint32_t [1];

    cache_shared_nb_line       [0] = 8 ;
    cache_shared_size_line     [0] = 8 ;
    cache_shared_size_word     [0] = 4 ;
    cache_shared_associativity [0] = 4 ;
    cache_shared_hit_latence   [0] = 2 ;
    cache_shared_miss_penality [0] = 5 ;

    uint32_t  * icache_nb_level      = new uint32_t   [nb_entity];
    uint32_t  * icache_nb_port       = new uint32_t   [nb_entity];
    uint32_t ** icache_nb_line       = new uint32_t * [nb_entity];
    uint32_t ** icache_size_line     = new uint32_t * [nb_entity];
    uint32_t ** icache_size_word     = new uint32_t * [nb_entity];
    uint32_t ** icache_associativity = new uint32_t * [nb_entity];
    uint32_t ** icache_hit_latence   = new uint32_t * [nb_entity];
    uint32_t ** icache_miss_penality = new uint32_t * [nb_entity];

    for (uint32_t i=0; i<nb_entity; i++)
      {
	icache_nb_level      [i]    = 1;
	icache_nb_port       [i]    = 2;
	icache_nb_line       [i]    = new uint32_t [1];
	icache_size_line     [i]    = new uint32_t [1];
	icache_size_word     [i]    = new uint32_t [1];
	icache_associativity [i]    = new uint32_t [1];
	icache_hit_latence   [i]    = new uint32_t [1];
	icache_miss_penality [i]    = new uint32_t [1];
	
	icache_nb_line       [i][0] = 8;
	icache_size_line     [i][0] = 8;
	icache_size_word     [i][0] = 4;
	icache_associativity [i][0] = 1;
	icache_hit_latence   [i][0] = 1;
	icache_miss_penality [i][0] = 3;
      }

    uint32_t  * dcache_nb_level      = new uint32_t   [nb_entity];
    uint32_t  * dcache_nb_port       = new uint32_t   [nb_entity];
    uint32_t ** dcache_nb_line       = new uint32_t * [nb_entity];
    uint32_t ** dcache_size_line     = new uint32_t * [nb_entity];
    uint32_t ** dcache_size_word     = new uint32_t * [nb_entity];
    uint32_t ** dcache_associativity = new uint32_t * [nb_entity];
    uint32_t ** dcache_hit_latence   = new uint32_t * [nb_entity];
    uint32_t ** dcache_miss_penality = new uint32_t * [nb_entity];

    for (uint32_t i=0; i<nb_entity; i++)
      {
	dcache_nb_level      [i]    = 1;
	dcache_nb_port       [i]    = 2;
	dcache_nb_line       [i]    = new uint32_t [1];
	dcache_size_line     [i]    = new uint32_t [1];
	dcache_size_word     [i]    = new uint32_t [1];
	dcache_associativity [i]    = new uint32_t [1];
	dcache_hit_latence   [i]    = new uint32_t [1];
	dcache_miss_penality [i]    = new uint32_t [1];
	
	dcache_nb_line       [i][0] = 8;
	dcache_size_line     [i][0] = 8;
	dcache_size_word     [i][0] = 4;
	dcache_associativity [i][0] = 1;
	dcache_hit_latence   [i][0] = 1;
	dcache_miss_penality [i][0] = 3;
      }

    uint32_t   nb_component_tty = 1;
    uint32_t * tty_address = new uint32_t [nb_component_tty];
    uint32_t * nb_tty      = new uint32_t [nb_component_tty];
    tty_address [0] = 0xa0000000;
    nb_tty      [0] = 4;
    string  ** name_tty    = new string * [nb_component_tty];
    name_tty [0]    = new string [nb_tty[0]];
    name_tty [0][0] = "tty_0_0";
    name_tty [0][1] = "tty_0_1";
    name_tty [0][2] = "tty_0_2";
    name_tty [0][3] = "tty_0_3";

    uint32_t   nb_component_ramlock = 1;
    uint32_t * ramlock_address = new uint32_t [nb_component_ramlock];
    uint32_t * nb_lock         = new uint32_t [nb_component_ramlock];
    ramlock_address [0] = 0xb0000000;
    nb_lock         [0] = 10;

    uint32_t sim2os_address = 0xc0000000;
    uint32_t sim2os_size    = 0x00001000;
    SOCLIB_SEGMENT_TABLE * segtable = new SOCLIB_SEGMENT_TABLE;
    segtable->setMSBNumber    (8);
    segtable->setDefaultTarget(0,0);
    
    //shared data segment
    const int TEXT_BASE          = 0x00000000;
    const int DATA_CACHED_BASE   = 0x10000000;
    const int DATA_UNCACHED_BASE = 0x40000000;
    
    const int TEXT_SIZE          = 0x4000;
    const int DATA_CACHED_SIZE   = 0x4000;
    const int DATA_UNCACHED_SIZE = 0x4000;
    
    // Add a segment    ,name      ,address of base   ,size              ,global index,local index,uncache
    segtable->addSegment("text"    ,TEXT_BASE         ,TEXT_SIZE         ,0           ,0          ,false);
    segtable->addSegment("data"    ,DATA_CACHED_BASE  ,DATA_CACHED_SIZE  ,0           ,0          ,false);
    segtable->addSegment("data_unc",DATA_UNCACHED_BASE,DATA_UNCACHED_SIZE,0           ,0          ,true );


    Parameters * param = new Parameters
      (nb_entity,
       
       iaccess_nb_context,
       iaccess_nb_instruction,
       iaccess_nb_packet,
       iaccess_size_address,
       iaccess_size_data,
       
       daccess_nb_context,
       daccess_nb_packet,
       daccess_size_address,
       daccess_size_data,

       buffer_irsp_size,
       buffer_drsp_size,
       
       icache_nb_level     ,
       icache_nb_port      ,
       icache_nb_line      ,
       icache_size_line    ,
       icache_size_word    ,
       icache_associativity,
       icache_hit_latence  ,
       icache_miss_penality,
       dcache_nb_level     ,
       dcache_nb_port      ,
       dcache_nb_line      ,
       dcache_size_line    ,
       dcache_size_word    ,
       dcache_associativity,
       dcache_hit_latence  ,
       dcache_miss_penality,
       1                             ,
//     cache_shared_nb_port          ,
       cache_shared_nb_line          ,
       cache_shared_size_line        ,
       cache_shared_size_word        ,
       cache_shared_associativity    ,
       cache_shared_hit_latence      ,
       cache_shared_miss_penality    ,
       
       nb_component_tty,
       tty_address,
       nb_tty,
       name_tty,
       false, // don't execute xtty
       
       nb_component_ramlock,
       ramlock_address,
       nb_lock,
       
       sim2os_address,
       sim2os_size,
       segtable
       );

    segtable->print();

    Environment * env = new Environment ("environment",param);

    const char * filename = "Data/selftest/data/soft.x";
    const char * sections_text  []  = {".text",NULL}; 
    const char * sections_data  []  = {".data",".rodata",".bss",".sdata",".sbss", NULL}; 

    env->init("text"   , filename, sections_text);
    env->init("data"   , filename, sections_data);

//     cout << "<main> Press <Enter> to stop the test" << endl;
//     getchar();

    //==============================================================================
    //===== [ DECLARATION ]=========================================================
    //==============================================================================

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

    sc_signal<Tcontrol_t           >  *** ICACHE_REQ_VAL        = new sc_signal<Tcontrol_t           >  ** [nb_entity];
    sc_signal<Tcontrol_t           >  *** ICACHE_REQ_ACK        = new sc_signal<Tcontrol_t           >  ** [nb_entity];
    sc_signal<Ticache_context_t    >  *** ICACHE_REQ_CONTEXT_ID = new sc_signal<Ticache_context_t    >  ** [nb_entity];
    sc_signal<Ticache_packet_t     >  *** ICACHE_REQ_PACKET_ID  = new sc_signal<Ticache_packet_t     >  ** [nb_entity];
    sc_signal<Ticache_address_t    >  *** ICACHE_REQ_ADDRESS    = new sc_signal<Ticache_address_t    >  ** [nb_entity];
    sc_signal<Ticache_type_t       >  *** ICACHE_REQ_TYPE       = new sc_signal<Ticache_type_t       >  ** [nb_entity];

    sc_signal<Tcontrol_t           >  *** ICACHE_RSP_VAL        = new sc_signal<Tcontrol_t           >  ** [nb_entity];
    sc_signal<Tcontrol_t           >  *** ICACHE_RSP_ACK        = new sc_signal<Tcontrol_t           >  ** [nb_entity];
    sc_signal<Ticache_context_t    >  *** ICACHE_RSP_CONTEXT_ID = new sc_signal<Ticache_context_t    >  ** [nb_entity];
    sc_signal<Ticache_packet_t     >  *** ICACHE_RSP_PACKET_ID  = new sc_signal<Ticache_packet_t     >  ** [nb_entity];
    sc_signal<Ticache_instruction_t> **** ICACHE_RSP_INSTRUCTION= new sc_signal<Ticache_instruction_t> *** [nb_entity];//[nb_instruction]
    sc_signal<Ticache_error_t      >  *** ICACHE_RSP_ERROR      = new sc_signal<Ticache_error_t      >  ** [nb_entity];

    sc_signal<Tcontrol_t           >  *** DCACHE_REQ_VAL        = new sc_signal<Tcontrol_t           >  ** [nb_entity];
    sc_signal<Tcontrol_t           >  *** DCACHE_REQ_ACK        = new sc_signal<Tcontrol_t           >  ** [nb_entity];
    sc_signal<Tdcache_context_t    >  *** DCACHE_REQ_CONTEXT_ID = new sc_signal<Tdcache_context_t    >  ** [nb_entity];
    sc_signal<Tdcache_packet_t     >  *** DCACHE_REQ_PACKET_ID  = new sc_signal<Tdcache_packet_t     >  ** [nb_entity];
    sc_signal<Tdcache_address_t    >  *** DCACHE_REQ_ADDRESS    = new sc_signal<Tdcache_address_t    >  ** [nb_entity];
    sc_signal<Tdcache_type_t       >  *** DCACHE_REQ_TYPE       = new sc_signal<Tdcache_type_t       >  ** [nb_entity];
    sc_signal<Tdcache_data_t       >  *** DCACHE_REQ_WDATA      = new sc_signal<Tdcache_data_t       >  ** [nb_entity];

    sc_signal<Tcontrol_t           >  *** DCACHE_RSP_VAL        = new sc_signal<Tcontrol_t           >  ** [nb_entity];
    sc_signal<Tcontrol_t           >  *** DCACHE_RSP_ACK        = new sc_signal<Tcontrol_t           >  ** [nb_entity];
    sc_signal<Tdcache_context_t    >  *** DCACHE_RSP_CONTEXT_ID = new sc_signal<Tdcache_context_t    >  ** [nb_entity];
    sc_signal<Tdcache_packet_t     >  *** DCACHE_RSP_PACKET_ID  = new sc_signal<Tdcache_packet_t     >  ** [nb_entity];
    sc_signal<Tdcache_data_t       >  *** DCACHE_RSP_RDATA      = new sc_signal<Tdcache_data_t       >  ** [nb_entity];
    sc_signal<Tdcache_error_t      >  *** DCACHE_RSP_ERROR      = new sc_signal<Tdcache_error_t      >  ** [nb_entity];

    for (uint32_t i=0; i<nb_entity; i++)
      {
	ICACHE_REQ_VAL        [i] = new sc_signal<Tcontrol_t           >  * [icache_nb_port[i]];
	ICACHE_REQ_ACK        [i] = new sc_signal<Tcontrol_t           >  * [icache_nb_port[i]];
	ICACHE_REQ_CONTEXT_ID [i] = new sc_signal<Ticache_context_t    >  * [icache_nb_port[i]];
	ICACHE_REQ_PACKET_ID  [i] = new sc_signal<Ticache_packet_t     >  * [icache_nb_port[i]];
	ICACHE_REQ_ADDRESS    [i] = new sc_signal<Ticache_address_t    >  * [icache_nb_port[i]];
	ICACHE_REQ_TYPE       [i] = new sc_signal<Ticache_type_t       >  * [icache_nb_port[i]];

	ICACHE_RSP_VAL        [i] = new sc_signal<Tcontrol_t           >  * [icache_nb_port[i]];
	ICACHE_RSP_ACK        [i] = new sc_signal<Tcontrol_t           >  * [icache_nb_port[i]];
	ICACHE_RSP_CONTEXT_ID [i] = new sc_signal<Ticache_context_t    >  * [icache_nb_port[i]];
	ICACHE_RSP_PACKET_ID  [i] = new sc_signal<Ticache_packet_t     >  * [icache_nb_port[i]];
	ICACHE_RSP_INSTRUCTION[i] = new sc_signal<Ticache_instruction_t> ** [icache_nb_port[i]];//[nb_instruction]
	ICACHE_RSP_ERROR      [i] = new sc_signal<Ticache_error_t      >  * [icache_nb_port[i]];
	
	for (uint32_t j=0; j<icache_nb_port[i]; j++)
	  {
	    ICACHE_REQ_VAL         [i][j] = new sc_signal<Tcontrol_t           > ("");
	    ICACHE_REQ_ACK         [i][j] = new sc_signal<Tcontrol_t           > ("");
	    ICACHE_REQ_CONTEXT_ID  [i][j] = new sc_signal<Ticache_context_t    > ("");
	    ICACHE_REQ_PACKET_ID   [i][j] = new sc_signal<Ticache_packet_t     > ("");
	    ICACHE_REQ_ADDRESS     [i][j] = new sc_signal<Ticache_address_t    > ("");
	    ICACHE_REQ_TYPE        [i][j] = new sc_signal<Ticache_type_t       > ("");
	    
	    ICACHE_RSP_VAL         [i][j] = new sc_signal<Tcontrol_t           > ("");
	    ICACHE_RSP_ACK         [i][j] = new sc_signal<Tcontrol_t           > ("");
	    ICACHE_RSP_CONTEXT_ID  [i][j] = new sc_signal<Ticache_context_t    > ("");
	    ICACHE_RSP_PACKET_ID   [i][j] = new sc_signal<Ticache_packet_t     > ("");
	    ICACHE_RSP_ERROR       [i][j] = new sc_signal<Ticache_error_t      > ("");
	    
	    ICACHE_RSP_INSTRUCTION [i][j] = new sc_signal<Ticache_instruction_t> * [iaccess_nb_instruction[i]];
	    
	    for (uint32_t k=0; k<iaccess_nb_instruction[i]; k++)
	      ICACHE_RSP_INSTRUCTION [i][j][k] = new sc_signal<Ticache_instruction_t> ("");

	  }
	
	DCACHE_REQ_VAL        [i] = new sc_signal<Tcontrol_t           >  * [dcache_nb_port[i]];
	DCACHE_REQ_ACK        [i] = new sc_signal<Tcontrol_t           >  * [dcache_nb_port[i]];
	DCACHE_REQ_CONTEXT_ID [i] = new sc_signal<Tdcache_context_t    >  * [dcache_nb_port[i]];
	DCACHE_REQ_PACKET_ID  [i] = new sc_signal<Tdcache_packet_t     >  * [dcache_nb_port[i]];
	DCACHE_REQ_ADDRESS    [i] = new sc_signal<Tdcache_address_t    >  * [dcache_nb_port[i]];
	DCACHE_REQ_TYPE       [i] = new sc_signal<Tdcache_type_t       >  * [dcache_nb_port[i]];
	DCACHE_REQ_WDATA      [i] = new sc_signal<Tdcache_data_t       >  * [dcache_nb_port[i]];

	DCACHE_RSP_VAL        [i] = new sc_signal<Tcontrol_t           >  * [dcache_nb_port[i]];
	DCACHE_RSP_ACK        [i] = new sc_signal<Tcontrol_t           >  * [dcache_nb_port[i]];
	DCACHE_RSP_CONTEXT_ID [i] = new sc_signal<Tdcache_context_t    >  * [dcache_nb_port[i]];
	DCACHE_RSP_PACKET_ID  [i] = new sc_signal<Tdcache_packet_t     >  * [dcache_nb_port[i]];
	DCACHE_RSP_RDATA      [i] = new sc_signal<Tdcache_data_t       >  * [dcache_nb_port[i]];
	DCACHE_RSP_ERROR      [i] = new sc_signal<Tdcache_error_t      >  * [dcache_nb_port[i]];
	
	for (uint32_t j=0; j<dcache_nb_port[i]; j++)
	  {
	    DCACHE_REQ_VAL        [i][j] = new sc_signal<Tcontrol_t           > ("");
	    DCACHE_REQ_ACK        [i][j] = new sc_signal<Tcontrol_t           > ("");
	    DCACHE_REQ_CONTEXT_ID [i][j] = new sc_signal<Tdcache_context_t    > ("");
	    DCACHE_REQ_PACKET_ID  [i][j] = new sc_signal<Tdcache_packet_t     > ("");
	    DCACHE_REQ_ADDRESS    [i][j] = new sc_signal<Tdcache_address_t    > ("");
	    DCACHE_REQ_TYPE       [i][j] = new sc_signal<Tdcache_type_t       > ("");
	    DCACHE_REQ_WDATA      [i][j] = new sc_signal<Tdcache_data_t       > ("");
	    
	    DCACHE_RSP_VAL        [i][j] = new sc_signal<Tcontrol_t           > ("");
	    DCACHE_RSP_ACK        [i][j] = new sc_signal<Tcontrol_t           > ("");
	    DCACHE_RSP_CONTEXT_ID [i][j] = new sc_signal<Tdcache_context_t    > ("");
	    DCACHE_RSP_PACKET_ID  [i][j] = new sc_signal<Tdcache_packet_t     > ("");
	    DCACHE_RSP_RDATA      [i][j] = new sc_signal<Tdcache_data_t       > ("");
	    DCACHE_RSP_ERROR      [i][j] = new sc_signal<Tdcache_error_t      > ("");
	  }
      }
    
    //==============================================================================
    //===== [ INSTANCE ]============================================================
    //==============================================================================

    // instance
    (*(env->CLOCK )) (*(CLOCK ));
    (*(env->NRESET)) (*(NRESET));

    for (uint32_t i=0; i<nb_entity; i++)
      {
	for (uint32_t j=0; j<icache_nb_port[i]; j++)
	  {
	    (*(env->ICACHE_REQ_VAL         [i][j])) (*(ICACHE_REQ_VAL         [i][j]));
	    (*(env->ICACHE_REQ_ACK         [i][j])) (*(ICACHE_REQ_ACK         [i][j]));
	    (*(env->ICACHE_REQ_CONTEXT_ID  [i][j])) (*(ICACHE_REQ_CONTEXT_ID  [i][j]));
	    (*(env->ICACHE_REQ_PACKET_ID   [i][j])) (*(ICACHE_REQ_PACKET_ID   [i][j]));
	    (*(env->ICACHE_REQ_ADDRESS     [i][j])) (*(ICACHE_REQ_ADDRESS     [i][j]));
	    (*(env->ICACHE_REQ_TYPE        [i][j])) (*(ICACHE_REQ_TYPE        [i][j]));

	    (*(env->ICACHE_RSP_VAL         [i][j])) (*(ICACHE_RSP_VAL         [i][j]));
	    (*(env->ICACHE_RSP_ACK         [i][j])) (*(ICACHE_RSP_ACK         [i][j]));
	    (*(env->ICACHE_RSP_CONTEXT_ID  [i][j])) (*(ICACHE_RSP_CONTEXT_ID  [i][j]));
	    (*(env->ICACHE_RSP_PACKET_ID   [i][j])) (*(ICACHE_RSP_PACKET_ID   [i][j]));
	    (*(env->ICACHE_RSP_ERROR       [i][j])) (*(ICACHE_RSP_ERROR       [i][j]));
	    
	    for (uint32_t k=0; k<iaccess_nb_instruction[i]; k++)
	      (*(env->ICACHE_RSP_INSTRUCTION [i][j][k])) (*(ICACHE_RSP_INSTRUCTION [i][j][k]));

	  }
	
	for (uint32_t j=0; j<dcache_nb_port[i]; j++)
	  {
	    (*(env->DCACHE_REQ_VAL        [i][j])) (*(DCACHE_REQ_VAL        [i][j]));
	    (*(env->DCACHE_REQ_ACK        [i][j])) (*(DCACHE_REQ_ACK        [i][j]));
	    (*(env->DCACHE_REQ_CONTEXT_ID [i][j])) (*(DCACHE_REQ_CONTEXT_ID [i][j]));
	    (*(env->DCACHE_REQ_PACKET_ID  [i][j])) (*(DCACHE_REQ_PACKET_ID  [i][j]));
	    (*(env->DCACHE_REQ_ADDRESS    [i][j])) (*(DCACHE_REQ_ADDRESS    [i][j]));
	    (*(env->DCACHE_REQ_TYPE       [i][j])) (*(DCACHE_REQ_TYPE       [i][j]));
	    (*(env->DCACHE_REQ_WDATA      [i][j])) (*(DCACHE_REQ_WDATA      [i][j]));

	    (*(env->DCACHE_RSP_VAL        [i][j])) (*(DCACHE_RSP_VAL        [i][j]));
	    (*(env->DCACHE_RSP_ACK        [i][j])) (*(DCACHE_RSP_ACK        [i][j]));
	    (*(env->DCACHE_RSP_CONTEXT_ID [i][j])) (*(DCACHE_RSP_CONTEXT_ID [i][j]));
	    (*(env->DCACHE_RSP_PACKET_ID  [i][j])) (*(DCACHE_RSP_PACKET_ID  [i][j]));
	    (*(env->DCACHE_RSP_RDATA      [i][j])) (*(DCACHE_RSP_RDATA      [i][j]));
	    (*(env->DCACHE_RSP_ERROR      [i][j])) (*(DCACHE_RSP_ERROR      [i][j]));
	  }
      }

    //==============================================================================
    //===== [ INIT ]================================================================
    //==============================================================================

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

    sc_start(0);
    // reset
    NRESET->write(0);
    sc_start(5);
    NRESET->write(1);
    sc_start(1);

//     cout << *env << endl;

    //==============================================================================
    //===== [ ICACHE ]==============================================================
    //==============================================================================

    if (_TEST_IMEMORY_)
      {
	cout << "Test : ICACHE" << endl;
	// Test no respons
	
	for (uint32_t i = 0; i < param->nb_entity; i++)
	  for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
	    {
	      TEST(ICACHE_RSP_VAL [i][j]->read(), 0);
	      ICACHE_RSP_ACK [i][j]->write(0);
	    }
	
	for (uint32_t i = 0; i < param->nb_entity; i++)
	  for (uint32_t j=0; j<param->dcache_dedicated_nb_port [i]; j++)
	    {
	      TEST(DCACHE_RSP_VAL [i][j]->read(), 0);
	      DCACHE_RSP_ACK [i][j]->write(0);
	    }
	
	const int32_t percent_transaction_icache_req = 75;
	const int32_t percent_transaction_icache_rsp = 75;
	
	uint32_t packet_req = 0;
	uint32_t packet_rsp = 0;
	
	Ticache_address_t addr_max = 0xf0;
	
	do
	  {
	    Ticache_packet_t packet_req_next = packet_req;
	    
	    Ticache_address_t addr = (packet_req_next << 2);
	    for (uint32_t i=0; i<param->nb_entity; i++)
	      for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
		{
		  ICACHE_REQ_VAL        [i][j]->write((addr < addr_max) and ((rand()%100)<percent_transaction_icache_req));
		  ICACHE_REQ_CONTEXT_ID [i][j]->write(0);
		  ICACHE_REQ_ADDRESS    [i][j]->write(addr>>2);
		  ICACHE_REQ_PACKET_ID  [i][j]->write(addr>>2);
		  ICACHE_REQ_TYPE       [i][j]->write(ICACHE_TYPE_LOAD);
		  
		  packet_req_next++;
		  addr += (param->iaccess_nb_instruction[i]<<2);
		}
	    
	    for (uint32_t i=0; i<param->nb_entity; i++)
	      for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
		{
		  ICACHE_RSP_ACK        [i][j]->write((rand()%100)<percent_transaction_icache_rsp) ;
		}
	    
	    sc_start(1);
	    
	    for (uint32_t i=0; i<param->nb_entity; i++)
	      for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
		{
		  cout << "ICACHE_REQ_VALACK (" << ICACHE_REQ_VAL [i][j]->read() << "," << ICACHE_REQ_ACK [i][j]->read() << ")" << endl;
		  if (ICACHE_REQ_VAL [i][j]->read() and
		      ICACHE_REQ_ACK [i][j]->read())
		    {
		      cout << "packet_req : " << packet_req << endl;
		      packet_req ++;
		    }
		}
	    
	    for (uint32_t i=0; i<param->nb_entity; i++)
	      for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
		{
		  cout << "ICACHE_RSP_VALACK (" << ICACHE_RSP_VAL [i][j]->read() << "," << ICACHE_RSP_ACK [i][j]->read() << ")" << endl;
		  if (ICACHE_RSP_VAL [i][j]->read() and
		      ICACHE_RSP_ACK [i][j]->read())
		    {
		      cout << "packet_rsp : " << packet_rsp << endl;
		      packet_rsp ++;
		      
		      TEST(ICACHE_RSP_ERROR     [i][j]->read(),ICACHE_ERROR_NONE);
		      TEST(ICACHE_RSP_CONTEXT_ID[i][j]->read(),0);
		      
		      Ticache_packet_t packet = ICACHE_RSP_PACKET_ID [i][j]->read();
		      
		      for (unsigned int k=0; k<param->iaccess_nb_instruction[i]; k++)
			{
			  Ticache_instruction_t inst = ICACHE_RSP_INSTRUCTION[i][j][k]->read();
			  cout << "instruction [" << k << "] : " << std::hex << inst << std::dec << endl;
			  
			  TEST((inst>>16) , 0x1500); // copdop nop
			  TEST((inst&0xffff) , ((0xffff ^ (packet+k))+1)); // packet in CA2
			}
		      
		    }
		}
	    
	  } while (((packet_req<<2)< addr_max) or
		   ((packet_rsp<<2)< addr_max));
	
	for (uint32_t i=0; i<param->nb_entity; i++)
	  {
	    for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
	      ICACHE_REQ_VAL [i][j]->write(0);
	    for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
	      ICACHE_RSP_ACK [i][j]->write(1);
	  }
	
	sc_start(50);

	for (uint32_t i=0; i<param->nb_entity; i++)
	  for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
	    ICACHE_RSP_ACK [i][j]->write(0);
	
	cout << "Test : icache - bus error" << endl;

	// 1) in not valid segment
	ICACHE_REQ_VAL        [0][0]->write(1);
	ICACHE_REQ_CONTEXT_ID [0][0]->write(0);
	ICACHE_REQ_ADDRESS    [0][0]->write(0xe0000000>>2);
	ICACHE_REQ_PACKET_ID  [0][0]->write(21);
	ICACHE_REQ_TYPE       [0][0]->write(ICACHE_TYPE_LOAD);
	ICACHE_RSP_ACK        [0][0]->write(1);
	do
	  {
	    sc_start(1);
	  } while (ICACHE_REQ_ACK [0][0]->read() == 0);
	ICACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(ICACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(ICACHE_RSP_VAL [0][0]->read(), 1);
	TEST(ICACHE_RSP_CONTEXT_ID  [0][0]   ->read(), 0);
	TEST(ICACHE_RSP_PACKET_ID   [0][0]   ->read(), 21);
	TEST(ICACHE_RSP_INSTRUCTION [0][0][0]->read(), 0xe0000000);
	TEST(ICACHE_RSP_ERROR       [0][0]   ->read(), ICACHE_ERROR_BUS_ERROR);
	sc_start (1);
	TEST(ICACHE_RSP_VAL [0][0]->read(), 0);

	sc_start (10);
	
	// 2) in     valid segment but not memory
	ICACHE_REQ_VAL        [0][0]->write(1);
	ICACHE_REQ_CONTEXT_ID [0][0]->write(0);
	ICACHE_REQ_ADDRESS    [0][0]->write(0xa0000000>>2);
	ICACHE_REQ_PACKET_ID  [0][0]->write(21);
	ICACHE_REQ_TYPE       [0][0]->write(ICACHE_TYPE_LOAD);
	ICACHE_RSP_ACK        [0][0]->write(1);
	do
	  {
	    sc_start(1);
	  } while (ICACHE_REQ_ACK [0][0]->read() == 0);
	ICACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(ICACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(ICACHE_RSP_VAL [0][0]->read(), 1);
	TEST(ICACHE_RSP_CONTEXT_ID  [0][0]   ->read(), 0);
	TEST(ICACHE_RSP_PACKET_ID   [0][0]   ->read(), 21);
	TEST(ICACHE_RSP_INSTRUCTION [0][0][0]->read(), 0xa0000000);
	TEST(ICACHE_RSP_ERROR       [0][0]   ->read(), ICACHE_ERROR_BUS_ERROR);
	sc_start (1);
	TEST(ICACHE_RSP_VAL [0][0]->read(), 0);
	ICACHE_RSP_ACK        [0][0]->write(0);
      }

    //==============================================================================
    //===== [ TTY ]=================================================================
    //==============================================================================
    if (_TEST_TTY_)
      {
	cout << "Test : TTY" << endl;
	
	for (uint32_t i=0; i<param->nb_entity; i++)
	  for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
	    {
	      DCACHE_REQ_VAL        [i][j]->write(1);
	      DCACHE_REQ_CONTEXT_ID [i][j]->write(0);
	      DCACHE_REQ_PACKET_ID  [i][j]->write(0);
	      DCACHE_REQ_ADDRESS    [i][j]->write(tty_address[0]+(2<<2));
	      DCACHE_REQ_TYPE       [i][j]->write(DCACHE_TYPE_STORE_32);
	      DCACHE_REQ_WDATA      [i][j]->write(0xdeadbeef);
	    }
	
	sc_start(1);
	for (uint32_t i=0; i<param->nb_entity; i++)
	  for (uint32_t j=0; j<param->icache_dedicated_nb_port [i]; j++)
	    DCACHE_REQ_VAL        [i][j]->write(0);

	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_STORE_8);
	DCACHE_REQ_ADDRESS    [0][0]->write(tty_address[0]);
	
	char msg1 [] = "kane is back\n";
	
	for (uint32_t i=0; i<strlen(msg1); i++)
	  do
	    {
	      DCACHE_REQ_WDATA      [0][0]->write(msg1[i]);
	      sc_start(1);
	    } while (not DCACHE_REQ_ACK [0][0]->read());
	
	
	DCACHE_REQ_ADDRESS    [0][0]->write(tty_address[0]+(2<<4));
	char msg2 [] = "La Technologie au service de la paix\nEt au nom de kane !!!!!!!!!";
	
	for (uint32_t i=0; i<strlen(msg2); i++)
	  do
	    {
	      DCACHE_REQ_WDATA      [0][0]->write(msg2[i]);
	      sc_start(1);
	    } while (not DCACHE_REQ_ACK [0][0]->read());
	
	DCACHE_REQ_VAL        [0][0]->write(0);
	
	cout << "Test : TTY - bus error" << endl;
	
	// 1) bad access : load
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xa0000000);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_32);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0xa0000000);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_BUS_ERROR);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);
	
	// 2) bad register
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xa000000c);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_STORE_8);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0xa000000c);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_BUS_ERROR);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);


	// 3) bad tty number
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xa0000040);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_STORE_8);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0xa0000040);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_BUS_ERROR);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);
      }

    //==============================================================================
    //===== [ RAMLOCK ]=============================================================
    //==============================================================================
    if (_TEST_RAMLOCK_)
      {
	cout << "Test : RAMLOCK" << endl;

	// Test if lock : no
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xb0000003);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_8);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0x00000000);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);

	// Test if lock : yes
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xb0000003);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_8);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0x00000001);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);

	// Test if lock : no
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xb0000004);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_8);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0x00000000);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);

	// Test if lock : yes
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xb0000004);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_8);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0x00000001);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);


	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xb0000003);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_STORE_8);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);

	sc_start (1);

	// Test if lock : no
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xb0000003);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_8);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0x00000000);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);

	// Test if lock : yes
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xb0000003);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_8);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0x00000001);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);


	sc_start (5);
	// Bus Error

	// 1) size access
	// Test if lock : yes
	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xb0000003);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_16);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	sc_start (9);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 1);
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0xb0000003);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_BUS_ERROR);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);

      }

    //==============================================================================
    //===== [ MEMORY ]==============================================================
    //==============================================================================
    if (_TEST_DMEMORY_)
      {
	cout << "Test : MEMORY" << endl;

	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0x10000100);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_STORE_32);
	DCACHE_REQ_WDATA      [0][0]->write(0xdeadbeef);
	DCACHE_RSP_ACK        [0][0]->write(0);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);



	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0x10000100);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_32);
	DCACHE_REQ_WDATA      [0][0]->write(0x77777777);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	while (DCACHE_RSP_VAL [0][0]->read() == 0)
	  sc_start (1);
	
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0xdeadbeef);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);



	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0x10000100);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_16);
	DCACHE_REQ_WDATA      [0][0]->write(0x77777777);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	while (DCACHE_RSP_VAL [0][0]->read() == 0)
	  sc_start (1);
	
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0xdeaddead);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);

	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0x10000102);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_16);
	DCACHE_REQ_WDATA      [0][0]->write(0x77777777);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	while (DCACHE_RSP_VAL [0][0]->read() == 0)
	  sc_start (1);
	
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 0xbeefbeef);
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);

      }

    //==============================================================================
    //===== [ SIM2OS ]==============================================================
    //==============================================================================
    if (_TEST_SIM2OS_)
      {
	cout << "Test : SIM2OS" << endl;

	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xc0000000);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_STORE_32);
	DCACHE_REQ_WDATA      [0][0]->write(SERVICE_CLOCK);
	DCACHE_RSP_ACK        [0][0]->write(0);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);



	DCACHE_REQ_VAL        [0][0]->write(1);
	DCACHE_REQ_CONTEXT_ID [0][0]->write(0);
	DCACHE_REQ_PACKET_ID  [0][0]->write(21);
	DCACHE_REQ_ADDRESS    [0][0]->write(0xc0000004);
	DCACHE_REQ_TYPE       [0][0]->write(DCACHE_TYPE_LOAD_32);
	DCACHE_REQ_WDATA      [0][0]->write(0x77777777);
	DCACHE_RSP_ACK        [0][0]->write(1);
	// Wait ack
	do
	  {
	    sc_start(1);
	  } while (DCACHE_REQ_ACK [0][0]->read() == 0);
	DCACHE_REQ_VAL        [0][0]->write(0);

	while (DCACHE_RSP_VAL [0][0]->read() == 0)
	  sc_start (1);
	
	TEST(DCACHE_RSP_CONTEXT_ID  [0][0]->read(), 0);
	TEST(DCACHE_RSP_PACKET_ID   [0][0]->read(), 21);
	TEST(DCACHE_RSP_RDATA       [0][0]->read(), 354); // if all test is activate
	TEST(DCACHE_RSP_ERROR       [0][0]->read(), DCACHE_ERROR_NONE);
	sc_start (1);
	TEST(DCACHE_RSP_VAL [0][0]->read(), 0);
	DCACHE_RSP_ACK      [0][0]->write(0);

	
      }

    //==============================================================================
    //===== [ END TEST ]============================================================
    //==============================================================================

    cout << "<main> Press <Enter> to stop the test" << endl;
    getchar();

    delete CLOCK ;
    delete NRESET;

    for (uint32_t i=0; i<nb_entity; i++)
      {
	for (uint32_t j=0; j<icache_nb_port[i]; j++)
	  {
	    delete ICACHE_REQ_VAL         [i][j];
	    delete ICACHE_REQ_ACK         [i][j];
	    delete ICACHE_REQ_CONTEXT_ID  [i][j];
	    delete ICACHE_REQ_PACKET_ID   [i][j];
	    delete ICACHE_REQ_ADDRESS     [i][j];
	    delete ICACHE_REQ_TYPE        [i][j];
	    delete ICACHE_RSP_VAL         [i][j];
	    delete ICACHE_RSP_ACK         [i][j];
	    delete ICACHE_RSP_CONTEXT_ID  [i][j];
	    delete ICACHE_RSP_PACKET_ID   [i][j];
	    delete ICACHE_RSP_ERROR       [i][j];

	    for (uint32_t k=0; k<iaccess_nb_instruction[i]; k++)
	      delete ICACHE_RSP_INSTRUCTION [i][j][k];

	    delete [] ICACHE_RSP_INSTRUCTION [i][j];
	  }
	delete [] ICACHE_REQ_VAL         [i];
	delete [] ICACHE_REQ_ACK         [i];
	delete [] ICACHE_REQ_CONTEXT_ID  [i];
	delete [] ICACHE_REQ_PACKET_ID   [i];
	delete [] ICACHE_REQ_ADDRESS     [i];
	delete [] ICACHE_REQ_TYPE        [i];
	delete [] ICACHE_RSP_VAL         [i];
	delete [] ICACHE_RSP_ACK         [i];
	delete [] ICACHE_RSP_CONTEXT_ID  [i];
	delete [] ICACHE_RSP_PACKET_ID   [i];
	delete [] ICACHE_RSP_ERROR       [i];
	delete [] ICACHE_RSP_INSTRUCTION [i];
      }
    
    delete [] ICACHE_REQ_VAL        ;
    delete [] ICACHE_REQ_ACK        ;
    delete [] ICACHE_REQ_CONTEXT_ID ;
    delete [] ICACHE_REQ_PACKET_ID  ;
    delete [] ICACHE_REQ_ADDRESS    ;
    delete [] ICACHE_REQ_TYPE       ;
    delete [] ICACHE_RSP_VAL        ;
    delete [] ICACHE_RSP_ACK        ;
    delete [] ICACHE_RSP_CONTEXT_ID ;
    delete [] ICACHE_RSP_PACKET_ID  ;
    delete [] ICACHE_RSP_INSTRUCTION;
    delete [] ICACHE_RSP_ERROR      ;
    
    for (uint32_t i=0; i<nb_entity; i++)
      {
	for (uint32_t j=0; j<icache_nb_port[i]; j++)
	  {
	    delete DCACHE_REQ_VAL        [i][j];
	    delete DCACHE_REQ_ACK        [i][j];
	    delete DCACHE_REQ_CONTEXT_ID [i][j];
	    delete DCACHE_REQ_PACKET_ID  [i][j];
	    delete DCACHE_REQ_ADDRESS    [i][j];
	    delete DCACHE_REQ_TYPE       [i][j];
	    delete DCACHE_REQ_WDATA      [i][j];
	    delete DCACHE_RSP_VAL        [i][j];
	    delete DCACHE_RSP_ACK        [i][j];
	    delete DCACHE_RSP_CONTEXT_ID [i][j];
	    delete DCACHE_RSP_PACKET_ID  [i][j];
	    delete DCACHE_RSP_RDATA      [i][j];
	    delete DCACHE_RSP_ERROR      [i][j];
	  }

	delete [] DCACHE_REQ_VAL        [i];
	delete [] DCACHE_REQ_ACK        [i];
	delete [] DCACHE_REQ_CONTEXT_ID [i];
	delete [] DCACHE_REQ_PACKET_ID  [i];
	delete [] DCACHE_REQ_ADDRESS    [i];
	delete [] DCACHE_REQ_TYPE       [i];
	delete [] DCACHE_REQ_WDATA      [i];
	delete [] DCACHE_RSP_VAL        [i];
	delete [] DCACHE_RSP_ACK        [i];
	delete [] DCACHE_RSP_CONTEXT_ID [i];
	delete [] DCACHE_RSP_PACKET_ID  [i];
	delete [] DCACHE_RSP_RDATA      [i];
	delete [] DCACHE_RSP_ERROR      [i];
      }

    delete [] DCACHE_REQ_VAL        ;
    delete [] DCACHE_REQ_ACK        ;
    delete [] DCACHE_REQ_CONTEXT_ID ;
    delete [] DCACHE_REQ_PACKET_ID  ;
    delete [] DCACHE_REQ_ADDRESS    ;
    delete [] DCACHE_REQ_TYPE       ;
    delete [] DCACHE_REQ_WDATA      ;
    delete [] DCACHE_RSP_VAL        ;
    delete [] DCACHE_RSP_ACK        ;
    delete [] DCACHE_RSP_CONTEXT_ID ;
    delete [] DCACHE_RSP_PACKET_ID  ;
    delete [] DCACHE_RSP_RDATA      ;
    delete [] DCACHE_RSP_ERROR      ;
    
    delete    env;

    delete    param;
    delete    segtable;

    delete [] ramlock_address;
    delete [] nb_lock;
  
    delete [] name_tty [0];
    delete [] name_tty;
    delete [] tty_address;
    delete [] nb_tty;

    delete [] cache_shared_nb_line      ;
    delete [] cache_shared_size_line    ;
    delete [] cache_shared_size_word    ;
    delete [] cache_shared_associativity;
    delete [] cache_shared_hit_latence  ;
    delete [] cache_shared_miss_penality;
    delete [] icache_nb_level      ;
    delete [] icache_nb_port       ;
    delete [] icache_nb_line       [0];
    delete [] icache_size_line     [0];
    delete [] icache_size_word     [0];
    delete [] icache_associativity [0];
    delete [] icache_hit_latence   [0];
    delete [] icache_miss_penality [0];
    delete [] icache_nb_line       [1];
    delete [] icache_size_line     [1];
    delete [] icache_size_word     [1];
    delete [] icache_associativity [1];
    delete [] icache_hit_latence   [1];
    delete [] icache_miss_penality [1];
    delete [] icache_nb_line       ;
    delete [] icache_size_line     ;
    delete [] icache_size_word     ;
    delete [] icache_associativity ;
    delete [] icache_hit_latence   ;
    delete [] icache_miss_penality ;
    delete [] dcache_nb_level      ;
    delete [] dcache_nb_port       ;
    delete [] dcache_nb_line       [0];
    delete [] dcache_size_line     [0];
    delete [] dcache_size_word     [0];
    delete [] dcache_associativity [0];
    delete [] dcache_hit_latence   [0];
    delete [] dcache_miss_penality [0];
    delete [] dcache_nb_line       [1];
    delete [] dcache_size_line     [1];
    delete [] dcache_size_word     [1];
    delete [] dcache_associativity [1];
    delete [] dcache_hit_latence   [1];
    delete [] dcache_miss_penality [1];
    delete [] dcache_nb_line       ;
    delete [] dcache_size_line     ;
    delete [] dcache_size_word     ;
    delete [] dcache_associativity ;
    delete [] dcache_hit_latence   ;
    delete [] dcache_miss_penality ;

    delete [] iaccess_nb_context    ;
    delete [] iaccess_nb_instruction;
    delete [] iaccess_nb_packet     ;
    delete [] iaccess_size_address  ;
    delete [] iaccess_size_data     ;
    delete [] daccess_nb_context    ;
    delete [] daccess_nb_packet     ;
    delete [] daccess_size_address  ;
    delete [] daccess_size_data     ;

    delete [] buffer_irsp_size;
    delete [] buffer_drsp_size;    
  }
  cout << "<main> End" << endl;
  
  return EXIT_SUCCESS;
}
