#ifdef SYSTEMC
/*
 * $Id: Issue_queue_genMealy.cpp 88 2008-12-10 18:31:39Z rosiere $
 *
 * [ Description ]
 * 
 */

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

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace issue_queue {


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

    Tcontrol_t bank_full         [_param->_nb_bank];
    Tcontrol_t issue_ack         [_param->_nb_rename_unit][_param->_max_nb_inst_rename];
    Tcontrol_t reexecute_ack     [_param->_nb_inst_reexecute];
    bool       can_rename_select [_param->_nb_rename_unit];
    
    // Initialisation
    for (uint32_t i=0; i<_param->_nb_bank; i++)
      {
	internal_BANK_IN_ACK  [i] = false;
	bank_full [i] = not (_issue_queue[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_rename[i]; j++)
	  issue_ack [i][j] = false;
      }
    for (uint32_t i=0; i<_param->_nb_inst_reexecute; i++)
      reexecute_ack [i] = false;
    
    std::list<generic::priority::select_t> * select_reg = _priority_reg->select(); // same select for all issue

    // Priority at the Reexecute instruction !
    for (uint32_t i=0; i<_param->_nb_inst_reexecute; i++)
      // Test if have instruction
      if (PORT_READ(in_REEXECUTE_VAL [i]))
	{
	  Ttype_t type = PORT_READ(in_REEXECUTE_TYPE [i]);
	  
	  // scan all bank
	  for (std::list<generic::priority::select_t>::iterator it=select_reg->begin();
	       it!=select_reg->end();
	       it++)
	    {
	      uint32_t num_bank  = it->grp;
	      uint32_t num_issue = num_bank/_param->_nb_bank_select_out;
	      // test if bank is not busy (full or previous access) and if type match
	      if (not internal_BANK_IN_ACK [num_bank] and not bank_full [num_bank] and _param->_table_issue_type[num_issue][type])
		{
		  // find
		  reexecute_ack [i] = true;
		  internal_BANK_IN_ACK          [num_bank] = true;
		  internal_BANK_IN_IS_REEXECUTE [num_bank] = 1;
		  internal_BANK_IN_NUM_INST     [num_bank] = i;
		  break;
		}
	    }
	}
    
    // issue_in interface
    std::list<generic::priority::select_t> * select_in = _priority_in ->select(); // same select for all issue
    for (std::list<generic::priority::select_t>::iterator it=select_in ->begin();
	 it!=select_in ->end();
	 it++)
      {
	uint32_t num_rename_unit = it->grp;
	uint32_t num_inst_rename = it->elt;

        // Test if have instruction 
	if (can_rename_select [num_rename_unit]//  and 
// 	    PORT_READ(in_ISSUE_IN_VAL [num_rename_unit][num_inst_rename])
            )
	  {
	    Ttype_t type = PORT_READ(in_ISSUE_IN_TYPE [num_rename_unit][num_inst_rename]);
	  
	    // scan all bank
	    for (std::list<generic::priority::select_t>::iterator it=select_reg->begin();
		 it!=select_reg->end();
		 it++)
	      {
		uint32_t num_bank  = it->grp;
		uint32_t num_issue = num_bank/_param->_nb_bank_select_out;
		// test if bank is not busy (full or previous access) and if type match
		if (not internal_BANK_IN_ACK [num_bank] and not bank_full [num_bank] and _param->_table_issue_type[num_issue][type])
		  {
		    // find
		    issue_ack [num_rename_unit][num_inst_rename] = true;
		    internal_BANK_IN_ACK             [num_bank] = true;
		    internal_BANK_IN_IS_REEXECUTE    [num_bank] = 0;
		    internal_BANK_IN_NUM_RENAME_UNIT [num_bank] = num_rename_unit;
		    internal_BANK_IN_NUM_INST        [num_bank] = num_inst_rename;
		    break;
		  }
	      }

	    // is a valid instruction, but it's not send at a bank
	    //  ... invalid this rename_unit (because, rename in_order)
	    can_rename_select [num_rename_unit] |= issue_ack [num_rename_unit][num_inst_rename];
	  }
      }
    
    for (uint32_t i=0; i<_param->_nb_rename_unit; i++)
      for (uint32_t j=0; j<_param->_nb_inst_rename[i]; j++)
	PORT_WRITE(out_ISSUE_IN_ACK [i][j],issue_ack [i][j]);
    for (uint32_t i=0; i<_param->_nb_inst_reexecute; i++)
      PORT_WRITE(out_REEXECUTE_ACK [i],reexecute_ack [i]);

    log_end(Issue_queue,FUNCTION);
  };

}; // end namespace issue_queue
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core

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