#ifdef SYSTEMC
/*
 * $Id: Issue_queue_function_in_order_genMealy_issue_out.cpp 117 2009-05-16 14:42: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::function_in_order_genMealy_issue_out"
  void Issue_queue::function_in_order_genMealy_issue_out (void)
  {
    log_begin(Issue_queue,FUNCTION);
    log_function(Issue_queue,FUNCTION,_name.c_str());

    // ===================================================================
    // =====[ ISSUE_OUT ]=================================================
    // ===================================================================
    {
      Tcontrol_t val [_param->_nb_inst_issue];

      uint32_t index=0;
      for (uint32_t i=0; i<_param->_nb_inst_issue; i++)
        val [i] = 0;

      //--------------------------------------
      // From Reexecute_queue
      //--------------------------------------

      // scan all reexecute_queue slot ...
//       uint32_t num_reexecute_entry = 0;
      for (std::list<entry_t*>::iterator it=_reexecute_queue.begin();
           it!=_reexecute_queue.end();
           ++it)
        {
          entry_t* entry = (*it);

          val [index] = 1;
              
          if (_param->_have_port_context_id)
	  PORT_WRITE(out_ISSUE_OUT_CONTEXT_ID            [index], entry->_context_id           );
	  if (_param->_have_port_front_end_id)
	  PORT_WRITE(out_ISSUE_OUT_FRONT_END_ID          [index], entry->_front_end_id         );
	  if (_param->_have_port_rob_ptr  )
	  PORT_WRITE(out_ISSUE_OUT_PACKET_ID             [index], entry->_packet_id            );
	  PORT_WRITE(out_ISSUE_OUT_OPERATION             [index], entry->_operation            );
	  PORT_WRITE(out_ISSUE_OUT_TYPE                  [index], entry->_type                 );
	  PORT_WRITE(out_ISSUE_OUT_STORE_QUEUE_PTR_WRITE [index], entry->_store_queue_ptr_write);
	  if (_param->_have_port_load_queue_ptr)
	  PORT_WRITE(out_ISSUE_OUT_LOAD_QUEUE_PTR_WRITE  [index], entry->_load_queue_ptr_write );
	  PORT_WRITE(out_ISSUE_OUT_HAS_IMMEDIAT          [index], entry->_has_immediat         );
	  PORT_WRITE(out_ISSUE_OUT_IMMEDIAT              [index], entry->_immediat             );
	  PORT_WRITE(out_ISSUE_OUT_READ_RA               [index], entry->_read_ra              );
	  PORT_WRITE(out_ISSUE_OUT_NUM_REG_RA            [index], entry->_num_reg_ra           );
	  PORT_WRITE(out_ISSUE_OUT_READ_RB               [index], entry->_read_rb              );
	  PORT_WRITE(out_ISSUE_OUT_NUM_REG_RB            [index], entry->_num_reg_rb           );
	  PORT_WRITE(out_ISSUE_OUT_READ_RC               [index], entry->_read_rc              );
	  PORT_WRITE(out_ISSUE_OUT_NUM_REG_RC            [index], entry->_num_reg_rc           );
	  PORT_WRITE(out_ISSUE_OUT_WRITE_RD              [index], entry->_write_rd             );
	  PORT_WRITE(out_ISSUE_OUT_NUM_REG_RD            [index], entry->_num_reg_rd           );
	  PORT_WRITE(out_ISSUE_OUT_WRITE_RE              [index], entry->_write_re             );
	  PORT_WRITE(out_ISSUE_OUT_NUM_REG_RE            [index], entry->_num_reg_re           );

          internal_ISSUE_OUT_FROM_REEXECUTE [index] = true;
//        internal_ISSUE_OUT_NUM_BANK       [index] = num_reexecute_entry;
          internal_ISSUE_OUT_ENTRY          [index] = entry;

          index ++; // next slot
        }
      
      //--------------------------------------
      // From Issue_queue
      //--------------------------------------
      index = _param->_nb_inst_reexecute;

      log_printf(TRACE,Issue_queue,FUNCTION,"  * From Issue_queue");

      // for all instruction in issue_queue head ...
      for (uint32_t i=0; i<_param->_nb_bank; ++i)
        {
          uint32_t num_bank=(reg_NUM_BANK_HEAD+i)%_param->_nb_bank;
          
          log_printf(TRACE,Issue_queue,FUNCTION,"    * Bank [%d]",num_bank);
          
//           bool find = false;
          
          // ... test if have an instruction
          if (not _issue_queue [num_bank].empty())
            {
 	      log_printf(TRACE,Issue_queue,FUNCTION,"      * Not Empty !!!");

              // read instruction
              entry_t* entry = _issue_queue [num_bank].front();
              
//               Tcontrol_t issue_ack = PORT_READ(in_ISSUE_OUT_ACK [index]);
              
              log_printf(TRACE,Issue_queue,FUNCTION,"      * Issue [%d]",index);
//               log_printf(TRACE,Issue_queue,FUNCTION,"        * issue_ack            : %d",issue_ack);
//            log_printf(TRACE,Issue_queue,FUNCTION,"        * previous transaction : %d",val[index]);
//            log_printf(TRACE,Issue_queue,FUNCTION,"        * can issue type       : %d",_param->_table_issue_type [index][entry->_type]);

              // in_order : test if find a valid read_unit
//               if (issue_ack)
//                 {
// 	          log_printf(TRACE,Issue_queue,FUNCTION,"        * find !!!");
                  
//                   find = true;
//                 }

              // find a issue port
              val [index] = true; // instruction is valid
              
              if (_param->_have_port_context_id)
              PORT_WRITE(out_ISSUE_OUT_CONTEXT_ID            [index], entry->_context_id           );
              if (_param->_have_port_front_end_id)
              PORT_WRITE(out_ISSUE_OUT_FRONT_END_ID          [index], entry->_front_end_id         );
              if (_param->_have_port_rob_ptr  )
              PORT_WRITE(out_ISSUE_OUT_PACKET_ID             [index], entry->_packet_id            );
              PORT_WRITE(out_ISSUE_OUT_OPERATION             [index], entry->_operation            );
              PORT_WRITE(out_ISSUE_OUT_TYPE                  [index], entry->_type                 );
              PORT_WRITE(out_ISSUE_OUT_STORE_QUEUE_PTR_WRITE [index], entry->_store_queue_ptr_write);
              if (_param->_have_port_load_queue_ptr)
              PORT_WRITE(out_ISSUE_OUT_LOAD_QUEUE_PTR_WRITE  [index], entry->_load_queue_ptr_write );
              PORT_WRITE(out_ISSUE_OUT_HAS_IMMEDIAT          [index], entry->_has_immediat         );
              PORT_WRITE(out_ISSUE_OUT_IMMEDIAT              [index], entry->_immediat             );
              PORT_WRITE(out_ISSUE_OUT_READ_RA               [index], entry->_read_ra              );
              PORT_WRITE(out_ISSUE_OUT_NUM_REG_RA            [index], entry->_num_reg_ra           );
              PORT_WRITE(out_ISSUE_OUT_READ_RB               [index], entry->_read_rb              );
              PORT_WRITE(out_ISSUE_OUT_NUM_REG_RB            [index], entry->_num_reg_rb           );
              PORT_WRITE(out_ISSUE_OUT_READ_RC               [index], entry->_read_rc              );
              PORT_WRITE(out_ISSUE_OUT_NUM_REG_RC            [index], entry->_num_reg_rc           );
              PORT_WRITE(out_ISSUE_OUT_WRITE_RD              [index], entry->_write_rd             );
              PORT_WRITE(out_ISSUE_OUT_NUM_REG_RD            [index], entry->_num_reg_rd           );
              PORT_WRITE(out_ISSUE_OUT_WRITE_RE              [index], entry->_write_re             );
              PORT_WRITE(out_ISSUE_OUT_NUM_REG_RE            [index], entry->_num_reg_re           );
              
              internal_ISSUE_OUT_FROM_REEXECUTE [index] = false;
              internal_ISSUE_OUT_NUM_BANK       [index] = num_bank;
              internal_ISSUE_OUT_ENTRY          [index] = entry;

              index ++; // next slot
            }

//           if (not find)
//             {
//  	      log_printf(TRACE,Issue_queue,FUNCTION,"      * Not find. Stop Scan (in order)");
              
//               break; // stop scan (in order)
//             }
        }
      
      // Output
      for (uint32_t i=0; i<_param->_nb_inst_issue; i++)
        {
          internal_ISSUE_OUT_VAL [i] = val [i];
          PORT_WRITE(out_ISSUE_OUT_VAL [i], internal_ISSUE_OUT_VAL [i]);

//           // Type invalid to the Core_Glue network
//           if (not val [i]) // == empty
//             PORT_WRITE(out_ISSUE_OUT_TYPE [i], TYPE_INVALID);
        }
    }

    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
