#ifndef Allocation_H
#define Allocation_H

// Help to allocate interface

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

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

#ifdef POSITION
#define ALLOC_INTERFACE( name, direction, localisation, str)		\
  Interface_fifo * interface = _interfaces->set_interface( name, direction, localisation, str);
#else
#define ALLOC_INTERFACE( name, direction, localisation, str)		\
  Interface_fifo * interface = _interfaces->set_interface( name);
#endif

#define ALLOC_VAL_ACK_IN(  sig, name, type)				\
  {									\
    sig = interface->set_signal_valack_in (name, type);			\
  }									
#define ALLOC_VAL_ACK_OUT( sig, name, type)				\
  {									\
    sig = interface->set_signal_valack_out(name, type);			\
  }									
#define ALLOC_VALACK_IN(     sig, type)					\
  {									\
    sig = interface->set_signal_valack_in (type);			\
  }									
#define ALLOC_VALACK_OUT(    sig, type)					\
  {									\
    sig = interface->set_signal_valack_out(type);			\
  }									
#define ALLOC_SIGNAL_IN(  sig, name, type, size)			\
  if (size > 0)								\
    {									\
      sig = interface->set_signal_in <type> (name, size);		\
    }									
#define ALLOC_SIGNAL_OUT( sig, name, type, size)			\
  if (size > 0)								\
    {									\
      sig = interface->set_signal_out<type> (name, size);		\
    }

#define ALLOC_SC_SIGNAL(  sig, name, type)		                \
  sc_signal<type> * sig = new sc_signal<type> (name);

#define INSTANCE_SC_SIGNAL(component, sig)	\
  (*(component->sig)) (*(sig));

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

#define __ALLOC1_INTERFACE(name, it1)		\
  const std::string interface_name = name;	\
  const uint32_t iterator_1 = it1;

#define __ALLOC1_SIGNAL_IN( sig, name, type)		\
  {									\
    sig = new SC_IN(type) * [iterator_1];				\
    std::string separator="_";						\
    for (uint32_t alloc_signal_it1=0; alloc_signal_it1<iterator_1; alloc_signal_it1++) \
      {									\
	std::string str = "in_"+interface_name+separator+toString(alloc_signal_it1)+separator+name; \
	sig [alloc_signal_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 alloc_signal_it1=0; alloc_signal_it1<iterator_1; alloc_signal_it1++) \
      {									\
	std::string str = "out_"+interface_name+separator+toString(alloc_signal_it1)+separator+name; \
	sig [alloc_signal_it1] = new SC_OUT(type) (str.c_str());		\
      }									\
  }

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

#define ALLOC1_VAL_ACK_IN( sig, name, type)				\
  {									\
    sig = new SC_IN (Tcontrol_t) * [iterator_1];			\
    for (uint32_t alloc_signal_it1=0; alloc_signal_it1<iterator_1; alloc_signal_it1++) \
      {									\
	sig [alloc_signal_it1] = interface[alloc_signal_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 alloc_signal_it1=0; alloc_signal_it1<iterator_1; alloc_signal_it1++) \
      {									\
	sig [alloc_signal_it1] = interface[alloc_signal_it1]->set_signal_valack_out(name, type); \
      }									\
  }
#define ALLOC1_VALACK_IN(    sig, type)					\
  {									\
    sig = new SC_IN (Tcontrol_t) * [iterator_1];			\
    for (uint32_t alloc_signal_it1=0; alloc_signal_it1<iterator_1; alloc_signal_it1++) \
      {									\
	sig [alloc_signal_it1] = interface[alloc_signal_it1]->set_signal_valack_in (type); \
      }									\
  }
#define ALLOC1_VALACK_OUT(   sig, type)					\
  {									\
    sig = new SC_OUT(Tcontrol_t) * [iterator_1];			\
    for (uint32_t alloc_signal_it1=0; alloc_signal_it1<iterator_1; alloc_signal_it1++) \
      {									\
	sig [alloc_signal_it1] = interface[alloc_signal_it1]->set_signal_valack_out(type); \
      }									\
  }
#define ALLOC1_SIGNAL_IN( sig, name, type, size)			\
  if (size > 0)								\
    {									\
      sig = new SC_IN (type) * [iterator_1];				\
      for (uint32_t alloc_signal_it1=0; alloc_signal_it1<iterator_1; alloc_signal_it1++) \
	{								\
	  sig [alloc_signal_it1] = interface[alloc_signal_it1]->set_signal_in <type> (name, size); \
	}								\
    }

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

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

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

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

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

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

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

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

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

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

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

#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 ALLOC2_SC_SIGNAL( sig, name, type, it1, it2)			\
  sc_signal<type> *** sig = new sc_signal<type> ** [it1];		\
  {									\
    std::string separator="_";						\
    std::string str;							\
    for (uint32_t alloc_signal_it1=0; alloc_signal_it1<it1; alloc_signal_it1++)	\
      {									\
	sig [alloc_signal_it1] = new sc_signal<type> * [it2];		\
	for (uint32_t alloc_signal_it2=0; alloc_signal_it2<it2; alloc_signal_it2++) \
	  {								\
	    str = name+separator+toString(alloc_signal_it1)+separator+toString(alloc_signal_it2); \
	    sig [alloc_signal_it1][alloc_signal_it2] = new sc_signal<type> (str.c_str()); \
	  }								\
      }									\
  }

#define INSTANCE2_SC_SIGNAL(component, sig, it1, it2)			\
  for (uint32_t alloc_signal_it1=0; alloc_signal_it1<it1; alloc_signal_it1++) \
    for (uint32_t alloc_signal_it2=0; alloc_signal_it2<it2; alloc_signal_it2++)	\
      {									\
	(*(component->sig[alloc_signal_it1][alloc_signal_it2])) (*(sig[alloc_signal_it1][alloc_signal_it2])); \
      }
#endif
