#ifdef SYSTEMC
/*
 * $Id: Stat_List_unit_genMoore.cpp 123 2009-06-08 20:43:30Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Rename_unit/Register_translation_unit/Stat_List_unit/include/Stat_List_unit.h"
#include <set>

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace rename_unit {
namespace register_translation_unit {
namespace stat_list_unit {

#define STAT_LIST_SCAN_ALL

#undef  FUNCTION
#define FUNCTION "Stat_List_unit::genMoore"
  void Stat_List_unit::genMoore (void)
  {
    log_begin(Stat_List_unit,FUNCTION);
    log_function(Stat_List_unit,FUNCTION,_name.c_str());

    if (PORT_READ(in_NRESET))
      {
    uint32_t  gpr_ptr = reg_GPR_PTR_FREE;
    uint32_t  spr_ptr = reg_SPR_PTR_FREE;
#ifdef STAT_LIST_SCAN_ALL
    std::set<Tgeneral_address_t> list_gpr_free;
    std::set<Tspecial_address_t> list_spr_free;
#endif

    for (uint32_t i=0; i<_param->_nb_reg_free; i++)
      {
        log_printf(TRACE,Stat_List_unit,FUNCTION,"  * PUSH [%d]",i);
          
	uint32_t offset  = i*_param->_nb_bank_by_port_free;

	// PUSH_GPR
	{
	  bool     val      = false;
	  uint32_t bank_gpr = offset;

#ifdef STAT_LIST_SCAN_ALL
          for (uint32_t _gpr_ptr=0;  _gpr_ptr<_param->_nb_general_register_by_bank; ++_gpr_ptr)
            {
              gpr_ptr = (gpr_ptr+1)%_param->_nb_general_register_by_bank;
#endif	  
              for (bank_gpr = offset; bank_gpr<offset+_param->_nb_bank_by_port_free; bank_gpr++)
                if (gpr_stat_list[bank_gpr][gpr_ptr].can_free())
                  {
#ifdef STAT_LIST_SCAN_ALL
                    Tgeneral_address_t num_reg = ((bank_gpr<<_param->_shift_gpr) | gpr_ptr);
                    if (list_gpr_free.find(num_reg) == list_gpr_free.end())
                      {
                        list_gpr_free.insert(num_reg);
#endif
                        val = true;
                        break;
#ifdef STAT_LIST_SCAN_ALL
                      }
#endif
                  }
#ifdef STAT_LIST_SCAN_ALL
              if (val)
                break;
            }
#endif	  

          log_printf(TRACE,Stat_List_unit,FUNCTION,"    * val      : %d",val);
          log_printf(TRACE,Stat_List_unit,FUNCTION,"    * bank_gpr : %d",bank_gpr);
          log_printf(TRACE,Stat_List_unit,FUNCTION,"    * gpr_ptr  : %d",gpr_ptr);
          log_printf(TRACE,Stat_List_unit,FUNCTION,"    * num_reg  : %d",((bank_gpr<<_param->_shift_gpr) | gpr_ptr));

	  internal_PUSH_GPR_VAL      [i] = val;
	  internal_PUSH_GPR_NUM_BANK [i] = bank_gpr;
	  internal_PUSH_GPR_NUM_REG  [i] = gpr_ptr ;

	  if (val)
	    PORT_WRITE(out_PUSH_GPR_NUM_REG[i], ((bank_gpr<<_param->_shift_gpr) | gpr_ptr));
	}

	// PUSH_SPR
	{
	  bool     val      = false;
	  uint32_t bank_spr = offset;

#ifdef STAT_LIST_SCAN_ALL
          for (uint32_t _spr_ptr=0;  _spr_ptr<_param->_nb_special_register_by_bank; ++_spr_ptr)
            {
              spr_ptr = (spr_ptr+1)%_param->_nb_special_register_by_bank;
#endif	  
              for (bank_spr = offset; bank_spr<offset+_param->_nb_bank_by_port_free; bank_spr++)
                if (spr_stat_list[bank_spr][spr_ptr].can_free())
                  {
#ifdef STAT_LIST_SCAN_ALL
                    Tspecial_address_t num_reg = ((bank_spr<<_param->_shift_spr) | spr_ptr);
                    if (list_spr_free.find(num_reg) == list_spr_free.end())
                      {
                        list_spr_free.insert(num_reg);
#endif
                        val = true;
                        break;
#ifdef STAT_LIST_SCAN_ALL
                      }
#endif
                  }
#ifdef STAT_LIST_SCAN_ALL
              if (val)
                break;
            }
#endif	  

          log_printf(TRACE,Stat_List_unit,FUNCTION,"    * val      : %d",val);
          log_printf(TRACE,Stat_List_unit,FUNCTION,"    * bank_spr : %d",bank_spr);
          log_printf(TRACE,Stat_List_unit,FUNCTION,"    * spr_ptr  : %d",spr_ptr);
          log_printf(TRACE,Stat_List_unit,FUNCTION,"    * num_reg  : %d",((bank_spr<<_param->_shift_spr) | spr_ptr));

	  internal_PUSH_SPR_VAL      [i] = val;
	  internal_PUSH_SPR_NUM_BANK [i] = bank_spr;
	  internal_PUSH_SPR_NUM_REG  [i] = spr_ptr ;

	  if (val)
	    PORT_WRITE(out_PUSH_SPR_NUM_REG[i], ((bank_spr<<_param->_shift_spr) | spr_ptr));
	}


      }
      }
    else
      {
        for (uint32_t i=0; i<_param->_nb_reg_free; i++)
          {
            internal_PUSH_GPR_VAL      [i] = 0;
//          internal_PUSH_GPR_NUM_BANK [i] = bank_gpr;
//          internal_PUSH_GPR_NUM_REG  [i] = gpr_ptr ;
            internal_PUSH_SPR_VAL      [i] = 0;
// 	    internal_PUSH_SPR_NUM_BANK [i] = bank_spr;
// 	    internal_PUSH_SPR_NUM_REG  [i] = spr_ptr ;
          }
      }

    for (uint32_t i=0; i<_param->_nb_reg_free; i++)
      {
        PORT_WRITE(out_PUSH_GPR_VAL [i], internal_PUSH_GPR_VAL      [i]);
        PORT_WRITE(out_PUSH_SPR_VAL [i], internal_PUSH_SPR_VAL      [i]);
      }
  
    log_end(Stat_List_unit,FUNCTION);
  };

}; // end namespace stat_list_unit
}; // end namespace register_translation_unit
}; // end namespace rename_unit
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core

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