/*
 * $Id: Morpheo_allocation.cpp 88 2008-12-10 18:31:39Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "TopLevel/include/Morpheo.h"
#include "Behavioural/include/Allocation.h"

namespace morpheo {

#undef  FUNCTION
#define FUNCTION "Morpheo::allocation"
  void Morpheo::allocation 
  (
#ifdef STATISTICS
   morpheo::behavioural::Parameters_Statistics * param_statistics
#else
   void
#endif
   )
  {
    log_begin(Morpheo,FUNCTION);

    _component = new behavioural::Component (_usage);

    behavioural::Entity * entity = _component->set_entity (_name       
					      ,"Morpheo"
#ifdef POSITION
					      ,COMBINATORY 
#endif
					      );

    _interfaces = entity->set_interfaces();
    
    // ~~~~~[ Interface : "" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      behavioural::Interface * interface = _interfaces->set_interface(""
#ifdef POSITION
							 ,IN
							 ,SOUTH,
							 "Generalist interface"
#endif
							 );
      
      in_CLOCK        = interface->set_signal_clk              ("clock" ,1, behavioural::CLOCK_VHDL_YES);
      in_NRESET       = interface->set_signal_in  <Tcontrol_t> ("nreset",1, behavioural::RESET_VHDL_YES);
    }


    // ~~~~~[ Interface "icache_req" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("icache_req",WEST,OUT,_("Request to instruction cache"),_nb_icache_port);

      ALLOC1_VALACK_OUT(out_ICACHE_REQ_VAL         ,behavioural::VAL);
      ALLOC1_VALACK_IN ( in_ICACHE_REQ_ACK         ,behavioural::ACK);
      ALLOC1_SIGNAL_OUT(out_ICACHE_REQ_THREAD_ID   ,"thread_id",Ticache_context_t    ,_size_icache_thread_id);
      ALLOC1_SIGNAL_OUT(out_ICACHE_REQ_PACKET_ID   ,"packet_id",Ticache_packet_t     ,_size_icache_packet_id);
      ALLOC1_SIGNAL_OUT(out_ICACHE_REQ_ADDRESS     ,"address"  ,Ticache_address_t    ,_size_icache_address  );
      ALLOC1_SIGNAL_OUT(out_ICACHE_REQ_TYPE        ,"type"     ,Ticache_type_t       ,_size_icache_type     );
    }

    // ~~~~~[ Interface "icache_rsp" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("icache_rsp",WEST,IN ,_("Respons from instruction cache"),_nb_icache_port);
      
      ALLOC1_VALACK_IN ( in_ICACHE_RSP_VAL         ,behavioural::VAL);
      ALLOC1_VALACK_OUT(out_ICACHE_RSP_ACK         ,behavioural::ACK);
      ALLOC1_SIGNAL_IN ( in_ICACHE_RSP_THREAD_ID   ,"thread_id"  ,Ticache_context_t    ,_size_icache_thread_id);
      ALLOC1_SIGNAL_IN ( in_ICACHE_RSP_PACKET_ID   ,"packet_id"  ,Ticache_packet_t     ,_size_icache_packet_id);
      ALLOC1_SIGNAL_IN ( in_ICACHE_RSP_ERROR       ,"error"      ,Ticache_error_t      ,_size_icache_error);
    }
    {
      ALLOC2_INTERFACE("icache_rsp",WEST,IN ,_("Respons from instruction cache"),_nb_icache_port,_icache_nb_instruction[it1]);
      
      _ALLOC2_SIGNAL_IN ( in_ICACHE_RSP_INSTRUCTION ,"instruction",Ticache_instruction_t,_size_icache_instruction,_nb_icache_port,_icache_nb_instruction[it1]);
    }

    // ~~~~~[ Interface "dcache_req" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("dcache_req", OUT, NORTH, _("Request to data cache"),_nb_dcache_port);
      
      ALLOC1_VALACK_OUT(out_DCACHE_REQ_VAL         ,behavioural::VAL);
      ALLOC1_VALACK_IN ( in_DCACHE_REQ_ACK         ,behavioural::ACK);
      ALLOC1_SIGNAL_OUT(out_DCACHE_REQ_THREAD_ID   ,"thread_id",Tdcache_context_t    ,_size_dcache_thread_id);
      ALLOC1_SIGNAL_OUT(out_DCACHE_REQ_PACKET_ID   ,"packet_id",Tdcache_packet_t     ,_size_dcache_packet_id);
      ALLOC1_SIGNAL_OUT(out_DCACHE_REQ_ADDRESS     ,"address"  ,Tdcache_address_t    ,_size_dcache_address);
      ALLOC1_SIGNAL_OUT(out_DCACHE_REQ_WDATA       ,"wdata"    ,Tdcache_data_t       ,_size_dcache_data);
      ALLOC1_SIGNAL_OUT(out_DCACHE_REQ_TYPE        ,"type"     ,Tdcache_type_t       ,_size_dcache_type);
    }
									    
    // ~~~~~[ Interface "dcache_rsp" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    {
      ALLOC1_INTERFACE("dcache_rsp", IN , NORTH, _("Respons from data cache"),_nb_dcache_port);

      ALLOC1_VALACK_IN ( in_DCACHE_RSP_VAL         ,behavioural::VAL);
      ALLOC1_VALACK_OUT(out_DCACHE_RSP_ACK         ,behavioural::ACK);
      ALLOC1_SIGNAL_IN ( in_DCACHE_RSP_THREAD_ID   ,"thread_id",Tdcache_context_t    ,_size_dcache_thread_id);
      ALLOC1_SIGNAL_IN ( in_DCACHE_RSP_PACKET_ID   ,"packet_id",Tdcache_packet_t     ,_size_dcache_packet_id);
      ALLOC1_SIGNAL_IN ( in_DCACHE_RSP_RDATA       ,"rdata"    ,Tdcache_data_t       ,_size_dcache_data);
      ALLOC1_SIGNAL_IN ( in_DCACHE_RSP_ERROR       ,"error"    ,Tdcache_error_t      ,_size_dcache_error);
    }

    // ~~~~~[ Interface : "interrupt" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("interrupt", IN , NORTH, _("Interruption line"),_nb_thread);

      ALLOC1_SIGNAL_IN ( in_INTERRUPT_ENABLE      ,"enable",Tcontrol_t           ,1);
    }

    // ~~~~~[ Component ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    std::string name;

    {
      name = _name+"_core";
      log_printf(INFO,Core,FUNCTION,_("Create   : %s"),name.c_str());
      
      _component_core = new morpheo::behavioural::core::Core
        (name.c_str()
#ifdef STATISTICS
         ,param_statistics
#endif
         ,_param_core
         ,_usage);
      
      _component->set_component (_component_core->_component
#ifdef POSITION
                                 , 50, 50, 10, 10
#endif
                                 );
    }
    
    // ~~~~~[ Instanciation ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    std::string src,dest;

    // ===================================================================
    // =====[ core ]======================================================
    // ===================================================================
    {
      src = _name+"_core";
      log_printf(INFO,Core,FUNCTION,_("Instance : %s"),src.c_str());
      
      // ~~~~~[ Interface "" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      {
        dest = _name;
#ifdef POSITION
        _component->interface_map (src ,"",
                                   dest,"");
#endif
        PORT_MAP(_component,src , "in_CLOCK" ,dest, "in_CLOCK");
        PORT_MAP(_component,src , "in_NRESET",dest, "in_NRESET");
      }

      // ~~~~~[ Interface "icache_req" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (uint32_t i=0; i<_nb_icache_port; ++i)
        {
          dest = _name;
#ifdef POSITION
          _component->interface_map (src ,"icache_req_"+toString(i),
                                     dest,"icache_req_"+toString(i));
#endif

          PORT_MAP(_component,src ,"out_ICACHE_REQ_"+toString(i)+"_VAL"      ,
                              dest,"out_ICACHE_REQ_"+toString(i)+"_VAL"      );
          PORT_MAP(_component,src , "in_ICACHE_REQ_"+toString(i)+"_ACK"      ,
                              dest, "in_ICACHE_REQ_"+toString(i)+"_ACK"      );
          if (_have_port_icache_thread_id)
          PORT_MAP(_component,src ,"out_ICACHE_REQ_"+toString(i)+"_THREAD_ID",
                              dest,"out_ICACHE_REQ_"+toString(i)+"_THREAD_ID");
          if (_have_port_icache_packet_id)
          PORT_MAP(_component,src ,"out_ICACHE_REQ_"+toString(i)+"_PACKET_ID",
                              dest,"out_ICACHE_REQ_"+toString(i)+"_PACKET_ID");
          PORT_MAP(_component,src ,"out_ICACHE_REQ_"+toString(i)+"_ADDRESS"  ,
                              dest,"out_ICACHE_REQ_"+toString(i)+"_ADDRESS"  );
          PORT_MAP(_component,src ,"out_ICACHE_REQ_"+toString(i)+"_TYPE"     ,
                              dest,"out_ICACHE_REQ_"+toString(i)+"_TYPE"     );
        }

      // ~~~~~[ Interface "icache_rsp" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
      for (uint32_t i=0; i<_nb_icache_port; ++i)
        {
          dest = _name;
#ifdef POSITION
          _component->interface_map (src ,"icache_rsp_"+toString(i),
                                     dest,"icache_rsp_"+toString(i));
#endif

          PORT_MAP(_component,src , "in_ICACHE_RSP_"+toString(i)+"_VAL"      ,
                              dest, "in_ICACHE_RSP_"+toString(i)+"_VAL"      );
          PORT_MAP(_component,src ,"out_ICACHE_RSP_"+toString(i)+"_ACK"      ,
                              dest,"out_ICACHE_RSP_"+toString(i)+"_ACK"      );
          if (_have_port_icache_thread_id)
          PORT_MAP(_component,src , "in_ICACHE_RSP_"+toString(i)+"_THREAD_ID",
                              dest, "in_ICACHE_RSP_"+toString(i)+"_THREAD_ID");
          if (_have_port_icache_packet_id)
          PORT_MAP(_component,src , "in_ICACHE_RSP_"+toString(i)+"_PACKET_ID",
                              dest, "in_ICACHE_RSP_"+toString(i)+"_PACKET_ID");
          PORT_MAP(_component,src , "in_ICACHE_RSP_"+toString(i)+"_ERROR"    ,
                              dest, "in_ICACHE_RSP_"+toString(i)+"_ERROR"    );

          for (uint32_t j=0; j<_icache_nb_instruction[i]; ++j)
            {
              dest = _name;
#ifdef POSITION
              _component->interface_map (src ,"icache_rsp_"+toString(i)+"_"+toString(j),
                                         dest,"icache_rsp_"+toString(i)+"_"+toString(j));
#endif
              
              PORT_MAP(_component,src , "in_ICACHE_RSP_"+toString(i)+"_"+toString(j)+"_INSTRUCTION",
                                  dest, "in_ICACHE_RSP_"+toString(i)+"_"+toString(j)+"_INSTRUCTION");
            }
        }

      // ~~~~~[ Interface "dcache_req" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (uint32_t i=0; i<_nb_dcache_port; ++i)
        {
          dest = _name;
#ifdef POSITION
          _component->interface_map (src ,"dcache_req_"+toString(i),
                                     dest,"dcache_req_"+toString(i));
#endif

          PORT_MAP(_component,src ,"out_DCACHE_REQ_"+toString(i)+"_VAL"      ,
                              dest,"out_DCACHE_REQ_"+toString(i)+"_VAL"      );
          PORT_MAP(_component,src , "in_DCACHE_REQ_"+toString(i)+"_ACK"      ,
                              dest, "in_DCACHE_REQ_"+toString(i)+"_ACK"      );
          if (_have_port_dcache_thread_id)
          PORT_MAP(_component,src ,"out_DCACHE_REQ_"+toString(i)+"_THREAD_ID",
                              dest,"out_DCACHE_REQ_"+toString(i)+"_THREAD_ID");
          if (_have_port_dcache_packet_id)
          PORT_MAP(_component,src ,"out_DCACHE_REQ_"+toString(i)+"_PACKET_ID",
                              dest,"out_DCACHE_REQ_"+toString(i)+"_PACKET_ID");
          PORT_MAP(_component,src ,"out_DCACHE_REQ_"+toString(i)+"_ADDRESS"  ,
                              dest,"out_DCACHE_REQ_"+toString(i)+"_ADDRESS"  );
          PORT_MAP(_component,src ,"out_DCACHE_REQ_"+toString(i)+"_WDATA"    ,
                              dest,"out_DCACHE_REQ_"+toString(i)+"_WDATA"    );
          PORT_MAP(_component,src ,"out_DCACHE_REQ_"+toString(i)+"_TYPE"     ,
                              dest,"out_DCACHE_REQ_"+toString(i)+"_TYPE"     );
        }

      // ~~~~~[ Interface "dcache_rsp" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
      for (uint32_t i=0; i<_nb_dcache_port; ++i)
        {
          dest = _name;
#ifdef POSITION
          _component->interface_map (src ,"dcache_rsp_"+toString(i),
                                     dest,"dcache_rsp_"+toString(i));
#endif

          PORT_MAP(_component,src , "in_DCACHE_RSP_"+toString(i)+"_VAL"      ,
                              dest, "in_DCACHE_RSP_"+toString(i)+"_VAL"      );
          PORT_MAP(_component,src ,"out_DCACHE_RSP_"+toString(i)+"_ACK"      ,
                              dest,"out_DCACHE_RSP_"+toString(i)+"_ACK"      );
          if (_have_port_dcache_thread_id)
          PORT_MAP(_component,src , "in_DCACHE_RSP_"+toString(i)+"_THREAD_ID",
                              dest, "in_DCACHE_RSP_"+toString(i)+"_THREAD_ID");
          if (_have_port_dcache_packet_id)
          PORT_MAP(_component,src , "in_DCACHE_RSP_"+toString(i)+"_PACKET_ID",
                              dest, "in_DCACHE_RSP_"+toString(i)+"_PACKET_ID");
          PORT_MAP(_component,src , "in_DCACHE_RSP_"+toString(i)+"_RDATA"    ,
                              dest, "in_DCACHE_RSP_"+toString(i)+"_RDATA"    );
          PORT_MAP(_component,src , "in_DCACHE_RSP_"+toString(i)+"_ERROR"    ,
                              dest, "in_DCACHE_RSP_"+toString(i)+"_ERROR"    );
        }

      // ~~~~~[ Interface "interrupt" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
      for (uint32_t i=0; i<_nb_thread; ++i)
        {
          dest = _name;
#ifdef POSITION
          _component->interface_map (src ,"interrupt_"+toString(i),
                                     dest,"interrupt_"+toString(i));
#endif

          PORT_MAP(_component,src , "in_INTERRUPT_"+toString(i)+"_ENABLE",
                              dest, "in_INTERRUPT_"+toString(i)+"_ENABLE");
        }
    }


    // ~~~~~[ Others ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     if (DEBUG_Morpheo == true)
       _component->test_map();

#ifdef POSITION
     if (usage_is_set(_usage,USE_POSITION))
       _component->generate_file();
#endif

     log_end(Morpheo,FUNCTION);
  };
}; // end namespace morpheo
