#ifdef SYSTEMC
/*
 * $Id: Commit_unit_genMealy_insert.cpp 100 2009-01-08 13:06:27Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Commit_unit/include/Commit_unit.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace commit_unit {


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

    Tcontrol_t bank_full         [_param->_nb_bank];
    Tcontrol_t insert_ack        [_param->_nb_rename_unit][_param->_max_nb_inst_insert];
#ifdef SYSTEMC_VHDL_COMPATIBILITY
    Tpacket_t  insert_packet_id  [_param->_nb_rename_unit][_param->_max_nb_inst_insert];
#endif
    bool       can_rename_select [_param->_nb_rename_unit];
    
    // Initialisation
    for (uint32_t i=0; i<_param->_nb_bank; i++)
      {
	internal_BANK_INSERT_VAL  [i] = false;
	bank_full [i] = not (_rob[i].size() < _param->_size_bank); 
      }
    for (uint32_t i=0; i<_param->_nb_rename_unit; i++)
      {
	can_rename_select [i] = true;
	for (uint32_t j=0; j<_param->_nb_inst_insert[i]; j++)
	  {
	    insert_ack       [i][j] = false;
#ifdef SYSTEMC_VHDL_COMPATIBILITY
	    insert_packet_id [i][j] = false;
#endif
	  }
      }

    // insert interface
//     log_printf(TRACE,Commit_unit,FUNCTION,"  * reg_NUM_BANK_TAIL : %d",reg_NUM_BANK_TAIL);

    std::list<generic::priority::select_t> * select_insert = _priority_insert ->select(); // same select for all insert
    std::list<generic::priority::select_t>::iterator it=select_insert ->begin();

    // Scan all bank ...
    for (uint32_t i=0; i<_param->_nb_bank; i++)
      {
	// compute the bank number (num_bank_tail is the older write slot)
	uint32_t num_bank = (reg_NUM_BANK_TAIL+i)%_param->_nb_bank;

// 	log_printf(TRACE,Commit_unit,FUNCTION,"  * BANK : %d", num_bank);
// 	log_printf(TRACE,Commit_unit,FUNCTION,"    * val  : %d", internal_BANK_INSERT_VAL [num_bank]);
// 	log_printf(TRACE,Commit_unit,FUNCTION,"    * full : %d", bank_full [num_bank]);

        // Scan all insert interface to find a valid transaction
	while (it!=select_insert ->end())
	  {
	    uint32_t num_rename_unit = it->grp;
	    uint32_t num_inst_insert = it->elt;

	    it++;

 	    log_printf(TRACE,Commit_unit,FUNCTION,"  * INSERT [%d][%d]", num_rename_unit,num_inst_insert);
//  	    log_printf(TRACE,Commit_unit,FUNCTION,"    * INSERT_VAL        : %d", PORT_READ(in_INSERT_VAL [num_rename_unit][num_inst_insert]));
 	    log_printf(TRACE,Commit_unit,FUNCTION,"    * can_rename_select : %d", can_rename_select [num_rename_unit]);

	    // Test if have instruction
            //   -> rename_unit_glue test the in-order insert !!!!!
	    if (can_rename_select [num_rename_unit] // and 
// 		PORT_READ(in_INSERT_VAL [num_rename_unit][num_inst_insert])
                )
	      {
                log_printf(TRACE,Commit_unit,FUNCTION,"      * have instruction");
                log_printf(TRACE,Commit_unit,FUNCTION,"      * bank_full : %d",bank_full [num_bank]);

		// test if bank is not busy (full or previous access)
		if (not bank_full [num_bank])
		  {
		    // find !!!
		    insert_ack       [num_rename_unit][num_inst_insert] = true;

		    Tpacket_t packet_id = ((num_bank << _param->_shift_num_bank) | reg_BANK_PTR [num_bank]);

#ifdef SYSTEMC_VHDL_COMPATIBILITY
		    insert_packet_id [num_rename_unit][num_inst_insert] = packet_id;
#else
		    if (_param->_have_port_rob_ptr  )
		    PORT_WRITE(out_INSERT_PACKET_ID [num_rename_unit][num_inst_insert],packet_id);
#endif
		    internal_BANK_INSERT_VAL             [num_bank] = true;
		    internal_BANK_INSERT_NUM_RENAME_UNIT [num_bank] = num_rename_unit;
		    internal_BANK_INSERT_NUM_INST        [num_bank] = num_inst_insert;
		    
		    break;
		  }
	      }
		
	    // is a valid instruction, but it's not send at a bank
	    //  ... invalid this rename_unit (because, insert in_order)
	    can_rename_select [num_rename_unit] = false;
	  }
      }
    
    // Write output
    for (uint32_t i=0; i<_param->_nb_rename_unit; i++)
      for (uint32_t j=0; j<_param->_nb_inst_insert[i]; j++)
	{
	  PORT_WRITE(out_INSERT_ACK       [i][j],insert_ack       [i][j]);
          log_printf(TRACE,Commit_unit,FUNCTION,"  * INSERT [%d][%d] -> ack %d",i,j,insert_ack[i][j]);

#ifdef SYSTEMC_VHDL_COMPATIBILITY
	  if (_param->_have_port_rob_ptr  )
	  PORT_WRITE(out_INSERT_PACKET_ID [i][j],insert_packet_id [i][j]);
#endif
	}
    
    log_end(Commit_unit,FUNCTION);
  };

}; // end namespace commit_unit
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core
}; // end namespace behavioural
}; // end namespace morpheo              
#endif
