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

#include "Behavioural/include/Signal.h"


namespace morpheo              {
namespace behavioural          {

#undef  FUNCTION
#define FUNCTION "Signal::link"
  void Signal::link (Signal * signal_dest,
		     bool     signal_dest_is_port)
  {
    log_printf(FUNC,Behavioural,FUNCTION,"Begin");

    Signal * signal_src = this;

    // Test
    if (signal_src ->_is_allocate == false)
      throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\", can't map with signal \""+        get_name()+"\", because the first signal is not already allocate."));
    if (signal_dest->_is_allocate == false)
      throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\", can't map with signal \""+signal_dest->get_name()+"\", because the second signal is not already allocate."));
    if (signal_src ->_is_map_as_src  == true)
      throw (ErrorMorpheo ("<Signal::mapping> Can't mapping signal \""+_name+"\" with \""+signal_dest->get_name()+"\", because the first signal is already mapped."));

    // List of all case
    //
    //            src         dest
    // COMPONENT {IN } ----- {SIG} SIGNAL
    // COMPONENT {OUT} ----- {SIG} SIGNAL
    //
    // COMPONENT {IN } ----- {IN } PORT
    // COMPONENT {OUT} ----- {OUT} PORT

    // list valid case
    if (not (    signal_dest_is_port and (((signal_src->_direction == IN ) and (signal_dest->_direction == IN      )) or
					  ((signal_src->_direction == OUT) and (signal_dest->_direction == OUT     )))) and
	not (not signal_dest_is_port and (((signal_src->_direction == IN ) and (signal_dest->_direction == INTERNAL)) or
					  ((signal_src->_direction == OUT) and (signal_dest->_direction == INTERNAL)))))
      throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\" can't been linked with signal \""+signal_dest->get_name()+"\" : illegal direction ("+toString(signal_src->_direction)+" with "+toString(signal_dest->_direction)+")."));

    // update info source
    signal_src ->_connect_to_signal   = signal_dest;
    signal_src ->_is_map_as_src       = true;
    
    // update info destination
    signal_dest->_connect_from_signal = signal_src;
    signal_dest->_is_map_as_dest      = true;

    // an internal signal and port can't be a source. 
    // also, to fill the connect_to_signal's field 
    if ((signal_src->_direction == OUT) and 
	(signal_dest->_direction == INTERNAL))
      {
	signal_dest->_connect_to_signal = signal_src;
      }

    // vhdl_testbench : to read an output producte by a internal component
    // TODO : à vérifier !!!!!!!!!!!!
    if ((signal_dest_is_port == true) and 
	(signal_src ->_direction == OUT))
      signal_dest->_sc_signal_map = signal_src ->_sc_signal_map;
    
    connect (signal_dest);

    log_printf(FUNC,Behavioural,FUNCTION,"End");
  };

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