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

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Rename_unit/Load_Store_pointer_unit/include/Load_Store_pointer_unit.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace rename_unit {
namespace load_store_pointer_unit {


#undef  FUNCTION
#define FUNCTION "Load_Store_pointer_unit::transition"
  void Load_Store_pointer_unit::transition (void)
  {
    log_printf(FUNC,Load_Store_pointer_unit,FUNCTION,"Begin");

    if (PORT_READ(in_NRESET) == 0)
      {
	for (uint32_t i=0; i<_param->_nb_load_store_queue; i++)
	  {
	    reg_STORE_QUEUE_PTR_WRITE [i] = 0;
	    reg_STORE_QUEUE_NB_USE    [i] = 0;
	    reg_LOAD_QUEUE_PTR_WRITE  [i] = 0;
	    
	    for (uint32_t j=0; j<_param->_size_store_queue[i]; j++)
	      reg_STORE_QUEUE_USE [i][j] = false;
	    for (uint32_t j=0; j<_param->_size_load_queue[i]; j++)
	      reg_LOAD_QUEUE_USE  [i][j] = false;
	  }
      }
    else
      {
	// =====================================================
	// =====[ INSERT ]======================================
	// =====================================================
	
	for (uint32_t i=0; i<_param->_nb_inst_insert; i++)
	  if (PORT_READ(in_INSERT_VAL [i]) and internal_INSERT_ACK [i])
	    {
// 	      log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"INSERT [%d]",i);
	      
	      switch (internal_INSERT_OPERATION_USE [i])
		{
		case OPERATION_USE_STORE_QUEUE :
		  {
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * use STORE_QUEUE");

		    uint32_t   lsq = internal_INSERT_LSQ [i];
		    Tlsq_ptr_t ptr = internal_INSERT_PTR [i];

// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * lsq : %d",lsq);
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * ptr : %d",ptr);

		    reg_STORE_QUEUE_PTR_WRITE [lsq]      = (ptr+1)%_param->_size_store_queue[lsq];
		    reg_STORE_QUEUE_NB_USE    [lsq]      ++;
		    reg_STORE_QUEUE_USE       [lsq][ptr] = true;

		    break;
		  }
		case OPERATION_USE_LOAD_QUEUE :
		  {
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * use LOAD_QUEUE");

		    uint32_t   lsq = internal_INSERT_LSQ [i];
		    Tlsq_ptr_t ptr = internal_INSERT_PTR [i];
		    
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * lsq : %d",lsq);
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * ptr : %d",ptr);

		    reg_LOAD_QUEUE_PTR_WRITE [lsq]      = (ptr+1)%_param->_size_load_queue[lsq];
		    reg_LOAD_QUEUE_USE       [lsq][ptr] = true;

		    break;
		  }
		default :
		  {
		    break;
		  }
		}
	    }
		
	// =====================================================
	// =====[ RETIRE ]======================================
	// =====================================================
	for (uint32_t i=0; i<_param->_nb_inst_retire; i++)
	  if (PORT_READ(in_RETIRE_VAL [i]) and internal_RETIRE_ACK [i])
	    {
// 	      log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"RETIRE [%d]",i);

	      switch (internal_RETIRE_OPERATION_USE [i])
		{
		case OPERATION_USE_STORE_QUEUE :
		  {
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * use STORE_QUEUE");

		    uint32_t   lsq = internal_RETIRE_LSQ [i];
		    Tlsq_ptr_t ptr = internal_RETIRE_PTR [i];

// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * lsq : %d",lsq);
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * ptr : %d",ptr);
		    
// 		    reg_STORE_QUEUE_PTR_WRITE [lsq]      = ((ptr==0)?_param->_size_store_queue[lsq]:ptr)-1;
		    reg_STORE_QUEUE_NB_USE    [lsq]      --;
		    reg_STORE_QUEUE_USE       [lsq][ptr] = false;

		    break;
		  }
		case OPERATION_USE_LOAD_QUEUE :
		  {
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * use LOAD_QUEUE");

		    uint32_t   lsq = internal_RETIRE_LSQ [i];
		    Tlsq_ptr_t ptr = internal_RETIRE_PTR [i];
		    
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * lsq : %d",lsq);
// 		    log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * ptr : %d",ptr);
		    
// 		    reg_LOAD_QUEUE_PTR_WRITE [lsq]      = ((ptr==0)?_param->_size_load_queue[lsq]:ptr)-1;
		    reg_LOAD_QUEUE_USE       [lsq][ptr] = false;
		    
		    break;
		  }
		default :
		  {
		    break;
		  }
		}	
	    }
      }


//     for (uint32_t i=0; i<_param->_nb_load_store_queue; i++)
//       {
// 	std::string str;

// 	log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"LOAD_STORE_QUEUE [%d]",i);

// 	log_printf(TRACE,Load_Store_pointer_unit,FUNCTION," * STORE_QUEUE_PTR_WRITE : %d",reg_STORE_QUEUE_PTR_WRITE [i]);
// 	log_printf(TRACE,Load_Store_pointer_unit,FUNCTION," * STORE_QUEUE_NB_USE    : %d",reg_STORE_QUEUE_NB_USE    [i]);

// 	str = "";
// 	for (uint32_t j=0; j<_param->_size_store_queue[i]; j++)
// 	  str += toString(reg_STORE_QUEUE_USE [i][j]) + " ";
// 	log_printf(TRACE,Load_Store_pointer_unit,FUNCTION," * %s",str.c_str());
	
// 	log_printf(TRACE,Load_Store_pointer_unit,FUNCTION," * LOAD_QUEUE_PTR_WRITE  : %d",reg_LOAD_QUEUE_PTR_WRITE [i]);

// 	str = "";
// 	for (uint32_t j=0; j<_param->_size_load_queue[i]; j++)
// 	  str += toString(reg_LOAD_QUEUE_USE [i][j]) + " ";
// 	log_printf(TRACE,Load_Store_pointer_unit,FUNCTION," * %s",str.c_str());
//       }

#if defined(STATISTICS) or defined(VHDL_TESTBENCH)
    end_cycle ();
#endif

    log_printf(FUNC,Load_Store_pointer_unit,FUNCTION,"End");
  };

}; // end namespace load_store_pointer_unit
}; // end namespace rename_unit
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core

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