#ifdef SYSTEMC
/*
 * $Id: Free_List_unit_genMealy_pop.cpp 109 2009-02-16 20:28:31Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Rename_unit/Register_translation_unit/Free_List_unit/include/Free_List_unit.h"

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


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

    std::list<generic::priority::select_t> * select_gpr = _priority_gpr->select();
    std::list<generic::priority::select_t>::iterator it_gpr=select_gpr->begin();

    std::list<generic::priority::select_t> * select_spr = _priority_spr->select();
    std::list<generic::priority::select_t>::iterator it_spr=select_spr->begin();

    for (uint32_t i=0; i<_param->_nb_pop; i++)
      {
        log_printf(TRACE,Free_List_unit,FUNCTION,"  * POP [%d]",i);
        
	// GPR
	bool gpr_ack = not PORT_READ(in_POP_GPR_VAL[i]);
        
        log_printf(TRACE,Free_List_unit,FUNCTION,"    * GPR_VAL : %d",PORT_READ(in_POP_GPR_VAL[i]));
        
	if (not gpr_ack)
          {
            // scan all bank
            for (;
                 it_gpr!=select_gpr->end();
                 ++it_gpr)
              {
                uint32_t num_bank = it_gpr->grp;
                
                log_printf(TRACE,Free_List_unit,FUNCTION,"    * num_bank: %d",num_bank);
                
                if (not _gpr_list[num_bank].empty())
                  {
                    // find
                    log_printf(TRACE,Free_List_unit,FUNCTION,"    * find    : %d",_gpr_list[num_bank].front());
                    
                    gpr_ack = true;
                    internal_POP_GPR_BANK [i] = num_bank;
                    PORT_WRITE(out_POP_GPR_NUM_REG [i],
                               //(num_bank << _param->_shift) | // only in VHDL
                               _gpr_list[num_bank].front());
                  
                    ++it_gpr;
                    break;
                  }
              }
          }

	// SPR
	bool spr_ack = not PORT_READ(in_POP_SPR_VAL[i]);
        
        log_printf(TRACE,Free_List_unit,FUNCTION,"    * SPR_VAL : %d",PORT_READ(in_POP_SPR_VAL[i]));
        
	if (not spr_ack)
          {
            // scan all bank
            for (;
                 it_spr!=select_spr->end();
                 ++it_spr)
              {
                uint32_t num_bank = it_spr->grp;
                
                log_printf(TRACE,Free_List_unit,FUNCTION,"    * num_bank: %d",num_bank);
                
                if (not _spr_list[num_bank].empty())
                  {
                    // find
                    log_printf(TRACE,Free_List_unit,FUNCTION,"    * find    : %d",_spr_list[num_bank].front());
                    
                    spr_ack = true;
                    internal_POP_SPR_BANK [i] = num_bank;
                    PORT_WRITE(out_POP_SPR_NUM_REG [i],
                               //(num_bank << _param->_shift) | // only in VHDL
                               _spr_list[num_bank].front());
                  
                    ++it_spr;
                    break;
                  }
              }
          }


	internal_POP_ACK [i] = gpr_ack and spr_ack;
	PORT_WRITE(out_POP_ACK [i], internal_POP_ACK [i]);
      }

//     for (uint32_t i=0; i<_param->_nb_pop; i++)
//       {
//         log_printf(TRACE,Free_List_unit,FUNCTION,"  * POP [%d]",i);
        
//  	uint32_t offset = (i*_param->_nb_bank_by_pop) + reg_BANK_PRIORITY;

// 	// GPR
// 	bool gpr_ack = not PORT_READ(in_POP_GPR_VAL[i]);

//         log_printf(TRACE,Free_List_unit,FUNCTION,"    * GPR_VAL : %d",PORT_READ(in_POP_GPR_VAL[i]));

// 	if (not gpr_ack)
//           {
//             for (uint32_t j=0; j<_param->_nb_bank_by_pop; j++)
//               {
//                 uint32_t bank = (offset+((j+reg_BANK_BY_POP_PRIORITY)%_param->_nb_bank_by_pop))%_param->_nb_bank;
                
//                 log_printf(TRACE,Free_List_unit,FUNCTION,"    * bank    : %d",bank);
                
//                 if (not _gpr_list[bank].empty())
//                   {
//                     // find
//                     log_printf(TRACE,Free_List_unit,FUNCTION,"    * find    : %d",_gpr_list[bank].front());
                    
//                     gpr_ack = true;
//                     internal_POP_GPR_BANK [i] = bank;
//                     PORT_WRITE(out_POP_GPR_NUM_REG [i],
//                                //(bank << _param->_shift) | // only in VHDL
//                                _gpr_list[bank].front());
                    
//                     break;
//                   }
//               }
//           }

// 	// SPR
// 	bool spr_ack = not PORT_READ(in_POP_SPR_VAL[i]);
        
//         log_printf(TRACE,Free_List_unit,FUNCTION,"    * SPR_VAL : %d",PORT_READ(in_POP_SPR_VAL[i]));
        
// 	if (not spr_ack)
//           {
//             uint32_t offset = (i*_param->_nb_bank_by_pop) + reg_BANK_PRIORITY;

//             for (uint32_t j=0; j<_param->_nb_bank_by_pop; j++)
//               {
//                 uint32_t bank = (offset+((j+reg_BANK_BY_POP_PRIORITY)%_param->_nb_bank_by_pop))%_param->_nb_bank;
                
//                 log_printf(TRACE,Free_List_unit,FUNCTION,"    * bank    : %d",bank);
                
//                 if (not _spr_list[bank].empty())
//                   {
//                     // find
//                     log_printf(TRACE,Free_List_unit,FUNCTION,"    * find    : %d",_spr_list[bank].front());
                    
//                     spr_ack = true;
//                     internal_POP_SPR_BANK [i] = bank;
//                     PORT_WRITE(out_POP_SPR_NUM_REG [i],
//                                //(bank << _param->_shift) | // only in VHDL
//                                _spr_list[bank].front());
                    
//                     break;
//                   }
//               }
//           }

// 	internal_POP_ACK [i] = gpr_ack and spr_ack;
	
// 	PORT_WRITE(out_POP_ACK [i], internal_POP_ACK [i]);
//       }
    

    log_end(Free_List_unit,FUNCTION);
  };

}; // end namespace free_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
