#ifdef SYSTEMC
/*
 * $Id: Decod_queue_function_multi_fifo_genMealy_decod_out.cpp 124 2009-06-17 12:11:25Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_Front_end/Front_end/Decod_unit/Decod_queue/include/Decod_queue.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_front_end {
namespace front_end {
namespace decod_unit {
namespace decod_queue {


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

    if (PORT_READ(in_NRESET))
      {
    bool       context_val   [_param->_nb_context];
    uint32_t   nb_inst_event [_param->_nb_context];
    for (uint32_t i=0; i<_param->_nb_context; i++)
      {
        context_val   [i] = true;
        nb_inst_event [i] = reg_NB_INST_EVENT [i];
      }

    Tcontrol_t val         [_param->_nb_inst_decod];
    for (uint32_t i=0; i<_param->_nb_inst_decod; i++)
      {
	val                    [i] = 0;
	internal_DECOD_OUT_VAL [i] = 0;
	internal_DECOD_OUT_ACK [i] = 0;
      }
    
    uint32_t num_bank = reg_NUM_BANK_HEAD%_param->_nb_bank;
    
    for (uint32_t i=0; i<_param->_nb_inst_decod; i++)
      {
        log_printf(TRACE,Decod_queue,FUNCTION,_("  * num_bank : %d"),num_bank);

        if (not reg_QUEUE[num_bank].empty())
          {
            log_printf(TRACE,Decod_queue,FUNCTION,_("  * Queue is not empty, slot [%d] is valid."),i);
            
            Tcontext_t context  = reg_QUEUE[num_bank].front()->_context_id [0];

            log_printf(TRACE,Decod_queue,FUNCTION,"      * context      : %d",context);

            if (context_val [context])
              {

//                 Tdepth_t   depth           = reg_QUEUE[num_bank].front()->_depth         [0];
//                 Tdepth_t   depth_min       = (_param->_have_port_depth)?PORT_READ(in_DEPTH_MIN [context]):0;
//                 Tdepth_t   depth_max       = (_param->_have_port_depth)?PORT_READ(in_DEPTH_MAX [context]):0;
//                 Tcontrol_t depth_full      = PORT_READ(in_DEPTH_FULL[context]);
                
                    // is a valid instruction ?
                // If DEPTH_CURRENT :
                // equal at     DEPTH_MIN            -> not speculative
                // not include ]DEPTH_MIN:DEPTH_MAX] -> previous branch miss
                //     include ]DEPTH_MIN:DEPTH_MAX] -> speculative
                
                // All case
                // ....... min ...X... max ....... OK
                // ....... min ....... max ...X... KO
                // ...X... min ....... max ....... KO
                // ....... max ....... min ...X... OK
                // ...X... max ....... min ....... OK
                // ....... max ...X... min ....... KO
                
                Tcontrol_t is_valid = (nb_inst_event [context] == 0);
                
//                 Tcontrol_t   is_valid      = ((depth == depth_min) or
//                                               depth_full or
//                                               ((depth_min <= depth_max)?
//                                                ((depth >= depth_min) and (depth <=depth_max)):
//                                                ((depth >= depth_min) or  (depth <=depth_max))));
                
                log_printf(TRACE,Decod_queue,FUNCTION,"    * is_valid : %d",is_valid);
                log_printf(TRACE,Decod_queue,FUNCTION,"      * context_val  : %d",context_val   [context]);
                log_printf(TRACE,Decod_queue,FUNCTION,"      * nb_inst_event: %d",nb_inst_event [context]);
//              log_printf(TRACE,Decod_queue,FUNCTION,"      * depth        : %d",depth);
//              log_printf(TRACE,Decod_queue,FUNCTION,"      * depth_min    : %d",depth_min);
//              log_printf(TRACE,Decod_queue,FUNCTION,"      * depth_max    : %d",depth_max);
//              log_printf(TRACE,Decod_queue,FUNCTION,"      * depth_full   : %d",depth_full);
#ifdef DEBUG    
                log_printf(TRACE,Decod_queue,FUNCTION,"      * address      : 0x%x (0x%x)",reg_QUEUE[num_bank].front()->_address     [0],reg_QUEUE[num_bank].front()->_address     [0]<<2);
#endif          
                log_printf(TRACE,Decod_queue,FUNCTION,"      * address_next : 0x%x (0x%x)",reg_QUEUE[num_bank].front()->_address_next[0],reg_QUEUE[num_bank].front()->_address_next[0]<<2);
                
                internal_DECOD_OUT_VAL [i] = 1; // in all case, val is set (entry is not empty, and instruction is valid)

                if (is_valid)
                  {
                    val                    [i] = 1;
                    internal_DECOD_OUT_ACK [i] = PORT_READ(in_DECOD_OUT_ACK [i]);
                  }
                else
                  {
                    // Consume the instruction (to erase)
                    internal_DECOD_OUT_ACK [i] = 1;

                    // Have event ?
                    if (nb_inst_event [context] > 0)
                      {
                        nb_inst_event [context] --;
                        
                        // Last event ?
                        if (nb_inst_event [context] == 0)
                          {
                            context_val [context] = false;
                          }
                      }
                  }

                log_printf(TRACE,Decod_queue,FUNCTION,"      * decod_out_ack: %d (%d)",internal_DECOD_OUT_ACK [i],PORT_READ(in_DECOD_OUT_ACK [i]));
              }
          }
        num_bank = (num_bank+1)%_param->_nb_bank;
      }
    
    for (uint32_t i=0; i<_param->_nb_inst_decod; i++)
      {
        log_printf(TRACE,Decod_queue,FUNCTION,"  * DECOD_OUT_VAL : %d",val [i]);
        
        PORT_WRITE(out_DECOD_OUT_VAL [i],val [i]);
      }
      }
    else
      {
        // Reset
        for (uint32_t i=0; i<_param->_nb_inst_decod; i++)
          {
            internal_DECOD_OUT_VAL [i] = 0;
            internal_DECOD_OUT_ACK [i] = 0;
            PORT_WRITE(out_DECOD_OUT_VAL [i],0);
          }
      }

    log_end(Decod_queue,FUNCTION);
  };

}; // end namespace decod_queue
}; // end namespace decod_unit
}; // end namespace front_end
}; // end namespace multi_front_end
}; // end namespace core

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