/*
 * $Id: Special_Register_unit_allocation.cpp 98 2008-12-31 10:18:08Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Special_Register_unit/include/Special_Register_unit.h"
#include "Behavioural/include/Allocation.h"
#include "Common/include/Max.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace special_register_unit {



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

    _component   = new Component (_usage);

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

    _interfaces = entity->set_interfaces();

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

    // ~~~~~[ Interface : "spr_access" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC1_INTERFACE("spr_access",IN,WEST, _("Access from reexecute_unit"), _param->_nb_inst_reexecute);

      ALLOC1_VALACK_IN ( in_SPR_ACCESS_VAL           ,VAL);
      ALLOC1_VALACK_OUT(out_SPR_ACCESS_ACK           ,ACK);
      ALLOC1_SIGNAL_IN ( in_SPR_ACCESS_WEN           ,"wen"         ,Tcontrol_t         ,1);
      ALLOC1_SIGNAL_IN ( in_SPR_ACCESS_CONTEXT_ID    ,"context_id"  ,Tcontext_t         ,_param->_size_context_id  );
      ALLOC1_SIGNAL_IN ( in_SPR_ACCESS_FRONT_END_ID  ,"front_end_id",Tcontext_t         ,_param->_size_front_end_id);
      ALLOC1_SIGNAL_IN ( in_SPR_ACCESS_NUM_GROUP     ,"num_group"   ,Tspr_address_t     ,_param->_size_special_address_group   );
      ALLOC1_SIGNAL_IN ( in_SPR_ACCESS_NUM_REG       ,"num_reg"     ,Tspr_address_t     ,_param->_size_special_address_register);
      ALLOC1_SIGNAL_IN ( in_SPR_ACCESS_WDATA         ,"wdata"       ,Tspr_t             ,_param->_size_spr);
      ALLOC1_SIGNAL_OUT(out_SPR_ACCESS_RDATA         ,"rdata"       ,Tspr_t             ,_param->_size_spr);
      ALLOC1_SIGNAL_OUT(out_SPR_ACCESS_INVALID       ,"invalid"     ,Tcontrol_t         ,1);
    }

    // ~~~~~[ Interface : "spr_read" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC2_INTERFACE("spr_read",OUT,WEST, _("Output for a spr bit field."), _param->_nb_front_end, _param->_nb_context[it1]);

      _ALLOC2_SIGNAL_OUT(out_SPR_READ_SR             ,"sr",Tspr_t,_param->_size_spr, _param->_nb_front_end, _param->_nb_context[it1]);
    }

    // ~~~~~[ Interface : "spr_commit" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC2_INTERFACE("spr_commit",IN,WEST, _("Commit instruction to change SR's flags."), _param->_nb_front_end, _param->_nb_context[it1]);

      _ALLOC2_VALACK_IN ( in_SPR_COMMIT_VAL           ,VAL,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_VALACK_OUT(out_SPR_COMMIT_ACK           ,ACK,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_COMMIT_SR_F_VAL      ,"sr_f_val"     ,Tcontrol_t         ,1,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_COMMIT_SR_F          ,"sr_f"         ,Tcontrol_t         ,1,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_COMMIT_SR_CY_VAL     ,"sr_cy_val"    ,Tcontrol_t         ,1,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_COMMIT_SR_CY         ,"sr_cy"        ,Tcontrol_t         ,1,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_COMMIT_SR_OV_VAL     ,"sr_ov_val"    ,Tcontrol_t         ,1,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_COMMIT_SR_OV         ,"sr_ov"        ,Tcontrol_t         ,1,_param->_nb_front_end, _param->_nb_context[it1]);
    }

    // ~~~~~[ Interface "spr_event" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {
      ALLOC2_INTERFACE("spr_event",IN,WEST, _("Event change a lot of exception."), _param->_nb_front_end, _param->_nb_context[it1]);

      _ALLOC2_VALACK_IN ( in_SPR_EVENT_VAL            ,VAL,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_VALACK_OUT(out_SPR_EVENT_ACK            ,ACK,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_EVENT_EPCR          ,"EPCR"          ,Tspr_t            ,_param->_size_spr,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_EVENT_EEAR_WEN      ,"EEAR_WEN"      ,Tcontrol_t        ,1                ,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_EVENT_EEAR          ,"EEAR"          ,Tspr_t            ,_param->_size_spr,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_EVENT_SR_DSX        ,"SR_DSX"        ,Tcontrol_t        ,1                ,_param->_nb_front_end, _param->_nb_context[it1]);
      _ALLOC2_SIGNAL_IN ( in_SPR_EVENT_SR_TO_ESR     ,"SR_TO_ESR"     ,Tcontrol_t        ,1                ,_param->_nb_front_end, _param->_nb_context[it1]);
    }

    if (usage_is_set(_usage,USE_SYSTEMC))
      {
    // ~~~~~[ Internal ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    internal_SPR_ACCESS_ACK = new Tcontrol_t   [_param->_nb_inst_reexecute];
    internal_SPR_COMMIT_ACK = new Tcontrol_t * [_param->_nb_front_end];
    internal_SPR_EVENT_ACK  = new Tcontrol_t * [_param->_nb_front_end];
    for (uint32_t i=0; i<_param->_nb_front_end; i++)
      {
        internal_SPR_COMMIT_ACK [i]  = new Tcontrol_t [_param->_nb_context [i]];
        internal_SPR_EVENT_ACK  [i]  = new Tcontrol_t [_param->_nb_context [i]];
      }
      }

    // ~~~~~[ Component ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    _spr_access_mode = new SPR_access_mode ** [_param->_nb_front_end];
    for (uint32_t i=0; i<_param->_nb_front_end; i++)
      {
	_spr_access_mode [i] = new SPR_access_mode * [_param->_nb_context[i]];

	for (uint32_t j=0; j<_param->_nb_context[i]; j++)
	  {
	    _spr_access_mode [i][j] = new SPR_access_mode;

	    for (uint32_t k=0; k<NB_GROUP; k++)
	      if (_param->_implement_group [i][j][k])
		_spr_access_mode [i][j]->implement_group(k);
	  }
      }

    _spr = new SPR **** [_param->_nb_front_end];
    for (uint32_t i=0; i<_param->_nb_front_end; i++)
      {
	_spr [i] = new SPR *** [_param->_nb_context[i]];

	for (uint32_t j=0; j<_param->_nb_context[i]; j++)
	  {
	    _spr [i][j] = new SPR ** [NB_GROUP];

	    for (uint32_t k=0; k<NB_GROUP; k++)
	      if (_param->_implement_group [i][j][k])
		{
		  _spr [i][j][k] = new SPR * [NB_REG_GROUP[k]];
                  
                  for (uint32_t l=0; l<NB_REG_GROUP[k]; l++)
                    _spr [i][j][k][l] = NULL;
                  
		  switch (k)
		    {
		    case GROUP_SYSTEM_AND_CONTROL  :
		      {
			_spr [i][j][k][SPR_VR          ] = new VR          (i,j,_param);
			_spr [i][j][k][SPR_UPR         ] = new UPR         (i,j,_param);
			_spr [i][j][k][SPR_CPUCFGR     ] = new CPUCFGR     (i,j,_param);
			_spr [i][j][k][SPR_DMMUCFGR    ] = new DMMUCFGR    (i,j,_param);
			_spr [i][j][k][SPR_IMMUCFGR    ] = new IMMUCFGR    (i,j,_param);
			_spr [i][j][k][SPR_DCCFGR      ] = new DCCFGR      (i,j,_param);
			_spr [i][j][k][SPR_ICCFGR      ] = new ICCFGR      (i,j,_param);
			_spr [i][j][k][SPR_DCFGR       ] = new DCFGR       (i,j,_param);
			_spr [i][j][k][SPR_PCCFGR      ] = new PCCFGR      (i,j,_param);
			_spr [i][j][k][SPR_NPC         ] = new NPC         (i,j,_param);
			_spr [i][j][k][SPR_SR          ] = new SR          (i,j,_param);
			_spr [i][j][k][SPR_PPC         ] = new PPC         (i,j,_param);
			_spr [i][j][k][SPR_CID         ] = new CID         (i,j,_param);
			_spr [i][j][k][SPR_FPCSR       ] = new FPCSR       (i,j,_param);
			_spr [i][j][k][SPR_EPCR        ] = new EPCR        (i,j,_param);
			_spr [i][j][k][SPR_EEAR        ] = new EEAR        (i,j,_param);
			_spr [i][j][k][SPR_ESR         ] = new ESR         (i,j,_param);
// 			_spr [i][j][k][SPR_GPR         ] = new GPR         (i,j,_param);
			
			break;
		      }
		    case GROUP_DCACHE              :
		      {
			_spr [i][j][k][SPR_DCCR        ] = new DCCR        (i,j,_param);
			_spr [i][j][k][SPR_DCBPR       ] = new DCBPR       (i,j,_param);
			_spr [i][j][k][SPR_DCBFR       ] = new DCBFR       (i,j,_param);
			_spr [i][j][k][SPR_DCBIR       ] = new DCBIR       (i,j,_param);
			_spr [i][j][k][SPR_DCBWR       ] = new DCBWR       (i,j,_param);
			_spr [i][j][k][SPR_DCBLR       ] = new DCBLR       (i,j,_param);

			break;
		      }
		    case GROUP_DMMU                :
		    case GROUP_IMMU                :
		    case GROUP_ICACHE              :
		    case GROUP_DEBUG               :
		    case GROUP_PERFORMANCE_COUNTER :
		    case GROUP_POWER_MANAGEMENT    :
		    case GROUP_PIC                 :
		    case GROUP_TICK_TIMER          :
		    case GROUP_FLOATING_POINT      :

		    case GROUP_MAC                 :
		    case GROUP_RESERVED_1          :
		    case GROUP_RESERVED_2          :
		    case GROUP_RESERVED_3          :
		    case GROUP_RESERVED_4          :
		    case GROUP_RESERVED_5          :
		    case GROUP_RESERVED_6          :
		    case GROUP_RESERVED_7          :
		    case GROUP_RESERVED_8          :
		    case GROUP_RESERVED_9          :
		    case GROUP_RESERVED_10         :
		    case GROUP_RESERVED_11         :
		    case GROUP_RESERVED_12         :
		    case GROUP_CUSTOM_1            :
		    case GROUP_CUSTOM_2            :
		    case GROUP_CUSTOM_3            :
		    case GROUP_CUSTOM_4            :
		    case GROUP_CUSTOM_5            :
		    case GROUP_CUSTOM_6            :
		    case GROUP_CUSTOM_7            :
		    case GROUP_CUSTOM_8            :
		    default :
		      {
		      }
		    }
		}
	      else
		_spr [i][j][k] = NULL;
	  }
      }
    
    for (uint32_t i=0; i<_param->_nb_front_end; i++)
      for (uint32_t j=0; j<_param->_nb_context[i]; j++)
	for (uint32_t k=0; k<NB_GROUP; k++)
	  if (_param->_implement_group [i][j][k])
            {
              for (uint32_t l=0; l<NB_REG_GROUP[k]; l++)
                if (_spr [i][j][k][l] == NULL)
                  _spr_access_mode [i][j]->invalid_register (k,l);
            }
          else
            {
              for (uint32_t l=0; l<NB_REG_GROUP[k]; l++)
                _spr_access_mode [i][j]->invalid_register (k,l);
            }

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

    log_end(Special_Register_unit,FUNCTION);
  };

}; // end namespace special_register_unit
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core

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