#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
    
    {
      // 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())
	{
	  vhdl->set_body ("------------------------------------------------------");
	  vhdl->set_body ("-- Output's Buffer");
	  vhdl->set_body ("------------------------------------------------------");
	  
	  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<Tcomponent_t *>         * list_component = _list_component;
    list<Tcomponent_t *>::iterator i              = list_component->begin();
    if (not list_component->empty())
      {
	while (i != list_component->end())
	  {
	    Entity *    entity   = (*i)->_entity;
	    Tinstance_t instance = (*i)->_instance;
	    
	    if (instance & INSTANCE_LIBRARY)
	      vhdl->set_library_work (entity->get_name() + "_Pack");

	    if (instance & INSTANCE_COMPONENT)
	    {
	      list<string> list_port_map;
	      
	      // 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())
			    {
			      // 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
// 				  {
// 				    // 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 , signal_src ->get_size(),
								     name_dest, signal_dest->get_size() );
				}
			      ++k;
			    }
			}
		      ++j;
		    }
		}
	      vhdl->set_body_component ("instance_"+entity->get_name(),entity->get_name(),list_port_map);
	      
	    }
	    ++i;
	  }
      }
    log_printf(FUNC,Behavioural,FUNCTION,"End");
  };
  
}; // end namespace behavioural
}; // end namespace morpheo
#endif
