#ifdef SYSTEMC
/*
 * $Id: Commit_unit_genMealy_insert.cpp 117 2009-05-16 14:42:39Z 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];
    bool       event_stop;
   
//     Initialisation
    event_stop = false; // one signal for all context.
    for (uint32_t i=0; i<_param->_nb_front_end; ++i)
      for (uint32_t j=0; j<_param->_nb_context[i]; ++j)
        event_stop |= reg_EVENT_STOP [i][j];
    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);

    if (not event_stop)
      {
        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 = ((reg_BANK_PTR [num_bank] << _param->_shift_num_slot) | 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
