#ifdef SYSTEMC
/*
 * $Id: Load_Store_pointer_unit_transition.cpp 110 2009-02-19 16:31:47Z rosiere $
 *
 * [ 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_begin(Load_Store_pointer_unit,FUNCTION);
    log_function(Load_Store_pointer_unit,FUNCTION,_name.c_str());

    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;
		  }
		}	
	    }
      }

    // ===================================================================
    // =====[ OTHER ]=====================================================
    // ===================================================================

#if (DEBUG >= DEBUG_TRACE) and (DEBUG_Commit_unit == true)
    {
      log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"  * Dump Load_Store_pointer Unit");
      
      for (uint32_t i=0; i<_param->_nb_load_store_queue; ++i)
        {
          log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"    * Load_Store_unit [%d]",i);
          log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"      * reg_STORE_QUEUE_NB_USE    : %d", reg_STORE_QUEUE_NB_USE   [i]);
          log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"      * reg_STORE_QUEUE_PTR_WRITE : %d", reg_STORE_QUEUE_PTR_WRITE[i]);
          log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"      * reg_STORE_QUEUE_USE       :");
          for (uint32_t j=0; j<_param->_size_store_queue [i]; ++j)
          log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"        [%d] %d",j,reg_STORE_QUEUE_USE [i][j]);
          log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"      * reg_LOAD_QUEUE_PTR_WRITE  : %d", reg_LOAD_QUEUE_PTR_WRITE [i]);
          log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"      * reg_LOAD_QUEUE_USE        :");
          for (uint32_t j=0; j<_param->_size_load_queue [i]; ++j)
          log_printf(TRACE,Load_Store_pointer_unit,FUNCTION,"        [%d] %d",j,reg_LOAD_QUEUE_USE [i][j]);
        }
    }
#endif

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

    log_end(Load_Store_pointer_unit,FUNCTION);
  };

}; // 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
