/*
 * $Id: test.cpp 138 2010-05-12 17:34:01Z rosiere $
 *
 * [ Description ]
 * 
 * Platforms : Morpheo + Environment
 */

#define CYCLE_MAX 0

#include "../include/test.h"

#include "Environment.h"
#include "Behavioural/include/Allocation.h"
#include "Common/include/Time.h"
#include "../../../IPs/systemC/shared/mapping_memory.h"
#include "../../../IPs/systemC/processor/Morpheo/Common/include/Test.h"

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

int test(string   filename_simulator,
         string   filename_generator,
         string   filename_instance ,
         string   filename_software ,
         uint32_t nb_cache_dedicated,
         uint32_t nb_cache_shared   ,
         uint32_t cache_size        ,
         uint32_t cache_ratio       ,
         morpheo::behavioural::custom::custom_information_t (*get_custom_information) (void)
          )
{
  //==============================================================================
  //===== [ DECLARATION ]=========================================================
  //==============================================================================


  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //~~~~~ [ Morpheo  ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  // 1) Translation 
  if (setlocale (LC_ALL, "") == NULL)
    {
      msgError("Error setlocale.\n");
      exit (EXIT_FAILURE);
    }
  
  // 2) Morpheo Construction
  Morpheo * morpheo;
  try
    {
      morpheo = new Morpheo
        ("morpheo",
         filename_simulator, 
         filename_generator, 
         filename_instance ,
         get_custom_information
         );
    }
  catch (morpheo::ErrorMorpheo & error)
    {
      std::cerr << error.what() << std::endl;

      msgError("%s\n",STR_KO);
      
      return EXIT_FAILURE;
    }

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //~~~~~ [ Environment  ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  uint32_t    nb_thread = morpheo->_nb_thread;
  uint32_t    nb_entity = 1;

  // Cache access
  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] = morpheo->_nb_thread;
      iaccess_nb_instruction [i] = max<uint32_t>(morpheo->_icache_nb_instruction,morpheo->_nb_icache_port);
      iaccess_nb_packet      [i] = 1<<morpheo->_size_icache_packet_id;
      iaccess_size_address   [i] = morpheo->_size_icache_address;
      iaccess_size_data      [i] = morpheo->_size_icache_instruction;
      
      daccess_nb_context     [i] = morpheo->_nb_thread;
      daccess_nb_packet      [i] = 1<<morpheo->_size_dcache_packet_id;
      daccess_size_address   [i] = morpheo->_size_dcache_address;
      daccess_size_data      [i] = morpheo->_size_dcache_data;

      buffer_irsp_size       [i] =  8;
      buffer_drsp_size       [i] =  8;
    }

  uint32_t cache_nb_line       ;
  uint32_t cache_size_line     ;
  uint32_t cache_size_word     ;
  uint32_t cache_associativity ;
  uint32_t cache_hit_latence   ;
  uint32_t cache_miss_penality ;

  // Instruction/Data cache
  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];

  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++)
    {
      cache_size_word     = max(max<uint32_t>(morpheo->_icache_nb_instruction,morpheo->_nb_icache_port)*morpheo->_size_icache_instruction,morpheo->_size_dcache_data)/8;
      cache_size_line     = 8;

      if (cache_size<(cache_size_line*cache_size_word))
        {
          msgError("cache is too small\n");
          exit(EXIT_FAILURE);
        }

      cache_nb_line       = cache_size/(cache_size_line*cache_size_word);
      cache_associativity = 1;
      cache_hit_latence   = 1;
      cache_miss_penality = 5;

      icache_nb_level      [i]    = nb_cache_dedicated;
      icache_nb_port       [i]    = morpheo->_nb_icache_port;
      icache_nb_line       [i]    = new uint32_t [icache_nb_level[i]];
      icache_size_line     [i]    = new uint32_t [icache_nb_level[i]];
      icache_size_word     [i]    = new uint32_t [icache_nb_level[i]];
      icache_associativity [i]    = new uint32_t [icache_nb_level[i]];
      icache_hit_latence   [i]    = new uint32_t [icache_nb_level[i]];
      icache_miss_penality [i]    = new uint32_t [icache_nb_level[i]];

      dcache_nb_level      [i]    = icache_nb_level [i];
      dcache_nb_port       [i]    = morpheo->_nb_dcache_port;
      dcache_nb_line       [i]    = new uint32_t [dcache_nb_level[i]];
      dcache_size_line     [i]    = new uint32_t [dcache_nb_level[i]];
      dcache_size_word     [i]    = new uint32_t [dcache_nb_level[i]];
      dcache_associativity [i]    = new uint32_t [dcache_nb_level[i]];
      dcache_hit_latence   [i]    = new uint32_t [dcache_nb_level[i]];
      dcache_miss_penality [i]    = new uint32_t [dcache_nb_level[i]];
      
      for (uint32_t j=0; j<icache_nb_level[i]; ++j)
        {
          icache_nb_line       [i][j] = cache_nb_line      ;
          icache_size_line     [i][j] = cache_size_line    ;
          icache_size_word     [i][j] = cache_size_word    ;
          icache_associativity [i][j] = cache_associativity;
          icache_hit_latence   [i][j] = cache_hit_latence  ;
          icache_miss_penality [i][j] = cache_miss_penality;

          dcache_nb_line       [i][j] = cache_nb_line      ;
          dcache_size_line     [i][j] = cache_size_line    ;
          dcache_size_word     [i][j] = cache_size_word    ;
          dcache_associativity [i][j] = cache_associativity;
          dcache_hit_latence   [i][j] = cache_hit_latence  ;
          dcache_miss_penality [i][j] = cache_miss_penality;

          cache_nb_line       *= cache_ratio;
          cache_size_line     *= cache_ratio;
//        cache_size_word     *= cache_ratio;
          cache_associativity *= cache_ratio;
          cache_hit_latence   *= cache_ratio;
          cache_miss_penality *= cache_ratio;
        }
    }
  
  // Cache shared
  uint32_t * cache_shared_nb_line       = new uint32_t [nb_cache_shared];
  uint32_t * cache_shared_size_line     = new uint32_t [nb_cache_shared];
  uint32_t * cache_shared_size_word     = new uint32_t [nb_cache_shared];
  uint32_t * cache_shared_associativity = new uint32_t [nb_cache_shared];
  uint32_t * cache_shared_hit_latence   = new uint32_t [nb_cache_shared];
  uint32_t * cache_shared_miss_penality = new uint32_t [nb_cache_shared];

  for (uint32_t i=0; i<nb_cache_shared; ++i)
    {
      cache_shared_nb_line       [i] = cache_nb_line      ;
      cache_shared_size_line     [i] = cache_size_line    ;
      cache_shared_size_word     [i] = cache_size_word    ;
      cache_shared_associativity [i] = cache_associativity;
      cache_shared_hit_latence   [i] = cache_hit_latence  ;
      cache_shared_miss_penality [i] = cache_miss_penality;

      cache_nb_line       *= cache_ratio;
      cache_size_line     *= cache_ratio;
//    cache_size_word     *= cache_ratio;
      cache_associativity *= cache_ratio;
      cache_hit_latence   *= cache_ratio;
      cache_miss_penality *= cache_ratio;
    }
  
  // TTY
  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];
  for (uint32_t i=0; i<nb_component_tty; ++i)
    {
      tty_address [i] = TTY_BASE;
      nb_tty      [i] = nb_thread;
    }
  string  ** name_tty    = new string * [nb_component_tty];
  for (uint32_t i=0; i<nb_component_tty; ++i)
    {
      name_tty [i]    = new string [nb_tty[i]];
      for (uint32_t j=0; j<nb_tty[i]; ++j)
        name_tty [i][j] = "tty_"+toString(i)+"_"+toString(j);
    }

  // Ramlock
  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];
  for (uint32_t i=0; i<nb_component_ramlock; ++i)
    {
      ramlock_address [i] = RAMLOCK_BASE;
      nb_lock         [i] = 100*nb_thread;
    }

  // Sim2OS
  uint32_t sim2os_address = SIM2OS_BASE;
  uint32_t sim2os_size    = SIM2OS_SIZE;

  SOCLIB_SEGMENT_TABLE * segtable = new SOCLIB_SEGMENT_TABLE;
  segtable->setMSBNumber    (8);
  segtable->setDefaultTarget(0,0);

  // 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_stack"  ,DATA_STACK_BASE   ,DATA_STACK_SIZE   ,0           ,0          ,false);
  segtable->addSegment("data_unc"    ,DATA_UNCACHED_BASE,DATA_UNCACHED_SIZE,0           ,0          ,true );

  Parameters * param_environment = new Parameters
    (nb_thread,
     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,

     nb_cache_shared               ,
//   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,
     
     nb_component_ramlock,
     ramlock_address,
     nb_lock,
     
     sim2os_address,
     sim2os_size,
     segtable
     );
  
//   cout << param_environment->print(0) << endl;

  Environment * environment = new Environment ("environment",param_environment);
  
  const char * sections_text [] = {".text",NULL}; 
  const char * sections_data [] = {".data",".rodata",".bss",".sdata",".sbss", NULL}; 

  if (environment->init("text", filename_software.c_str(), sections_text) == false) exit (EXIT_FAILURE);
  if (environment->init("data", filename_software.c_str(), sections_data) == false) exit (EXIT_FAILURE);

  // segtable->print();

  //==============================================================================
  //===== [ SIGNAL ]==============================================================
  //==============================================================================
#ifdef SYSTEMCASS_SPECIFIC
  sc_clock              *  CLOCK  = new sc_clock ("CLOCK__________________", 1.0, 0.5);
#else
  sc_time period (TIME_PERIOD, TIME_UNIT);
  sc_clock              *  CLOCK  = new sc_clock ("CLOCK__________________", period);	 
#endif
  sc_signal<Tcontrol_t> *  NRESET = new sc_signal<Tcontrol_t> ("NRESET_________________");

  sc_signal<Tcontrol_t           >  ** ICACHE_REQ_VAL        ;
  sc_signal<Tcontrol_t           >  ** ICACHE_REQ_ACK        ;
  sc_signal<Ticache_context_t    >  ** ICACHE_REQ_THREAD_ID  ;
  sc_signal<Ticache_packet_t     >  ** ICACHE_REQ_PACKET_ID  ;
  sc_signal<Ticache_address_t    >  ** ICACHE_REQ_ADDRESS    ;
  sc_signal<Ticache_type_t       >  ** ICACHE_REQ_TYPE       ;

  sc_signal<Tcontrol_t           >  ** ICACHE_RSP_VAL        ;
  sc_signal<Tcontrol_t           >  ** ICACHE_RSP_ACK        ;
  sc_signal<Ticache_context_t    >  ** ICACHE_RSP_THREAD_ID  ;
  sc_signal<Ticache_packet_t     >  ** ICACHE_RSP_PACKET_ID  ;
  sc_signal<Ticache_instruction_t> *** ICACHE_RSP_INSTRUCTION;
  sc_signal<Ticache_error_t      >  ** ICACHE_RSP_ERROR      ;

  sc_signal<Tcontrol_t           >  ** DCACHE_REQ_VAL        ;
  sc_signal<Tcontrol_t           >  ** DCACHE_REQ_ACK        ;
  sc_signal<Tdcache_context_t    >  ** DCACHE_REQ_THREAD_ID  ;
  sc_signal<Tdcache_packet_t     >  ** DCACHE_REQ_PACKET_ID  ;
  sc_signal<Tdcache_address_t    >  ** DCACHE_REQ_ADDRESS    ;
  sc_signal<Tdcache_data_t       >  ** DCACHE_REQ_WDATA      ;
  sc_signal<Tdcache_type_t       >  ** DCACHE_REQ_TYPE       ;

  sc_signal<Tcontrol_t           >  ** DCACHE_RSP_VAL        ;
  sc_signal<Tcontrol_t           >  ** DCACHE_RSP_ACK        ;
  sc_signal<Tdcache_context_t    >  ** DCACHE_RSP_THREAD_ID  ;
  sc_signal<Tdcache_packet_t     >  ** DCACHE_RSP_PACKET_ID  ;
  sc_signal<Tdcache_data_t       >  ** DCACHE_RSP_RDATA      ;
  sc_signal<Tdcache_error_t      >  ** DCACHE_RSP_ERROR      ;

  sc_signal<Tcontrol_t           >  ** INTERRUPT_ENABLE      ;

  ALLOC1_SC_SIGNAL(ICACHE_REQ_VAL         ,"ICACHE_REQ_VAL_________",Tcontrol_t           ,morpheo->_nb_icache_port);
  ALLOC1_SC_SIGNAL(ICACHE_REQ_ACK         ,"ICACHE_REQ_ACK_________",Tcontrol_t           ,morpheo->_nb_icache_port);
  ALLOC1_SC_SIGNAL(ICACHE_REQ_THREAD_ID   ,"ICACHE_REQ_THREAD_ID___",Ticache_context_t    ,morpheo->_nb_icache_port);
  ALLOC1_SC_SIGNAL(ICACHE_REQ_PACKET_ID   ,"ICACHE_REQ_PACKET_ID___",Ticache_packet_t     ,morpheo->_nb_icache_port);
  ALLOC1_SC_SIGNAL(ICACHE_REQ_ADDRESS     ,"ICACHE_REQ_ADDRESS_____",Ticache_address_t    ,morpheo->_nb_icache_port);
  ALLOC1_SC_SIGNAL(ICACHE_REQ_TYPE        ,"ICACHE_REQ_TYPE________",Ticache_type_t       ,morpheo->_nb_icache_port);

  ALLOC1_SC_SIGNAL(ICACHE_RSP_VAL         ,"ICACHE_RSP_VAL_________",Tcontrol_t           ,morpheo->_nb_icache_port);
  ALLOC1_SC_SIGNAL(ICACHE_RSP_ACK         ,"ICACHE_RSP_ACK_________",Tcontrol_t           ,morpheo->_nb_icache_port);
  ALLOC1_SC_SIGNAL(ICACHE_RSP_THREAD_ID   ,"ICACHE_RSP_THREAD_ID___",Ticache_context_t    ,morpheo->_nb_icache_port);
  ALLOC1_SC_SIGNAL(ICACHE_RSP_PACKET_ID   ,"ICACHE_RSP_PACKET_ID___",Ticache_packet_t     ,morpheo->_nb_icache_port);
  ALLOC2_SC_SIGNAL(ICACHE_RSP_INSTRUCTION ,"ICACHE_RSP_INSTRUCTION_",Ticache_instruction_t,morpheo->_nb_icache_port,morpheo->_icache_nb_instruction[it1]);
  ALLOC1_SC_SIGNAL(ICACHE_RSP_ERROR       ,"ICACHE_RSP_ERROR_______",Ticache_error_t      ,morpheo->_nb_icache_port);

  ALLOC1_SC_SIGNAL(DCACHE_REQ_VAL         ,"DCACHE_REQ_VAL_________",Tcontrol_t           ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_REQ_ACK         ,"DCACHE_REQ_ACK_________",Tcontrol_t           ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_REQ_THREAD_ID   ,"DCACHE_REQ_THREAD_ID___",Tdcache_context_t    ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_REQ_PACKET_ID   ,"DCACHE_REQ_PACKET_ID___",Tdcache_packet_t     ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_REQ_ADDRESS     ,"DCACHE_REQ_ADDRESS_____",Tdcache_address_t    ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_REQ_WDATA       ,"DCACHE_REQ_WDATA_______",Tdcache_data_t       ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_REQ_TYPE        ,"DCACHE_REQ_TYPE________",Tdcache_type_t       ,morpheo->_nb_dcache_port);

  ALLOC1_SC_SIGNAL(DCACHE_RSP_VAL         ,"DCACHE_RSP_VAL_________",Tcontrol_t           ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_RSP_ACK         ,"DCACHE_RSP_ACK_________",Tcontrol_t           ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_RSP_THREAD_ID   ,"DCACHE_RSP_THREAD_ID___",Tdcache_context_t    ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_RSP_PACKET_ID   ,"DCACHE_RSP_PACKET_ID___",Tdcache_packet_t     ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_RSP_RDATA       ,"DCACHE_RSP_RDATA_______",Tdcache_data_t       ,morpheo->_nb_dcache_port);
  ALLOC1_SC_SIGNAL(DCACHE_RSP_ERROR       ,"DCACHE_RSP_ERROR_______",Tdcache_error_t      ,morpheo->_nb_dcache_port);

  ALLOC1_SC_SIGNAL(INTERRUPT_ENABLE       ,"INTERRUPT_ENABLE_______",Tcontrol_t           ,morpheo->_nb_thread);

  //==============================================================================
  //===== [ INSTANCE ]============================================================
  //==============================================================================

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //~~~~~ [ Morpheo  ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  (*(morpheo->in_CLOCK))        (*(CLOCK));
  (*(morpheo->in_NRESET))       (*(NRESET));

  _INSTANCE1_SC_SIGNAL(morpheo,out_ICACHE_REQ_VAL         ,ICACHE_REQ_VAL         ,morpheo->_nb_icache_port);
  _INSTANCE1_SC_SIGNAL(morpheo, in_ICACHE_REQ_ACK         ,ICACHE_REQ_ACK         ,morpheo->_nb_icache_port);
  if (morpheo->_have_port_icache_thread_id)
  _INSTANCE1_SC_SIGNAL(morpheo,out_ICACHE_REQ_THREAD_ID   ,ICACHE_REQ_THREAD_ID   ,morpheo->_nb_icache_port);
  if (morpheo->_have_port_icache_packet_id)
  _INSTANCE1_SC_SIGNAL(morpheo,out_ICACHE_REQ_PACKET_ID   ,ICACHE_REQ_PACKET_ID   ,morpheo->_nb_icache_port);
  _INSTANCE1_SC_SIGNAL(morpheo,out_ICACHE_REQ_ADDRESS     ,ICACHE_REQ_ADDRESS     ,morpheo->_nb_icache_port);
  _INSTANCE1_SC_SIGNAL(morpheo,out_ICACHE_REQ_TYPE        ,ICACHE_REQ_TYPE        ,morpheo->_nb_icache_port);
                                                                                                                      
  _INSTANCE1_SC_SIGNAL(morpheo, in_ICACHE_RSP_VAL         ,ICACHE_RSP_VAL         ,morpheo->_nb_icache_port);
  _INSTANCE1_SC_SIGNAL(morpheo,out_ICACHE_RSP_ACK         ,ICACHE_RSP_ACK         ,morpheo->_nb_icache_port);
  if (morpheo->_have_port_icache_thread_id)
  _INSTANCE1_SC_SIGNAL(morpheo, in_ICACHE_RSP_THREAD_ID   ,ICACHE_RSP_THREAD_ID   ,morpheo->_nb_icache_port);
  if (morpheo->_have_port_icache_packet_id)
  _INSTANCE1_SC_SIGNAL(morpheo, in_ICACHE_RSP_PACKET_ID   ,ICACHE_RSP_PACKET_ID   ,morpheo->_nb_icache_port);
  _INSTANCE2_SC_SIGNAL(morpheo, in_ICACHE_RSP_INSTRUCTION ,ICACHE_RSP_INSTRUCTION ,morpheo->_nb_icache_port,morpheo->_icache_nb_instruction[it1]);
  _INSTANCE1_SC_SIGNAL(morpheo, in_ICACHE_RSP_ERROR       ,ICACHE_RSP_ERROR       ,morpheo->_nb_icache_port);
                                                                                                                      
  _INSTANCE1_SC_SIGNAL(morpheo,out_DCACHE_REQ_VAL         ,DCACHE_REQ_VAL         ,morpheo->_nb_dcache_port);
  _INSTANCE1_SC_SIGNAL(morpheo, in_DCACHE_REQ_ACK         ,DCACHE_REQ_ACK         ,morpheo->_nb_dcache_port);
  if (morpheo->_have_port_dcache_thread_id)
  _INSTANCE1_SC_SIGNAL(morpheo,out_DCACHE_REQ_THREAD_ID   ,DCACHE_REQ_THREAD_ID   ,morpheo->_nb_dcache_port);
  if (morpheo->_have_port_dcache_packet_id)
  _INSTANCE1_SC_SIGNAL(morpheo,out_DCACHE_REQ_PACKET_ID   ,DCACHE_REQ_PACKET_ID   ,morpheo->_nb_dcache_port);
  _INSTANCE1_SC_SIGNAL(morpheo,out_DCACHE_REQ_ADDRESS     ,DCACHE_REQ_ADDRESS     ,morpheo->_nb_dcache_port);
  _INSTANCE1_SC_SIGNAL(morpheo,out_DCACHE_REQ_WDATA       ,DCACHE_REQ_WDATA       ,morpheo->_nb_dcache_port);
  _INSTANCE1_SC_SIGNAL(morpheo,out_DCACHE_REQ_TYPE        ,DCACHE_REQ_TYPE        ,morpheo->_nb_dcache_port);
                                                                                                                      
  _INSTANCE1_SC_SIGNAL(morpheo, in_DCACHE_RSP_VAL         ,DCACHE_RSP_VAL         ,morpheo->_nb_dcache_port);
  _INSTANCE1_SC_SIGNAL(morpheo,out_DCACHE_RSP_ACK         ,DCACHE_RSP_ACK         ,morpheo->_nb_dcache_port);
  if (morpheo->_have_port_dcache_thread_id)
  _INSTANCE1_SC_SIGNAL(morpheo, in_DCACHE_RSP_THREAD_ID   ,DCACHE_RSP_THREAD_ID   ,morpheo->_nb_dcache_port);
  if (morpheo->_have_port_dcache_packet_id)
  _INSTANCE1_SC_SIGNAL(morpheo, in_DCACHE_RSP_PACKET_ID   ,DCACHE_RSP_PACKET_ID   ,morpheo->_nb_dcache_port);
  _INSTANCE1_SC_SIGNAL(morpheo, in_DCACHE_RSP_RDATA       ,DCACHE_RSP_RDATA       ,morpheo->_nb_dcache_port);
  _INSTANCE1_SC_SIGNAL(morpheo, in_DCACHE_RSP_ERROR       ,DCACHE_RSP_ERROR       ,morpheo->_nb_dcache_port);
                                                                                                                      
  _INSTANCE1_SC_SIGNAL(morpheo, in_INTERRUPT_ENABLE       ,INTERRUPT_ENABLE       ,morpheo->_nb_thread);

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //~~~~~ [ Environment ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  (*(environment->CLOCK))        (*(CLOCK));
  (*(environment->NRESET))       (*(NRESET));

  for (uint32_t i=0; i<morpheo->_nb_icache_port; ++i)
    {
  (*(environment->ICACHE_REQ_VAL         [0][i]   )) (*(ICACHE_REQ_VAL         [i]   ));
  (*(environment->ICACHE_REQ_ACK         [0][i]   )) (*(ICACHE_REQ_ACK         [i]   ));
  (*(environment->ICACHE_REQ_CONTEXT_ID  [0][i]   )) (*(ICACHE_REQ_THREAD_ID   [i]   ));
  (*(environment->ICACHE_REQ_PACKET_ID   [0][i]   )) (*(ICACHE_REQ_PACKET_ID   [i]   ));
  (*(environment->ICACHE_REQ_ADDRESS     [0][i]   )) (*(ICACHE_REQ_ADDRESS     [i]   ));
  (*(environment->ICACHE_REQ_TYPE        [0][i]   )) (*(ICACHE_REQ_TYPE        [i]   ));
                                                                                     
  (*(environment->ICACHE_RSP_VAL         [0][i]   )) (*(ICACHE_RSP_VAL         [i]   ));
  (*(environment->ICACHE_RSP_ACK         [0][i]   )) (*(ICACHE_RSP_ACK         [i]   ));
  (*(environment->ICACHE_RSP_CONTEXT_ID  [0][i]   )) (*(ICACHE_RSP_THREAD_ID   [i]   ));
  (*(environment->ICACHE_RSP_PACKET_ID   [0][i]   )) (*(ICACHE_RSP_PACKET_ID   [i]   ));
  (*(environment->ICACHE_RSP_ERROR       [0][i]   )) (*(ICACHE_RSP_ERROR       [i]   ));

  for (uint32_t j=0; j<morpheo->_icache_nb_instruction[i]; ++j)
  (*(environment->ICACHE_RSP_INSTRUCTION [0][i][j])) (*(ICACHE_RSP_INSTRUCTION [i][j]));
    }
  for (uint32_t i=0; i<morpheo->_nb_dcache_port; ++i)
    {
  (*(environment->DCACHE_REQ_VAL         [0][i]   )) (*(DCACHE_REQ_VAL         [i]   ));
  (*(environment->DCACHE_REQ_ACK         [0][i]   )) (*(DCACHE_REQ_ACK         [i]   ));
  (*(environment->DCACHE_REQ_CONTEXT_ID  [0][i]   )) (*(DCACHE_REQ_THREAD_ID   [i]   ));
  (*(environment->DCACHE_REQ_PACKET_ID   [0][i]   )) (*(DCACHE_REQ_PACKET_ID   [i]   ));
  (*(environment->DCACHE_REQ_ADDRESS     [0][i]   )) (*(DCACHE_REQ_ADDRESS     [i]   ));
  (*(environment->DCACHE_REQ_WDATA       [0][i]   )) (*(DCACHE_REQ_WDATA       [i]   ));
  (*(environment->DCACHE_REQ_TYPE        [0][i]   )) (*(DCACHE_REQ_TYPE        [i]   ));
                                                                                     
  (*(environment->DCACHE_RSP_VAL         [0][i]   )) (*(DCACHE_RSP_VAL         [i]   ));
  (*(environment->DCACHE_RSP_ACK         [0][i]   )) (*(DCACHE_RSP_ACK         [i]   ));
  (*(environment->DCACHE_RSP_CONTEXT_ID  [0][i]   )) (*(DCACHE_RSP_THREAD_ID   [i]   ));
  (*(environment->DCACHE_RSP_PACKET_ID   [0][i]   )) (*(DCACHE_RSP_PACKET_ID   [i]   ));
  (*(environment->DCACHE_RSP_RDATA       [0][i]   )) (*(DCACHE_RSP_RDATA       [i]   ));
  (*(environment->DCACHE_RSP_ERROR       [0][i]   )) (*(DCACHE_RSP_ERROR       [i]   ));
    }

//_INSTANCE2_SC_SIGNAL(environment,INTERRUPT_ENABLE       ,1,morpheo->_nb_thread);

  //==============================================================================
  //===== [ SIMULATION ]==========================================================
  //==============================================================================

  // initialisation
 
  msgInformation("<test> Simulation Init\n");

  sc_time t (0, TIME_UNIT);
  sc_start(t);

  msgInformation("<test> Simulation Start\n");

  bool morpheo_error = false;
  try 
    {
      Time * _time_global = new Time();
      
      for (uint32_t i=0; i<morpheo->_nb_thread; ++i)
        INTERRUPT_ENABLE[i]->write(0);
      
      NRESET->write(0);
      SC_START(5);
      NRESET->write(1);  
      
      // Infinite loop
      do
        {
          //       Time * _time_local = new Time();
          SC_START(100000);
          //       delete _time_local;
        } while (not morpheo    ->simulation_end() and // morpheo condition stop
                 not environment->simulation_end());   // test ok
      delete _time_global;
    }
  catch (morpheo::ErrorMorpheo & error)
    {
      std::cerr << error.what() << std::endl;

      msgError("%s\n",STR_KO);

      morpheo_error = true;
    }

  bool morpheo_end     = morpheo->simulation_end();
  bool environment_end = environment->simulation_end();


  //==============================================================================
  //===== [ DESTRUCTION ]=========================================================
  //==============================================================================

  delete CLOCK;
  delete NRESET;

  DELETE1_SC_SIGNAL(ICACHE_REQ_VAL         ,morpheo->_nb_icache_port);
  DELETE1_SC_SIGNAL(ICACHE_REQ_ACK         ,morpheo->_nb_icache_port);
  DELETE1_SC_SIGNAL(ICACHE_REQ_THREAD_ID   ,morpheo->_nb_icache_port);
  DELETE1_SC_SIGNAL(ICACHE_REQ_PACKET_ID   ,morpheo->_nb_icache_port);
  DELETE1_SC_SIGNAL(ICACHE_REQ_ADDRESS     ,morpheo->_nb_icache_port);
  DELETE1_SC_SIGNAL(ICACHE_REQ_TYPE        ,morpheo->_nb_icache_port);
  
  DELETE1_SC_SIGNAL(ICACHE_RSP_VAL         ,morpheo->_nb_icache_port);
  DELETE1_SC_SIGNAL(ICACHE_RSP_ACK         ,morpheo->_nb_icache_port);
  DELETE1_SC_SIGNAL(ICACHE_RSP_THREAD_ID   ,morpheo->_nb_icache_port);
  DELETE1_SC_SIGNAL(ICACHE_RSP_PACKET_ID   ,morpheo->_nb_icache_port);
  DELETE1_SC_SIGNAL(ICACHE_RSP_ERROR       ,morpheo->_nb_icache_port);
  DELETE2_SC_SIGNAL(ICACHE_RSP_INSTRUCTION ,morpheo->_nb_icache_port,morpheo->_icache_nb_instruction[it1]);
  
  DELETE1_SC_SIGNAL(DCACHE_REQ_VAL         ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_REQ_ACK         ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_REQ_THREAD_ID   ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_REQ_PACKET_ID   ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_REQ_ADDRESS     ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_REQ_WDATA       ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_REQ_TYPE        ,morpheo->_nb_dcache_port);
  
  DELETE1_SC_SIGNAL(DCACHE_RSP_VAL         ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_RSP_ACK         ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_RSP_THREAD_ID   ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_RSP_PACKET_ID   ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_RSP_RDATA       ,morpheo->_nb_dcache_port);
  DELETE1_SC_SIGNAL(DCACHE_RSP_ERROR       ,morpheo->_nb_dcache_port);
  
  DELETE1_SC_SIGNAL(INTERRUPT_ENABLE       ,morpheo->_nb_thread);

  delete    environment;

  delete    param_environment;
  delete    segtable;

  delete [] nb_lock        ;
  delete [] ramlock_address;

  for (uint32_t i=0;i<nb_component_tty;++i)
    delete [] name_tty [i];
  delete [] name_tty;
  delete [] nb_tty;
  delete [] tty_address;

  delete [] cache_shared_miss_penality;
  delete [] cache_shared_hit_latence  ;
  delete [] cache_shared_associativity;
  delete [] cache_shared_size_word    ;
  delete [] cache_shared_size_line    ;
  delete [] cache_shared_nb_line      ;

  for (uint32_t i=0; i<nb_entity; i++)
    {
      delete [] dcache_miss_penality [i];
      delete [] dcache_hit_latence   [i];
      delete [] dcache_associativity [i];
      delete [] dcache_size_word     [i];
      delete [] dcache_size_line     [i];
      delete [] dcache_nb_line       [i];
    }
  delete [] dcache_miss_penality  ;
  delete [] dcache_hit_latence    ;
  delete [] dcache_associativity  ;
  delete [] dcache_size_word      ;
  delete [] dcache_size_line      ;
  delete [] dcache_nb_line        ;
  delete [] dcache_nb_level       ;
  delete [] dcache_nb_port        ;

  for (uint32_t i=0; i<nb_entity; i++)
    {
      delete [] icache_miss_penality [i];
      delete [] icache_hit_latence   [i];
      delete [] icache_associativity [i];
      delete [] icache_size_word     [i];
      delete [] icache_size_line     [i];
      delete [] icache_nb_line       [i];
    }
  delete [] icache_miss_penality;
  delete [] icache_hit_latence  ;
  delete [] icache_associativity;
  delete [] icache_size_word    ;
  delete [] icache_size_line    ;
  delete [] icache_nb_line      ;
  delete [] icache_nb_level     ;
  delete [] icache_nb_port      ;

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

  delete    morpheo;

  bool test_ok = false;
  if (not morpheo_error)
    {
      if (not morpheo_end and not environment_end)
        {
          msgError("<test> Simulation End : Unknow\n");
        }
      else
        {
          if (morpheo_end)
            {
              msgInformation("<test> Simulation End : MORPHEO\n");
              test_ok = true;
            }
          if (environment_end)
            {
              msgInformation("<test> Simulation End : ENVIRONMENT\n");
              test_ok = true;
            }
        }
    }

  if (test_ok)
    {
      msgInformation("%s\n",STR_OK);
      return EXIT_SUCCESS;
    }
  else
    {
      msgInformation("%s\n",STR_KO);
      return EXIT_FAILURE;
    }
}
