#ifndef morpheo_behavioural_Interface_h
#define morpheo_behavioural_Interface_h

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

#ifdef SYSTEMC
#include "systemc.h"
#endif

#include <stdint.h>
#include <iostream>
#include <list>
#include "Behavioural/include/Signal.h"
#include "Behavioural/include/Direction.h"
#include "Behavioural/include/Localisation.h"
#ifdef VHDL
#include "Behavioural/include/Vhdl.h"
#endif
#include "Include/ToString.h"
#include "Include/ErrorMorpheo.h"
#include "Include/Debug.h"

using namespace std;

namespace morpheo              {
namespace behavioural          {

  class Interface
  {
    friend class Interfaces;

    // -----[ fields ]----------------------------------------------------
  protected : const string          _name         ;
  protected : const direction_t     _direction    ;
  protected : const localisation_t  _localisation ;
  protected :       string          _comment      ;

  protected : list<Signal *>      * _list_signal  ;

#ifdef POSITION
  protected :       bool            _is_map       ;
  protected :       void          * _entity_map   ; // Entity -> erreur cyclique
  protected :       void          * _interface_map; // pour être homogène avec _entity_map
#endif

#ifdef VHDL_TESTBENCH
  private   : uint32_t              _nb_cycle     ;
#endif
    
    // -----[ methods ]---------------------------------------------------
  public    :                       Interface            (string         name        ,
							  direction_t    direction   ,
							  localisation_t localisation);

  public    :                       Interface            (const Interface    & interface);
  public    :                       ~Interface           ();

  public    : void                  set_comment          (string comment);
  protected : string                get_comment          (void          );

  protected : string                signal_name          (string      name_interface,
							  string      name_signal   ,
							  direction_t direction     );

  protected : string                get_signal           (void);
  public    : Signal *              set_signal           (string          name     ,
							  direction_t     direction,
							  uint32_t        size     ,
							  presence_port_t presence_port = PORT_VHDL_YES_TESTBENCH_YES);

#ifdef SYSTEMC
  public    : sc_in_clk *           set_signal_clk       (string          name     ,
							  uint32_t        size     ,
							  presence_port_t presence_port=CLOCK_VHDL_YES)
    {
      log_printf(FUNC,Behavioural,"set_signal_clk","Begin");

      if ((presence_port != CLOCK_VHDL_YES) and
	  (presence_port != CLOCK_VHDL_NO ))
	throw ErrorMorpheo ("Signal \""+name+"\" is a clock, bad presence_port.");

      Signal    * sig    = set_signal (name, IN , size, presence_port);
      sc_in_clk * signal = new sc_in_clk (sig->_name.c_str());

      log_printf(FUNC,Behavioural,"set_signal_clk","End");

      return signal;
    };

  public    : template <typename T>
              sc_in <T> *           set_signal_in       (string          name     ,
							 uint32_t        size     ,
							 presence_port_t presence_port=PORT_VHDL_YES_TESTBENCH_YES)
    {
      log_printf(FUNC,Behavioural,"set_signal_in","Begin");

      if ((presence_port == CLOCK_VHDL_YES) or 
	  (presence_port == CLOCK_VHDL_NO ))
	throw ErrorMorpheo ("Signal \""+name+"\" is not a clock, bad presence_port.");

      Signal * sig = set_signal (name, IN , size, presence_port);
      sc_in <T> * port = new sc_in <T> (sig->_name.c_str());
#ifdef VHDL_TESTBENCH
      sig->alloc<T> (static_cast<void *>(port));
#endif

      log_printf(FUNC,Behavioural,"set_signal_in","End");

      return port;
    };

  public    : template <typename T>
              sc_out <T> *          set_signal_out      (string          name     ,
							 uint32_t        size     ,
							 presence_port_t presence_port=PORT_VHDL_YES_TESTBENCH_YES)
    {
      log_printf(FUNC,Behavioural,"set_signal_out","Begin");

      if ((presence_port == CLOCK_VHDL_YES) or 
	  (presence_port == CLOCK_VHDL_NO ))
	throw ErrorMorpheo ("Signal \""+name+"\" is not a clock, bad presence_port.");

      Signal * sig = set_signal (name, OUT , size, presence_port);
      sc_out <T> * port = new sc_out <T> (sig->_name.c_str());
#ifdef VHDL_TESTBENCH
      sig->alloc<T> (static_cast<void *>(port));
#endif

      log_printf(FUNC,Behavioural,"set_signal_out","End");

      return port;
    };
#endif

#ifdef VHDL
  public    : void                  set_port             (Vhdl * & vhdl);
#ifdef VHDL_TESTBENCH
  public    : void                  set_signal           (Vhdl * & vhdl);
  public    : void                  get_signal           (list<string> * & list_signal);
#endif
#endif
#ifdef VHDL_TESTBENCH
  public    : uint32_t              get_cycle            (void);
  public    : string                get_clock            (void);

  public    : void                  testbench            (void);
  public    : void                  testbench_cycle      (void);
  public    : void                  testbench_body       (Vhdl           * & vhdl          ,
							  string             counter_name  );
  public    : string                testbench_test       (Vhdl           * & vhdl        ,
							  string             counter_name);
  public    : string                testbench_test_ok    (Vhdl           * & vhdl        );
  protected : string                testbench_test_name   (Vhdl           * & vhdl);
  protected : string                testbench_test_ok_name(Vhdl           * & vhdl);

#endif

#ifdef POSITION
  public    : void                  port_map             (void * entity,
							  void * interface);
#endif

  public    : XML                   toXML                (void);
#ifdef POSITION
  public    : XML                   toXML_mapping        (void);
#endif
  public    : friend ostream&       operator<<           (ostream& output_stream,
  					  		  morpheo::behavioural::Interface & x);

  };

}; // end namespace behavioural          
}; // end namespace morpheo              

#endif
