#ifdef SYSTEMC
/*
 * $Id: Context_State_genMoore.cpp 111 2009-02-27 18:37:40Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_Front_end/Front_end/Context_State/include/Context_State.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_front_end {
namespace front_end {
namespace context_state {


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

    // -------------------------------------------------------------------
    // -----[ EVENT ]-----------------------------------------------------
    // -------------------------------------------------------------------
    for (uint32_t i=0; i<_param->_nb_context; i++)
      {
	context_state_t state = reg_STATE [i];

        Tcontrol_t val              = ((state == CONTEXT_STATE_KO_EXCEP_ADDR      ) or
                                       (state == CONTEXT_STATE_KO_MISS_BRANCH_ADDR) or
                                       (state == CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR) or
                                       (state == CONTEXT_STATE_KO_MISS_LOAD_ADDR  ) or
                                       (state == CONTEXT_STATE_KO_PSYNC_ADDR      ) or 
                                       (state == CONTEXT_STATE_KO_CSYNC_ADDR));
        
        // SR can't change in this cycle
        // Exception Prefix High
        Taddress_t    address          = reg_EVENT_ADDRESS [i] | (((state == CONTEXT_STATE_KO_EXCEP_ADDR) and PORT_READ(in_SPR_SR_EPH [i]))?(0xF000000>>2):0);
        Taddress_t    address_next     = reg_EVENT_ADDRESS_EPCR [i];
        Tcontrol_t    address_next_val = (state == CONTEXT_STATE_KO_MISS_BRANCH_ADDR) and (reg_EVENT_ADDRESS_EPCR_VAL [i]);
        Tcontrol_t    is_ds_take       = (state == CONTEXT_STATE_KO_MISS_BRANCH_ADDR) and (reg_EVENT_IS_DS_TAKE       [i]);
	// excep : address exception
	// miss  : address delay_slot, and address dest
	// psync : address next
	// csync : address next
        Tevent_type_t type                         ;//[nb_context]
        Tdepth_t      depth            = reg_EVENT_DEPTH [i];

        switch (state)
          {
          case CONTEXT_STATE_KO_EXCEP_ADDR      : (type = EVENT_TYPE_EXCEPTION              ); break;
          case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR: 
          case CONTEXT_STATE_KO_MISS_BRANCH_ADDR: (type = EVENT_TYPE_BRANCH_MISS_SPECULATION); break;
          case CONTEXT_STATE_KO_MISS_LOAD_ADDR  : (type = EVENT_TYPE_LOAD_MISS_SPECULATION  ); break;
          case CONTEXT_STATE_KO_PSYNC_ADDR      : (type = EVENT_TYPE_PSYNC                  ); break; 
          case CONTEXT_STATE_KO_CSYNC_ADDR      : (type = EVENT_TYPE_CSYNC                  ); break;
          default                               : (type = EVENT_TYPE_NONE                   ); break;
          }
//      (type = EVENT_TYPE_SPR_ACCESS        );
//      (type = EVENT_TYPE_MSYNC             );
//      (type = EVENT_TYPE_BRANCH_NO_ACCURATE);

        internal_EVENT_VAL [i] = val;
	PORT_WRITE(out_EVENT_VAL              [i], val);
	PORT_WRITE(out_EVENT_ADDRESS          [i], address);
	PORT_WRITE(out_EVENT_ADDRESS_NEXT     [i], address_next); 
	PORT_WRITE(out_EVENT_ADDRESS_NEXT_VAL [i], address_next_val);
	PORT_WRITE(out_EVENT_IS_DS_TAKE       [i], is_ds_take);
	PORT_WRITE(out_EVENT_TYPE             [i], type);
        if (_param->_have_port_depth)
	PORT_WRITE(out_EVENT_DEPTH            [i], depth);

	log_printf(TRACE,Context_State,FUNCTION,"  * EVENT Context      : %d", i);
	log_printf(TRACE,Context_State,FUNCTION,"    * VAL              : %d", val);
	log_printf(TRACE,Context_State,FUNCTION,"    * ADDRESS          : %.8x (%.8x)", address     , address     <<2);
	log_printf(TRACE,Context_State,FUNCTION,"    * ADDRESS_NEXT     : %.8x (%.8x)", address_next, address_next<<2); 
	log_printf(TRACE,Context_State,FUNCTION,"    * ADDRESS_NEXT_VAL : %d", address_next_val);
	log_printf(TRACE,Context_State,FUNCTION,"    * IS_DS_TAKE       : %d", is_ds_take);
	log_printf(TRACE,Context_State,FUNCTION,"    * TYPE             : %d", type);
	log_printf(TRACE,Context_State,FUNCTION,"    * DEPTH            : %d", depth);
      }

    // -------------------------------------------------------------------
    // -----[ SPR_EVENT ]-------------------------------------------------
    // -------------------------------------------------------------------
    for (uint32_t i=0; i<_param->_nb_context; i++)
      {
	context_state_t state = reg_STATE [i];

	internal_SPR_EVENT_VAL [i] = (state == CONTEXT_STATE_KO_EXCEP_SPR  );

	PORT_WRITE(out_SPR_EVENT_VAL       [i], internal_SPR_EVENT_VAL     [i]);
	PORT_WRITE(out_SPR_EVENT_EPCR      [i], reg_EVENT_ADDRESS_EPCR     [i]);
	PORT_WRITE(out_SPR_EVENT_EEAR      [i], reg_EVENT_ADDRESS_EEAR     [i]);
	PORT_WRITE(out_SPR_EVENT_EEAR_WEN  [i], reg_EVENT_ADDRESS_EEAR_VAL [i]);
	PORT_WRITE(out_SPR_EVENT_SR_DSX    [i], reg_EVENT_IS_DELAY_SLOT    [i]);
	PORT_WRITE(out_SPR_EVENT_SR_TO_ESR [i], 1);
      }

    // -------------------------------------------------------------------
    // -----[ CONTEXT ]---------------------------------------------------
    // -------------------------------------------------------------------
    for (uint32_t i=0; i<_param->_nb_context; i++)
      {
	context_state_t state = reg_STATE [i];

// 	PORT_WRITE(out_CONTEXT_DECOD_ENABLE [i], ((state==CONTEXT_STATE_OK            ) or
// 						  (state==CONTEXT_STATE_KO_MSYNC_ISSUE) or
// 						  (state==CONTEXT_STATE_KO_SPR_ISSUE  )));
	PORT_WRITE(out_CONTEXT_DECOD_ENABLE [i], (state==CONTEXT_STATE_OK));
      }

    log_end(Context_State,FUNCTION);
  };

}; // end namespace context_state
}; // end namespace front_end
}; // end namespace multi_front_end
}; // end namespace core

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