#ifndef morpheo_behavioural_core_multi_execute_loop_execute_loop_multi_execute_unit_execute_unit_functionnal_unit_Types_h
#define morpheo_behavioural_core_multi_execute_loop_execute_loop_multi_execute_unit_execute_unit_functionnal_unit_Types_h

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

#ifdef SYSTEMC
#include "systemc.h"
#endif

#include "Common/include/BitManipulation.h"
#include "Behavioural/include/SPR_access_mode.h"
#include "Behavioural/include/Types.h"
#include "Behavioural/include/Parameters.h"

namespace morpheo {
namespace behavioural {
namespace core {
namespace multi_execute_loop {
namespace execute_loop {
namespace multi_execute_unit {
namespace execute_unit {
namespace functionnal_unit {

  class execute_timing_t
  {
    // if delay   > 0, can't accepted a transaction on EXECUTE_IN's  interface.
  public : uint32_t        _delay  ;
    // if latence > 0, can't initiate a transaction on EXECUTE_OUT's interface.
  public : uint32_t        _latence;

  public : execute_timing_t (uint32_t delay=0, uint32_t latence=0)
    {
      _delay   = delay;
      _latence = latence;
    };
  };

  typedef struct 
  {
    execute_timing_t   _timing      ;

    Tcontext_t         _context_id   ;
    Tcontext_t         _front_end_id ;
    Tcontext_t         _ooo_engine_id;
    Tpacket_t          _packet_id ;

    Toperation_t       _operation   ;
    Ttype_t            _type        ;
    Tcontrol_t         _has_immediat;
    Tgeneral_data_t    _immediat    ;
    Tgeneral_data_t    _data_ra     ;
    Tgeneral_data_t    _data_rb     ;
    Tspecial_data_t    _data_rc     ;
    Tgeneral_data_t    _data_rd     ;
    Tspecial_data_t    _data_re     ;

    Tcontrol_t         _write_rd  ;
    Tgeneral_address_t _num_reg_rd;
    Tcontrol_t         _write_re  ;
    Tspecial_address_t _num_reg_re;

    Texception_t       _exception   ;
    Tcontrol_t         _no_sequence ;
    Tgeneral_data_t    _address     ;
  } execute_operation_t;

  class execute_param_t
  {
  public : const uint32_t            _size_data;
  public : const Tgeneral_data_t     _mask_data;
  public : const Tgeneral_data_t     _mask_shift;
  public :       execute_timing_t ** _timing;

  public : execute_param_t (const uint32_t      size_data,
			    execute_timing_t ** timing):
    _size_data (size_data),
    _mask_data (gen_mask<Tgeneral_data_t> (size_data)),
    _mask_shift(gen_mask<Tgeneral_data_t> (log2(size_data)))
    {
      _timing = timing;
    };
  public : ~execute_param_t (void)
    {
    };
  } ;

  class execute_register_t
  {
    // information to custom group : 
    //  * perhalps a custom group start an operation after a access at a internal's group register
  public : bool               _i_read_spr;
  public : bool               _i_write_spr;
  public : uint32_t           _access_num_group;
  public : uint32_t           _access_num_register;
  public : Tgeneral_data_t    _spr_old;
  public : Tgeneral_data_t ** _spr;
  public : SPR_access_mode  * _spr_access_mode;
    
  public : execute_register_t (void)
    {
      _spr               = new Tgeneral_data_t * [NB_GROUP];
      _spr_access_mode   = new SPR_access_mode;
  
      for (uint32_t i=0; i<NB_GROUP; i++)
	{
	  _spr               [i] = NULL;
	}
    }

  public : ~execute_register_t (void)
    {
      for (uint32_t x=0; x<NB_GROUP; x++)
	if (_spr[x] != NULL)
	  delete _spr[x];
      delete _spr;
      delete _spr_access_mode;
    }

  public : void implement_group (uint32_t num_group, uint32_t nb_reg)
    {
      if ((num_group > NB_GROUP) or (_spr[num_group] != NULL))
	throw ERRORMORPHEO("execute_register_t::implement_group", "Invalid group number or this group is already implemented.");

      if (nb_reg > 0)
	{
	  _spr [num_group] = new Tgeneral_data_t [nb_reg];

	  if (num_group >= GROUP_CUSTOM_1)
	    _spr_access_mode ->implement_group(num_group, nb_reg);
	}
    }

  public : void implement_group (uint32_t num_group)
    {
      if ((num_group > NB_GROUP) or (_spr[num_group] != NULL))
	throw ERRORMORPHEO("execute_register_t::implement_group", "Invalid group number or this group is already implemented.");

      uint32_t nb_reg = _spr_access_mode ->implement_group(num_group);

      if (nb_reg > 0)
	_spr [num_group] = new Tgeneral_data_t [nb_reg];
    }
  };
  
  typedef void function_execute_t 
  (morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_operation_t *, 
   morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_register_t  *,
   morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_param_t     *);
  
  typedef void function_execute_end_cycle_t 
  (morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_register_t  *,
   morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_param_t     *);

  
}; // end namespace functionnal_unit
}; // end namespace execute_unit
}; // end namespace multi_execute_unit
}; // end namespace execute_loop
}; // end namespace multi_execute_loop
}; // end namespace core
}; // end namespace behavioural
}; // end namespace morpheo              
#endif
