#ifdef VHDL
/*
 * $Id$
 *
 * [ Description ]
 * 
 */

#include "Behavioural/include/Component.h"

namespace morpheo              {
namespace behavioural          {

#undef  FUNCTION
#define FUNCTION "Component::vhdl_instance"
  void Component::vhdl_instance (Vhdl * & vhdl)
  {
    log_printf(FUNC,Behavioural,FUNCTION,"Begin");

    uint32_t             cpt = 0;
    map<Signal *,string> tab;

    // buffer all output
    {
      vhdl->set_body ("------------------------------------------------------");
      vhdl->set_body ("-- Output's Buffer");
      vhdl->set_body ("------------------------------------------------------");

      // for each interface
      list<Interface_fifo *>         * list_interface = (_entity)->get_interfaces_list()->get_interface_list();
      list<Interface_fifo *>::iterator j              = list_interface->begin();
      if (not list_interface->empty())
	{
	  while (j != list_interface->end())
	    {
	      // for each signal
	      list<Signal *>         * list_signal = (*j)->get_signal_list();
	      list<Signal *>::iterator k           = list_signal->begin();
	      if (not list_signal->empty())
		{
		  while (k != list_signal->end())
		    {
		      Signal * signal = (*k);

		      // test if is connect with external interface or with an another component AND if this port is mapped. 
		      if ( (signal->get_direction() == OUT) and
			   (signal->get_connect_from_signal () != NULL) )
			{
			  // Create name
			  string signal_name = "signal_"+toString(cpt++);
			  
			  tab [signal                           ] = signal_name;
			  tab [signal->get_connect_from_signal()] = signal_name;
			  
			  // Add a new signal and the affectation
			  vhdl->set_signal (signal_name, signal->get_size());
			  vhdl->set_body   (signal->get_name()+" <= "+signal_name+";");
			}
		      else
			{
			  tab [signal                   ] = signal->get_name();
			}
		      ++k;
		    }
		}
	      ++j;
	    }
	}
      vhdl->set_body ("");
      vhdl->set_body ("------------------------------------------------------");
      vhdl->set_body ("");
    }

    vhdl->set_library_work (_entity->get_name() + "_Pack");

    // for each entity
    list<Entity *>         * list_component = _list_component;
    list<Entity *>::iterator i              = list_component->begin();
    if (not list_component->empty())
      {
	while (i != list_component->end())
	  {
	    vhdl->set_library_work ((*i)->get_name() + "_Pack");

	    list<string> list_port_map;
	    
	    // for each interface
	    list<Interface_fifo *>         * list_interface = (*i)->get_interfaces_list()->get_interface_list();
	    list<Interface_fifo *>::iterator j              = list_interface->begin();
	    if (not list_interface->empty())
	      {
		while (j != list_interface->end())
		  {
		    // for each signal
		    list<Signal *>         * list_signal = (*j)->get_signal_list();
		    list<Signal *>::iterator k           = list_signal->begin();
		    if (not list_signal->empty())
		      {
			while (k != list_signal->end())
			  {
			    // test if is connect with external interface or with an another component.
			    Signal * signal_src  = (*k);

			    if (signal_src->presence_vhdl () == true)
			      {
				Signal * signal_dest = signal_src->get_connect_to_signal();
				string   name_src    = signal_src->get_name();
				string   name_dest;
				
// 				// Test if destination signal is a interface port ?
// 				if (_entity->find_signal(signal_dest) == false)
// 				  {
				    // find if signal is already link
				    map<Signal *,string>::iterator it = tab.find(signal_dest); 
				    if (tab.find(signal_dest) == tab.end())
				      {
					// Create name
					name_dest = "signal_"+toString(cpt++);
					
					tab [signal_src ] = name_dest;
					tab [signal_dest] = name_dest;
					
					// Add a new signal
					vhdl->set_signal (name_dest, signal_src->get_size());
				      }
				    else
				      {
					// find !!!!
					name_dest = (*it).second;
					tab [signal_src ] = name_dest;
				      }
// 				  }
// 				else
// 				  {
// 				    cout << "Kane à dit : " << signal_dest->get_name() << endl;
// 				    // Test if output
// 				    if (signal_dest->get_direction() == OUT)
// 				      {
// 					// Take buffer's signal
// 					map<Signal *,string>::iterator it = tab.find(signal_dest);
// 					name_dest        = (*it).second;

// 					cout << " * OUT - name : " << name_dest << endl;
// 				      }
// 				    else
// 				      {
// 					name_dest = signal_dest->get_name();
// 					cout << " * IN  - name : " << name_dest << endl;
// 				      }				    
// 				  }
				
				vhdl->set_body_component_port_map (list_port_map, name_src, name_dest);
			      }
			    ++k;
			  }
		      }
		    ++j;
		  }
	      }
	    vhdl->set_body_component ("instance_"+(*i)->get_name(),(*i)->get_name(),list_port_map);
	    ++i;
	  }
      }
    log_printf(FUNC,Behavioural,FUNCTION,"End");
  };

}; // end namespace behavioural
}; // end namespace morpheo
#endif
