#ifndef morpheo_behavioural_Allocation_h
#define morpheo_behavioural_Allocation_h

/*
 * $Id: Allocation.h 122 2009-06-03 08:15:51Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Common/include/Debug.h"

// ======================================================================
// =====[ ALLOCATION / DELETE of ARRAY ]=================================
// ======================================================================
#define ALLOC0(var,type)                        \
  var = new type

#define ALLOC1(var,type,s1)                      \
  var = new type [s1]
  
#define ALLOC2(var,type,s1,s2)                   \
  var = new type * [s1];                         \
  for (uint32_t it1=0; it1<s1; ++it1)            \
    {                                            \
      var [it1] = new type [s2];                 \
    }

#define ALLOC3(var,type,s1,s2,s3)                \
  var = new type ** [s1];                        \
  for (uint32_t it1=0; it1<s1; ++it1)            \
    {                                            \
      var [it1] = new type * [s2];               \
      for (uint32_t it2=0; it2<s2; ++it2)        \
        {                                        \
          var [it1][it2] = new type [s3];        \
        }                                        \
    }
  
#define ALLOC4(var,type,s1,s2,s3,s4)                    \
  var = new type *** [s1];                              \
  for (uint32_t it1=0; it1<s1; ++it1)                   \
    {                                                   \
      var [it1] = new type ** [s2];                     \
      for (uint32_t it2=0; it2<s2; ++it2)               \
        {                                               \
          var [it1][it2] = new type * [s3];             \
          for (uint32_t it3=0; it3<s3; ++it3)           \
            {                                           \
              var [it1][it2][it3] = new type [s4];      \
            }                                           \
        }                                               \
    }

#define DELETE0(var)                            \
  delete var;
  
#define DELETE1(var,s1)                          \
  delete [] var;

#define DELETE2(var,s1,s2)                       \
  for (uint32_t it1=0; it1<s1; ++it1)            \
    {                                            \
      delete [] var [it1];                       \
    }                                            \
  delete [] var;                         
  
#define DELETE3(var,s1,s2,s3)                    \
  for (uint32_t it1=0; it1<s1; ++it1)            \
    {                                            \
      for (uint32_t it2=0; it2<s2; ++it2)        \
        {                                        \
          delete [] var [it1][it2];              \
        }                                        \
      delete [] var [it1];                       \
    }                                            \
  delete [] var;
  
#define DELETE4(var,s1,s2,s3,s4)                 \
  for (uint32_t it1=0; it1<s1; ++it1)            \
    {                                            \
      for (uint32_t it2=0; it2<s2; ++it2)        \
        {                                        \
          for (uint32_t it3=0; it3<s3; ++it3)    \
            {                                    \
              delete [] var [it1][it2][it3];     \
            }                                    \
          delete [] var [it1][it2];              \
        }                                        \
      delete [] var [it1];                       \
    }                                            \
  delete [] var;                                        

// ======================================================================
// =====[ ALLOCATION / DELETE of SIGNAL]=================================
// ======================================================================

// Help to allocate interface
#define INTERFACE_PRINT(name) log_printf(TRACE,Allocation,FUNCTION,"<%s> : Interface's creation : %s (%s, %d)",_name.c_str(),name,__FILE__,__LINE__);
#define PRINT_SIGNAL_ADDRESS(name,address) log_printf(TRACE,Allocation,FUNCTION,"Signal : %s 0x%.8x(%s, %d)",name,(uint32_t)((uint64_t)(address)),__FILE__,__LINE__);
#define PRINT_SIZE_NUL(component,interface,signal) log_printf(TRACE,Allocation,FUNCTION,_("<%s> %s.%s.%s : size is nul."),_name.c_str(),component->get_name().c_str(),interface->get_name().c_str(),signal);
#define TEST_SIGNAL(name,address) PRINT_SIGNAL_ADDRESS(name,address); TEST_PTR(address)
#define INSTANCE_FOREIGN_PRINT(name) log_printf(TRACE,Allocation,FUNCTION,"<%s> : %s (%s, %d)",_name.c_str(),name,__FILE__,__LINE__);

// ----------------------------------------------------------------------
// -----[ NO ITERATION ]-------------------------------------------------
// ----------------------------------------------------------------------

#define __ALLOC0_SIGNAL(sig, name, type)        \
  {                                             \
    sig = new type (name);                      \
  }

#ifdef POSITION
#define ALLOC0_INTERFACE_BEGIN( name, direction, localisation, str)     \
  INTERFACE_PRINT(name);                                                \
  morpheo::behavioural::Interface_fifo * interface = _interfaces->set_interface( name, direction, localisation, str);
#else
#define ALLOC0_INTERFACE_BEGIN( name, direction, localisation, str)     \
  INTERFACE_PRINT(name);                                                \
  morpheo::behavioural::Interface_fifo * interface = _interfaces->set_interface( name);
#endif

#define ALLOC0_INTERFACE_END()

#define ALLOC0_VAL_ACK_IN(  sig, name, type)                            \
  {                                                                     \
    sig = interface->set_signal_valack_in (name, type);                 \
  }                                                                     
#define ALLOC0_VAL_ACK_OUT( sig, name, type)                            \
  {                                                                     \
    sig = interface->set_signal_valack_out(name, type);                 \
  }                                                                     
#define ALLOC0_VALACK_IN(     sig, type)                                \
  {                                                                     \
    sig = interface->set_signal_valack_in (type);                       \
  }                                                                     
#define ALLOC0_VALACK_OUT(    sig, type)                                 \
  {                                                                     \
    sig = interface->set_signal_valack_out(type);                       \
  }                                                                     
#define ALLOC0_SIGNAL_IN(  sig, name, type, size)                        \
  if (size > 0)                                                         \
    {                                                                   \
      sig = interface->set_signal_in <type> (name, size);               \
    }                                                                   \
  else                                                                  \
    {                                                                   \
      PRINT_SIZE_NUL(_component,interface,name);                        \
    }
  
#define ALLOC0_SIGNAL_OUT( sig, name, type, size)                        \
  if (size > 0)                                                         \
    {                                                                   \
      sig = interface->set_signal_out<type> (name, size);               \
    }                                                                   \
  else                                                                  \
    {                                                                   \
      PRINT_SIZE_NUL(_component,interface,name); \
    }

#define DELETE0_SIGNAL( sig, size)                                      \
  if (size > 0)                                                         \
    {                                                                   \
      delete sig;                                                       \
    }

#define ALLOC0_FOREIGN_SIGNAL_IN(  sig, interface, name, type, size)    \
  if (size > 0)                                                         \
    {                                                                   \
      std::string str = (toString("in")+"_"+((interface!="")?(toString(interface)+"_"):toString(""))+toString(name)); \
      sig = new SC_IN    (type) (str.c_str());                          \
    }

#define ALLOC0_FOREIGN_SIGNAL_OUT( sig, interface, name, type, size)    \
  if (size > 0)                                                         \
    {                                                                   \
      std::string str = (toString("out")+"_"+((interface!="")?(toString(interface)+"_"):toString(""))+toString(name)); \
      sig = new SC_OUT   (type) (str.c_str());                          \
    }

#define DELETE0_FOREIGN_SIGNAL( sig, size) \
  {                                        \
    DELETE0_SIGNAL(sig,size);              \
  }

#define INSTANCE0_FOREIGN_SIGNAL(component, sig, type, name, size)      \
  if (size > 0)                                                         \
    {                                                                   \
      INSTANCE_FOREIGN_PRINT(name);                                     \
      _component->set_sc_signal<type>(_name,name,static_cast<void*>(component->sig)); \
    }

#define ALLOC0_SC_SIGNAL(  sig, name, type)                             \
  sig = new sc_signal<type> (name);                                     \
  PRINT_SIGNAL_ADDRESS(name,sig);

#define INSTANCE0_SC_SIGNAL(component, sig)                    \
  {                                                            \
    TEST_SIGNAL(component->sig->name(),component->sig);        \
    TEST_SIGNAL(sig           ->name(),sig);                   \
    (*(component->sig)) (*(sig));                              \
  }

#define _INSTANCE0_SC_SIGNAL(component, sig1,sig2)                      \
  {                                                                     \
    TEST_SIGNAL(component->sig1->name(),component->sig1);               \
    TEST_SIGNAL(sig2           ->name(),sig2);                          \
    (*(component->sig1)) (*(sig2));                                     \
  }

#define DELETE0_SC_SIGNAL( sig)                  \
  {                                              \
    PRINT_SIGNAL_ADDRESS("",sig);                \
    delete sig;                                  \
  }

// ----------------------------------------------------------------------
// -----[ ITERATION 1 ]--------------------------------------------------
// ----------------------------------------------------------------------

#define __ALLOC1_INTERFACE_BEGIN(name, x1)                                    \
  INTERFACE_PRINT(name);                                                \
  const std::string interface_name = name;                              \
  const uint32_t iterator_1 = x1;

#define __ALLOC1_INTERFACE_END(x1)

#define __ALLOC1_SIGNAL_IN( sig, name, type)                            \
  {                                                                     \
    sig = new SC_IN(type) * [iterator_1];                               \
    std::string separator="_";                                          \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        std::string str = "in_"+interface_name+separator+toString(it1)+separator+name; \
        sig [it1] = new SC_IN(type) (str.c_str());                      \
      }                                                                 \
  }

#define __ALLOC1_SIGNAL_OUT( sig, name, type)                           \
  {                                                                     \
    sig = new SC_OUT(type) * [iterator_1];                              \
    std::string separator="_";                                          \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        std::string str = "out_"+interface_name+separator+toString(it1)+separator+name; \
        sig [it1] = new SC_OUT(type) (str.c_str());                     \
      }                                                                 \
  }

#ifdef POSITION
#define ALLOC1_INTERFACE_BEGIN( name, direction, localisation, str, x1) \
  INTERFACE_PRINT(name);                                                \
  uint32_t iterator_1 = 0;                                              \
  morpheo::behavioural::Interface_fifo ** interface;                    \
  {                                                                     \
    std::string separator="_";                                          \
    iterator_1 = x1;                                                    \
    interface = new morpheo::behavioural::Interface_fifo * [iterator_1]; \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        interface [it1] = _interfaces->set_interface( name+separator+toString(it1), direction, localisation, str); \
      }                                                                 \
  }
#else
#define ALLOC1_INTERFACE_BEGIN( name, direction, localisation, str, x1)   \
  INTERFACE_PRINT(name);                                                \
  uint32_t iterator_1 = 0;                                              \
  morpheo::behavioural::Interface_fifo ** interface;                    \
  {                                                                     \
    std::string separator="_";                                          \
    iterator_1 = x1;                                                    \
    interface = new morpheo::behavioural::Interface_fifo * [iterator_1]; \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        interface [it1] = _interfaces->set_interface( name+separator+toString(it1)); \
      }                                                                 \
  }
#endif

#define ALLOC1_INTERFACE_END(x1)                \
  delete [] interface;

#define ALLOC1_VAL_ACK_IN( sig, name, type)                             \
  {                                                                     \
    sig = new SC_IN (Tcontrol_t) * [iterator_1];                        \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        sig [it1] = interface[it1]->set_signal_valack_in (name, type);  \
      }                                                                 \
  }
#define ALLOC1_VAL_ACK_OUT(sig, name, type)                             \
  {                                                                     \
    sig = new SC_OUT(Tcontrol_t) * [iterator_1];                        \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        sig [it1] = interface[it1]->set_signal_valack_out(name, type);  \
      }                                                                 \
  }
#define ALLOC1_VALACK_IN(    sig, type)                                 \
  {                                                                     \
    sig = new SC_IN (Tcontrol_t) * [iterator_1];                        \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        sig [it1] = interface[it1]->set_signal_valack_in (type);        \
      }                                                                 \
  }
#define ALLOC1_VALACK_OUT(   sig, type)                                 \
  {                                                                     \
    sig = new SC_OUT(Tcontrol_t) * [iterator_1];                        \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        sig [it1] = interface[it1]->set_signal_valack_out(type);        \
      }                                                                 \
  }
#define ALLOC1_SIGNAL_IN( sig, name, type, size)                        \
  {                                                                     \
    sig = new SC_IN (type) * [iterator_1];                              \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        if (size > 0)                                                   \
          {                                                             \
            sig [it1] = interface[it1]->set_signal_in <type> (name, size); \
          }                                                             \
        else                                                            \
          {                                                             \
            PRINT_SIZE_NUL(_component,interface[it1],name);             \
          }                                                             \
      }                                                                 \
  }

#define ALLOC1_SIGNAL_OUT(sig, name, type, size)                        \
  {                                                                     \
    sig = new SC_OUT(type) * [iterator_1];                              \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        if (size > 0)                                                   \
          {                                                             \
            sig [it1] = interface[it1]->set_signal_out<type> (name, size); \
          }                                                             \
        else                                                            \
          {                                                             \
            PRINT_SIZE_NUL(_component,interface[it1],name);             \
          }                                                             \
      }                                                                 \
  }

#define DELETE1_SIGNAL(sig, x1, size)                                   \
  {                                                                     \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        if (size > 0)                                                   \
          {                                                             \
            delete sig[it1];                                            \
          }                                                             \
      }                                                                 \
    delete [] sig;                                                      \
  }

#define ALLOC1_FOREIGN_SIGNAL_IN(sig, interface, name, type, size,x1)   \
  {                                                                     \
    sig = new SC_IN (type) * [x1];                                   \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      if (size > 0)                                                     \
        {                                                               \
          std::string str = (toString("in")+"_"+((interface!="")?(toString(interface)+"_"):toString(""))+toString(it1)+"_"+toString(name)); \
          sig [it1] = new SC_IN (type) (str.c_str());                   \
        }                                                               \
  }

#define ALLOC1_FOREIGN_SIGNAL_OUT(sig, interface, name, type, size,x1)  \
  {                                                                     \
    sig = new SC_OUT (type) * [x1];                                     \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      if (size > 0)                                                     \
        {                                                               \
          std::string str = (toString("out")+"_"+((interface!="")?(toString(interface)+"_"):toString(""))+toString(it1)+"_"+toString(name)); \
          sig [it1] = new SC_OUT (type) (str.c_str());                  \
        }                                                               \
  }

#define DELETE1_FOREIGN_SIGNAL( sig, size,x1)            \
  {                                                      \
    DELETE1_SIGNAL(sig,x1,size);                         \
  }

#define ALLOC1_SC_SIGNAL( sig, name, type, x1)                          \
  sig = new sc_signal<type> * [x1];                                     \
  {                                                                     \
    std::string separator="_";                                          \
    std::string str;                                                    \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        str = name+separator+toString(it1);                             \
        sig [it1] = new sc_signal<type> (str.c_str());                  \
        PRINT_SIGNAL_ADDRESS(str.c_str(),sig[it1]);                     \
      }                                                                 \
  }

#define INSTANCE1_SC_SIGNAL(component, sig, x1) \
  for (uint32_t it1=0; it1<x1; it1++)                                   \
    {                                                                   \
      TEST_SIGNAL(component->sig [it1]->name(),component->sig [it1]);   \
      TEST_SIGNAL(sig            [it1]->name(),sig            [it1]);   \
      (*(component->sig[it1])) (*(sig[it1]));                           \
    }

#define _INSTANCE1_SC_SIGNAL(component, sig1, sig2, x1) \
  for (uint32_t it1=0; it1<x1; it1++)                                   \
    {                                                                   \
      TEST_SIGNAL(component->sig1 [it1]->name(),component->sig1 [it1]); \
      TEST_SIGNAL(sig2            [it1]->name(),sig2            [it1]); \
      (*(component->sig1[it1])) (*(sig2[it1]));                         \
    }

#define DELETE1_SC_SIGNAL(sig, x1)                                      \
  {                                                                     \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        PRINT_SIGNAL_ADDRESS("",sig[it1]);                         \
        delete sig[it1];                                                \
      }                                                                 \
    delete [] sig;                                                      \
  }

// ----------------------------------------------------------------------
// -----[ ITERATION 2 ]--------------------------------------------------
// ----------------------------------------------------------------------

#ifdef POSITION
#define ALLOC2_INTERFACE_BEGIN( name, direction, localisation, str, x1, x2)   \
  INTERFACE_PRINT(name);                                                \
  uint32_t iterator_1 = 0;                                              \
  uint32_t iterator_2 = 0;                                              \
  morpheo::behavioural::Interface_fifo *** interface;                   \
  {                                                                     \
    std::string separator="_";                                          \
    iterator_1 = x1;                                                    \
    interface = new morpheo::behavioural::Interface_fifo ** [iterator_1]; \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        iterator_2 = x2;                                                \
        interface [it1] = new morpheo::behavioural::Interface_fifo * [iterator_2]; \
        for (uint32_t it2=0; it2<iterator_2; it2++)                     \
          {                                                             \
            interface [it1][it2] = _interfaces->set_interface( name+separator+toString(it1)+separator+toString(it2), direction, localisation, str); \
          }                                                             \
      }                                                                 \
  }
#else
#define ALLOC2_INTERFACE_BEGIN( name, direction, localisation, str, x1, x2)   \
  INTERFACE_PRINT(name);                                                \
  uint32_t iterator_1 = 0;                                              \
  uint32_t iterator_2 = 0;                                              \
  morpheo::behavioural::Interface_fifo *** interface;                   \
  {                                                                     \
    std::string separator="_";                                          \
    iterator_1 = x1;                                                    \
    interface = new morpheo::behavioural::Interface_fifo ** [iterator_1]; \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        iterator_2 = x2;                                                \
        interface [it1] = new morpheo::behavioural::Interface_fifo * [iterator_2]; \
        for (uint32_t it2=0; it2<iterator_2; it2++)                     \
          {                                                             \
            interface [it1][it2] = _interfaces->set_interface( name+separator+toString(it1)+separator+toString(it2)); \
          }                                                             \
      }                                                                 \
  }
#endif

#define ALLOC2_INTERFACE_END(x1, x2)                                    \
  for (uint32_t it1=0; it1<x1; it1++)                                   \
    delete [] interface [it1];                                          \
  delete [] interface;

#define _ALLOC2_VAL_ACK_IN( sig, name, type, x1, x2)                    \
  {                                                                     \
    sig = new SC_IN (Tcontrol_t) ** [x1];                               \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_IN (Tcontrol_t) * [x2];                      \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = interface[it1][it2]->set_signal_valack_in (name, type); \
          }                                                             \
      }                                                                 \
  }

#define _ALLOC2_VAL_ACK_OUT( sig, name, type, x1, x2)                   \
  {                                                                     \
    sig = new SC_OUT (Tcontrol_t) ** [x1];                              \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_OUT (Tcontrol_t) * [x2];                     \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = interface[it1][it2]->set_signal_valack_out (name, type); \
          }                                                             \
      }                                                                 \
  }

#define _ALLOC2_VALACK_IN(    sig,type, x1, x2)                         \
  {                                                                     \
    sig = new SC_IN (Tcontrol_t) ** [x1];                               \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_IN (Tcontrol_t) * [x2];                      \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = interface[it1][it2]->set_signal_valack_in (type); \
          }                                                             \
      }                                                                 \
  }

#define _ALLOC2_VALACK_OUT(    sig,type, x1, x2)                        \
  {                                                                     \
    sig = new SC_OUT (Tcontrol_t) ** [x1];                              \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_OUT (Tcontrol_t) * [x2];                     \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = interface[it1][it2]->set_signal_valack_out (type); \
          }                                                             \
      }                                                                 \
  }

#define _ALLOC2_SIGNAL_IN( sig, name, type, size, x1, x2)               \
  {                                                                     \
    sig = new SC_IN (type) ** [x1];                                     \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_IN (type) * [x2];                            \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            if (size > 0)                                               \
              {                                                         \
                sig [it1][it2] = interface[it1][it2]->set_signal_in <type> (name, size); \
              }                                                         \
            else                                                        \
              {                                                         \
                PRINT_SIZE_NUL(_component,interface[it1][it2],name);    \
              }                                                         \
          }                                                             \
      }                                                                 \
  }

#define _ALLOC2_SIGNAL_OUT( sig, name, type, size, x1, x2)              \
  {                                                                     \
    sig = new SC_OUT (type) ** [x1];                                    \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_OUT (type) * [x2];                           \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            if (size > 0)                                               \
              {                                                         \
                sig [it1][it2] = interface[it1][it2]->set_signal_out <type> (name, size); \
              }                                                         \
            else                                                        \
              {                                                         \
                PRINT_SIZE_NUL(_component,interface[it1][it2],name);    \
              }                                                         \
          }                                                             \
      }                                                                 \
  }

#define ALLOC2_VAL_ACK_IN( sig, name, type      ) _ALLOC2_VAL_ACK_IN( sig, name, type      , iterator_1, iterator_2) 
#define ALLOC2_VAL_ACK_OUT(sig, name, type      ) _ALLOC2_VAL_ACK_OUT(sig, name, type      , iterator_1, iterator_2) 
#define ALLOC2_VALACK_IN(  sig,       type      ) _ALLOC2_VALACK_IN(  sig,       type      , iterator_1, iterator_2) 
#define ALLOC2_VALACK_OUT( sig,       type      ) _ALLOC2_VALACK_OUT( sig,       type      , iterator_1, iterator_2) 
#define ALLOC2_SIGNAL_IN(  sig, name, type, size) _ALLOC2_SIGNAL_IN(  sig, name, type, size, iterator_1, iterator_2) 
#define ALLOC2_SIGNAL_OUT( sig, name, type, size) _ALLOC2_SIGNAL_OUT( sig, name, type, size, iterator_1, iterator_2) 

#define DELETE2_SIGNAL(sig, x1,x2, size)                                \
  {                                                                     \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            if (size > 0)                                               \
              {                                                         \
                delete sig[it1][it2];                                   \
              }                                                         \
          }                                                             \
        delete [] sig[it1];                                             \
      }                                                                 \
    delete [] sig;                                                      \
  }


#define ALLOC2_FOREIGN_SIGNAL_IN( sig, interface, name, type, size, x1, x2) \
  {                                                                     \
    sig = new SC_IN (type) ** [x1];                                     \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_IN (type) * [x2];                            \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          if (size > 0)                                                 \
            {                                                           \
              std::string str = (toString("in")+"_"+((interface!="")?(toString(interface)+"_"):toString(""))+toString(it1)+"_"+toString(it2)+"_"+toString(name)); \
              sig [it1][it2] = new SC_IN    (type) (str.c_str()); \
            }                                                           \
      }                                                                 \
  }

#define ALLOC2_FOREIGN_SIGNAL_OUT( sig, interface, name, type, size, x1, x2) \
  {                                                                     \
    sig = new SC_OUT (type) ** [x1];                                    \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_OUT (type) * [x2];                           \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          if (size > 0)                                                 \
            {                                                           \
              std::string str = (toString("out")+"_"+((interface!="")?(toString(interface)+"_"):toString(""))+toString(it1)+"_"+toString(it2)+"_"+toString(name)); \
              sig [it1][it2] = new SC_IN    (type) (str.c_str());       \
            }                                                           \
      }                                                                 \
  }

#define DELETE2_FOREIGN_SIGNAL( sig, size,x1,x2)            \
  {                                                         \
    DELETE2_SIGNAL(sig,x1,x2,size);                         \
  }

#define ALLOC2_SC_SIGNAL( sig, name, type, x1, x2)                      \
  sig = new sc_signal<type> ** [x1];                                    \
  {                                                                     \
    std::string separator="_";                                          \
    std::string str;                                                    \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new sc_signal<type> * [x2];                         \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            str = name+separator+toString(it1)+separator+toString(it2); \
            sig [it1][it2] = new sc_signal<type> (str.c_str());         \
            PRINT_SIGNAL_ADDRESS(str.c_str(),sig[it1][it2]);            \
          }                                                             \
      }                                                                 \
  }

#define INSTANCE2_SC_SIGNAL(component, sig, x1, x2)                     \
  for (uint32_t it1=0; it1<x1; it1++)                                   \
    for (uint32_t it2=0; it2<x2; it2++)                                 \
      {                                                                 \
        TEST_SIGNAL(component->sig  [it1][it2]->name(),component->sig  [it1][it2]); \
        TEST_SIGNAL(sig             [it1][it2]->name(),sig             [it1][it2]); \
        (*(component->sig[it1][it2])) (*(sig[it1][it2]));               \
      }

#define _INSTANCE2_SC_SIGNAL(component, sig1, sig2, x1, x2)             \
  for (uint32_t it1=0; it1<x1; it1++)                                   \
    for (uint32_t it2=0; it2<x2; it2++)                                 \
      {                                                                 \
        TEST_SIGNAL(component->sig1 [it1][it2]->name(),component->sig1 [it1][it2]); \
        TEST_SIGNAL(sig2            [it1][it2]->name(),sig2            [it1][it2]); \
        (*(component->sig1[it1][it2])) (*(sig2[it1][it2]));             \
      }

#define DELETE2_SC_SIGNAL(sig,x1,x2)                                    \
  {                                                                     \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            PRINT_SIGNAL_ADDRESS("",sig[it1][it2]);                     \
            delete sig[it1][it2];                                       \
          }                                                             \
        delete [] sig[it1];                                             \
      }                                                                 \
    delete [] sig;                                                      \
  }

// ----------------------------------------------------------------------
// -----[ ITERATION 3 ]--------------------------------------------------
// ----------------------------------------------------------------------

#ifdef POSITION
#define ALLOC3_INTERFACE_BEGIN( name, direction, localisation, str, x1, x2, x3) \
  INTERFACE_PRINT(name);                                                \
  uint32_t iterator_1 = 0;                                              \
  uint32_t iterator_2 = 0;                                              \
  uint32_t iterator_3 = 0;                                              \
  morpheo::behavioural::Interface_fifo **** interface;                  \
  {                                                                     \
    std::string separator="_";                                          \
    iterator_1 = x1;                                                    \
    interface = new morpheo::behavioural::Interface_fifo *** [iterator_1]; \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        iterator_2 = x2;                                                \
        interface [it1] = new morpheo::behavioural::Interface_fifo ** [iterator_2]; \
        for (uint32_t it2=0; it2<iterator_2; it2++)                     \
          {                                                             \
            iterator_3 = x3;                                            \
            interface [it1][it2] = new morpheo::behavioural::Interface_fifo * [iterator_3]; \
            for (uint32_t it3=0; it3<iterator_3; it3++)                 \
              {                                                         \
                interface [it1][it2][it3] = _interfaces->set_interface( name+separator+toString(it1)+separator+toString(it2)+separator+toString(it3), direction, localisation, str); \
              }                                                         \
          }                                                             \
      }                                                                 \
  }
#else
#define ALLOC3_INTERFACE_BEGIN( name, direction, localisation, str, x1, x2, x3) \
  INTERFACE_PRINT(name);                                                \
  uint32_t iterator_1 = 0;                                              \
  uint32_t iterator_2 = 0;                                              \
  uint32_t iterator_3 = 0;                                              \
  morpheo::behavioural::Interface_fifo **** interface;                  \
  {                                                                     \
    std::string separator="_";                                          \
    iterator_1 = x1;                                                    \
    interface = new morpheo::behavioural::Interface_fifo *** [iterator_1]; \
    for (uint32_t it1=0; it1<iterator_1; it1++)                         \
      {                                                                 \
        iterator_2 = x2;                                                \
        interface [it1] = new morpheo::behavioural::Interface_fifo ** [iterator_2]; \
        for (uint32_t it2=0; it2<iterator_2; it2++)                     \
          {                                                             \
            iterator_3 = x3;                                            \
            interface [it1][it2] = new morpheo::behavioural::Interface_fifo * [iterator_3]; \
            for (uint32_t it3=0; it3<iterator_3; it3++)                 \
              {                                                         \
                interface [it1][it2][it3] = _interfaces->set_interface( name+separator+toString(it1)+separator+toString(it2)+separator+toString(it3)); \
              }                                                         \
          }                                                             \
      }                                                                 \
  }
#endif

#define ALLOC3_INTERFACE_END(x1, x2, x3)                         \
  for (uint32_t it1=0; it1<x1; it1++)                                   \
    {                                                                   \
      for (uint32_t it2=0; it2<x2; it2++)                               \
        delete [] interface [it1][it2];                                 \
      delete [] interface [it1];                                        \
    }                                                                   \
  delete [] interface;

// #define _ALLOC3_VAL_ACK_IN( sig, name, type, x1, x2, x3)
// #define _ALLOC3_VAL_ACK_OUT( sig, name, type, x1, x2, x3)

#define _ALLOC3_VALACK_IN(    sig,type, x1, x2, x3)                     \
  {                                                                     \
    sig = new SC_IN (Tcontrol_t) *** [x1];                              \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_IN (Tcontrol_t) ** [x2];                     \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = new SC_IN (Tcontrol_t) * [x3];             \
            for (uint32_t it3=0; it3<x3; it3++)                         \
              {                                                         \
                sig [it1][it2][it3] = interface[it1][it2][it3]->set_signal_valack_in (type); \
              }                                                         \
          }                                                             \
      }                                                                 \
  }

#define _ALLOC3_VALACK_OUT(    sig,type, x1, x2, x3)                    \
  {                                                                     \
    sig = new SC_OUT (Tcontrol_t) *** [x1];                             \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_OUT (Tcontrol_t) ** [x2];                    \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = new SC_OUT (Tcontrol_t) * [x3];            \
            for (uint32_t it3=0; it3<x3; it3++)                         \
              {                                                         \
                sig [it1][it2][it3] = interface[it1][it2][it3]->set_signal_valack_out (type); \
              }                                                         \
          }                                                             \
      }                                                                 \
  }


#define _ALLOC3_SIGNAL_IN( sig, name, type, size, x1, x2,x3)            \
  {                                                                     \
    sig = new SC_IN (type) *** [x1];                                    \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_IN (type) ** [x2];                           \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = new SC_IN (type) * [x3];                   \
            for (uint32_t it3=0; it3<x3; it3++)                         \
              {                                                         \
                if (size > 0)                                           \
                  {                                                     \
                    sig [it1][it2][it3] = interface[it1][it2][it3]->set_signal_in <type> (name, size); \
                  }                                                     \
                else                                                    \
                  {                                                     \
                    PRINT_SIZE_NUL(_component,interface[it1][it2][it3],name); \
                  }                                                     \
              }                                                         \
          }                                                             \
      }                                                                 \
  }

#define _ALLOC3_SIGNAL_OUT( sig, name, type, size, x1, x2,x3)           \
  {                                                                     \
    sig = new SC_OUT (type) *** [x1];                                   \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_OUT (type) ** [x2];                          \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = new SC_OUT (type) * [x3];                  \
            for (uint32_t it3=0; it3<x3; it3++)                         \
              {                                                         \
                if (size > 0)                                           \
                  {                                                     \
                    sig [it1][it2][it3] = interface[it1][it2][it3]->set_signal_out <type> (name, size); \
                  }                                                     \
                else                                                    \
                  {                                                     \
                    PRINT_SIZE_NUL(_component,interface[it1][it2][it3],name); \
                  }                                                     \
              }                                                         \
          }                                                             \
      }                                                                 \
  }

// #define ALLOC3_VAL_ACK_IN( sig, name, type      ) _ALLOC3_VAL_ACK_IN( sig, name, type      , iterator_1, iterator_2, iterator_3) 
// #define ALLOC3_VAL_ACK_OUT(sig, name, type      ) _ALLOC3_VAL_ACK_OUT(sig, name, type      , iterator_1, iterator_2, iterator_3) 
#define ALLOC3_VALACK_IN(  sig,       type      ) _ALLOC3_VALACK_IN(  sig,       type      , iterator_1, iterator_2, iterator_3) 
#define ALLOC3_VALACK_OUT( sig,       type      ) _ALLOC3_VALACK_OUT( sig,       type      , iterator_1, iterator_2, iterator_3) 
#define ALLOC3_SIGNAL_IN(  sig, name, type, size) _ALLOC3_SIGNAL_IN(  sig, name, type, size, iterator_1, iterator_2, iterator_3) 
#define ALLOC3_SIGNAL_OUT( sig, name, type, size) _ALLOC3_SIGNAL_OUT( sig, name, type, size, iterator_1, iterator_2, iterator_3) 

#define DELETE3_SIGNAL(sig, x1, x2, x3, size)                           \
  {                                                                     \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            for (uint32_t it3=0; it3<x3; it3++)                         \
              {                                                         \
                if (size > 0)                                           \
                  {                                                     \
                    delete sig[it1][it2][it3];                          \
                  }                                                     \
              }                                                         \
            delete [] sig[it1][it2];                                    \
          }                                                             \
        delete [] sig[it1];                                             \
      }                                                                 \
    delete [] sig;                                                      \
  }

#define ALLOC3_FOREIGN_SIGNAL_IN( sig, interface, name, type, size, x1, x2,x3)     \
  {                                                                     \
    sig = new SC_IN (type) *** [x1];                                    \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_IN (type) ** [x2];                           \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = new SC_IN (type) * [x3];                   \
            for (uint32_t it3=0; it3<x3; it3++)                         \
              if (size > 0)                                             \
                {                                                       \
                  std::string str = (toString("in")+"_"+((interface!="")?(toString(interface)+"_"):toString(""))+toString(it1)+"_"+toString(it2)+"_"+toString(it3)+"_"+toString(name)); \
                  sig [it1][it2][it3] = new SC_IN (type) (str.c_str()); \
                }                                                       \
          }                                                             \
      }                                                                 \
  }

#define ALLOC3_FOREIGN_SIGNAL_OUT( sig, interface, name, type, size, x1, x2,x3)    \
  {                                                                     \
    sig = new SC_OUT (type) *** [x1];                                   \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        sig [it1] = new SC_OUT (type) ** [x2];                          \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            sig [it1][it2] = new SC_OUT (type) * [x3];                  \
            for (uint32_t it3=0; it3<x3; it3++)                         \
              if (size > 0)                                             \
                {                                                       \
                  std::string str = (toString("out")+"_"+((interface!="")?(toString(interface)+"_"):toString(""))+toString(it1)+"_"+toString(it2)+"_"+toString(it3)+"_"+toString(name)); \
                  sig [it1][it2][it3] = new SC_OUT(type) (str.c_str()); \
                }                                                       \
          }                                                             \
      }                                                                 \
  }

#define DELETE3_FOREIGN_SIGNAL( sig, size,x1,x2,x3)            \
  {                                                            \
    DELETE3_SIGNAL(sig,x1,x2,x3,size);                         \
  }

#define ALLOC3_SC_SIGNAL( sig, name, type, x1, x2, x3)                  \
  sig = new sc_signal<type> *** [x1];                                   \
  {                                                                     \
    std::string separator="_";                                          \
    std::string str;                                                    \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
         sig [it1] = new sc_signal<type> ** [x2];                       \
         for (uint32_t it2=0; it2<x2; it2++)                            \
           {                                                            \
              sig [it1][it2] = new sc_signal<type> * [x3];              \
              for (uint32_t it3=0; it3<x3; it3++)                       \
                {                                                       \
                  str = name+separator+toString(it1)+separator+toString(it2)+separator+toString(it3); \
                  sig [it1][it2][it3] = new sc_signal<type> (str.c_str()); \
                  PRINT_SIGNAL_ADDRESS(str.c_str(),sig[it1][it2][it3]); \
                }                                                       \
           }                                                            \
      }                                                                 \
  }

#define INSTANCE3_SC_SIGNAL(component, sig, x1, x2, x3)                 \
  for (uint32_t it1=0; it1<x1; it1++)                                   \
    for (uint32_t it2=0; it2<x2; it2++)                                 \
      for (uint32_t it3=0; it3<x3; it3++)                               \
        {                                                               \
          TEST_SIGNAL(component->sig  [it1][it2][it3]->name(),component->sig  [it1][it2][it3]); \
          TEST_SIGNAL(sig             [it1][it2][it3]->name(),sig             [it1][it2][it3]); \
          (*(component->sig[it1][it2][it3])) (*(sig[it1][it2][it3]));   \
        }

#define _INSTANCE3_SC_SIGNAL(component, sig1, sig2, x1, x2, x3)         \
  for (uint32_t it1=0; it1<x1; it1++)                                   \
    for (uint32_t it2=0; it2<x2; it2++)                                 \
      for (uint32_t it3=0; it3<x3; it3++)                               \
        {                                                               \
          TEST_SIGNAL(component->sig1 [it1][it2][it3]->name(),component->sig1 [it1][it2][it3]); \
          TEST_SIGNAL(sig2            [it1][it2][it3]->name(),sig2            [it1][it2][it3]); \
          (*(component->sig1[it1][it2][it3])) (*(sig2[it1][it2][it3])); \
        }

#define DELETE3_SC_SIGNAL(sig,x1,x2,x3)                                 \
  {                                                                     \
    for (uint32_t it1=0; it1<x1; it1++)                                 \
      {                                                                 \
        for (uint32_t it2=0; it2<x2; it2++)                             \
          {                                                             \
            for (uint32_t it3=0; it3<x3; it3++)                         \
              {                                                         \
                PRINT_SIGNAL_ADDRESS("",sig[it1][it2][it3]);            \
                delete sig[it1][it2][it3];                              \
              }                                                         \
            delete [] sig[it1][it2];                                    \
          }                                                             \
        delete [] sig[it1];                                             \
      }                                                                 \
    delete [] sig;                                                      \
  }

#endif
