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

#include "Behavioural/include/Signal.h"


namespace morpheo              {
namespace behavioural          {

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

    if (        _is_allocate == false)
      throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\", can't map with signal \""+        get_name()+"\", because it's not already allocate."));
    if (signal->_is_allocate == false)
      throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\", can't map with signal \""+signal->get_name()+"\", because it's not already allocate."));
    if (_is_map == true)
      throw (ErrorMorpheo ("<Signal::mapping> Can't mapping signal \""+_name+"\" with \""+signal->get_name()+"\", because it's already map."));
    

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

//  log_printf(TRACE,Behavioural,FUNCTION, "Signal \"%s\"\tlink with \"%s\"", _name.c_str(), signal->get_name().c_str());

    log_printf(TRACE,Behavioural,FUNCTION, " * sc_signal (before) %.8x - %.8x", (uint32_t)(_sc_signal_map), (uint32_t)(signal->_sc_signal_map));

    _connect_to_signal = signal;
    signal->_connect_from_signal = this;

    if (is_port_component == true)
      {
	if ((_direction == IN ) and (signal->_direction == IN ))
	  {
	    switch (_type_info)
	      {
	      case BOOL     : {(*(static_cast<sc_in  <bool    > *>(_sc_signal))) (*(static_cast<sc_in  <bool    > *>(signal->_sc_signal))); break;}
	      case UINT8_T  : {(*(static_cast<sc_in  <uint8_t > *>(_sc_signal))) (*(static_cast<sc_in  <uint8_t > *>(signal->_sc_signal))); break;}
	      case UINT16_T : {(*(static_cast<sc_in  <uint16_t> *>(_sc_signal))) (*(static_cast<sc_in  <uint16_t> *>(signal->_sc_signal))); break;}
	      case UINT32_T : {(*(static_cast<sc_in  <uint32_t> *>(_sc_signal))) (*(static_cast<sc_in  <uint32_t> *>(signal->_sc_signal))); break;}
	      case UINT64_T : {(*(static_cast<sc_in  <uint64_t> *>(_sc_signal))) (*(static_cast<sc_in  <uint64_t> *>(signal->_sc_signal))); break;}
	      default       : {throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\" : type unknow.")); break;}
	      }
	  }
	else
	  {
	    if ((_direction == OUT) and (signal->_direction == OUT))
	      {
		_is_map = true;
		signal->_sc_signal_map = _sc_signal_map;
		
		switch (_type_info)
		  {
		  case BOOL     : {(*(static_cast<sc_out <bool    > *>(_sc_signal))) (*(static_cast<sc_out <bool    > *>(signal->_sc_signal))); break;} 
		  case UINT8_T  : {(*(static_cast<sc_out <uint8_t > *>(_sc_signal))) (*(static_cast<sc_out <uint8_t > *>(signal->_sc_signal))); break;} 
		  case UINT16_T : {(*(static_cast<sc_out <uint16_t> *>(_sc_signal))) (*(static_cast<sc_out <uint16_t> *>(signal->_sc_signal))); break;}
		  case UINT32_T : {(*(static_cast<sc_out <uint32_t> *>(_sc_signal))) (*(static_cast<sc_out <uint32_t> *>(signal->_sc_signal))); break;} 
		  case UINT64_T : {(*(static_cast<sc_out <uint64_t> *>(_sc_signal))) (*(static_cast<sc_out <uint64_t> *>(signal->_sc_signal))); break;} 
		  default       : {throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\" : type unknow.")); break;}
		  }
	      }
	    else
	      {
		throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\" can't been linked with signal \""+signal->get_name()+"\" : between two components, illegal direction ("+toString(_direction)+" with "+toString(signal->_direction)+")."));
	      }
	  }
      }
    else
      {
	if ((_direction == IN ) and (signal->_direction == OUT))
	  {
	    switch (_type_info)
	      {
	      case BOOL     : {(*(static_cast<sc_in  <bool    > *>(_sc_signal))) (*(static_cast<sc_out <bool    > *>(signal->_sc_signal))); break;}
	      case UINT8_T  : {(*(static_cast<sc_in  <uint8_t > *>(_sc_signal))) (*(static_cast<sc_out <uint8_t > *>(signal->_sc_signal))); break;}
	      case UINT16_T : {(*(static_cast<sc_in  <uint16_t> *>(_sc_signal))) (*(static_cast<sc_out <uint16_t> *>(signal->_sc_signal))); break;}
	      case UINT32_T : {(*(static_cast<sc_in  <uint32_t> *>(_sc_signal))) (*(static_cast<sc_out <uint32_t> *>(signal->_sc_signal))); break;}
	      case UINT64_T : {(*(static_cast<sc_in  <uint64_t> *>(_sc_signal))) (*(static_cast<sc_out <uint64_t> *>(signal->_sc_signal))); break;}
	      default       : {throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\" : type unknow.")); break;}
	      }
	  }
	else
	  {
	    if ((_direction == OUT) and (signal->_direction == IN ))
	      {
		_is_map = true;
		switch (_type_info)
		  {
		  case BOOL     : {(*(static_cast<sc_out <bool    > *>(_sc_signal))) (*(static_cast<sc_in  <bool    > *>(signal->_sc_signal))); break;}
		  case UINT8_T  : {(*(static_cast<sc_out <uint8_t > *>(_sc_signal))) (*(static_cast<sc_in  <uint8_t > *>(signal->_sc_signal))); break;}
		  case UINT16_T : {(*(static_cast<sc_out <uint16_t> *>(_sc_signal))) (*(static_cast<sc_in  <uint16_t> *>(signal->_sc_signal))); break;}
		  case UINT32_T : {(*(static_cast<sc_out <uint32_t> *>(_sc_signal))) (*(static_cast<sc_in  <uint32_t> *>(signal->_sc_signal))); break;}
		  case UINT64_T : {(*(static_cast<sc_out <uint64_t> *>(_sc_signal))) (*(static_cast<sc_in  <uint64_t> *>(signal->_sc_signal))); break;}
		  default       : {throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\" : type unknow.")); break;}
		  }
	      }
	    else
	      {
		throw (ErrorMorpheo ("<Signal::link> Signal \""+_name+"\" can't been linked with signal \""+signal->get_name()+"\" : between a interface's port and one component, illegal direction ("+toString(_direction)+" with "+toString(signal->_direction)+")."));
	      }
	  }
      }

    log_printf(TRACE,Behavioural,FUNCTION, " * sc_signal (after ) %.8x - %.8x", (uint32_t)(_sc_signal_map), (uint32_t)(signal->_sc_signal_map));
    log_printf(FUNC,Behavioural,FUNCTION,"End");
  };

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