#ifdef SYSTEMC
/*
 * $Id: Special_Register_unit_transition.cpp 118 2009-05-20 22:01:32Z rosiere $
 *
 * [ Description ]
 * 
 */

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

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace special_register_unit {


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

    if (PORT_READ(in_NRESET) == 0)
      {
	for (uint32_t i=0; i<_param->_nb_front_end; i++)
	  for (uint32_t j=0; j<_param->_nb_context[i]; j++)
	    for (uint32_t k=0; k<NB_GROUP; k++)
	      if (_param->_implement_group [i][j][k])
		for (uint32_t l=0; l<NB_REG_GROUP[k]; l++)
		  if (_spr_access_mode [i][j]->exist(k,l))
		    {
#ifdef DEBUG_TEST
		      if (_spr [i][j][k]    == NULL)
			throw ERRORMORPHEO(FUNCTION,toString(_("Group [%d] is not implemented.\n"),k));
		      if (_spr [i][j][k][l] == NULL)
			throw ERRORMORPHEO(FUNCTION,toString(_("Register [%d][%d] is not implemented.\n"),k,l));
#endif
 		      log_printf(TRACE,Special_Register_unit,FUNCTION,"  * Reset SPR [%d][%d][%d][%d]",i,j,k,l);
		      _spr [i][j][k][l]->reset();
		    }

      }
    else
      {
	// ===================================================================
	// =====[ SPR_ACCESS ]================================================
	// ===================================================================
	for (uint32_t i=0; i<_param->_nb_inst_reexecute; i++)
	  if (PORT_READ(in_SPR_ACCESS_VAL [i]) and internal_SPR_ACCESS_ACK [i])
	    if (PORT_READ(in_SPR_ACCESS_WEN [i]))
	      {
                log_printf(TRACE,Special_Register_unit,FUNCTION,"  * SPR_ACCESS [%d]",i);

		Tcontext_t     front_end_id = (_param->_have_port_front_end_id)?PORT_READ(in_SPR_ACCESS_FRONT_END_ID [i]):0;
		Tcontext_t     context_id   = (_param->_have_port_context_id  )?PORT_READ(in_SPR_ACCESS_CONTEXT_ID   [i]):0;
		Tspr_address_t num_group    = PORT_READ(in_SPR_ACCESS_NUM_GROUP [i]);
		Tspr_address_t num_reg      = PORT_READ(in_SPR_ACCESS_NUM_REG   [i]);

                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * front_end_id : %d",front_end_id);
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * context_id   : %d",context_id  );
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * num_group    : %d",num_group   );
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * num_reg      : %d",num_reg     );

 		SR * sr = static_cast<SR*>(_spr [front_end_id][context_id][GROUP_SYSTEM_AND_CONTROL][SPR_SR]);

		Tcontrol_t sm    = sr->sm   ;
		Tcontrol_t sumra = sr->sumra;
                Tcontrol_t valid = _spr_access_mode [front_end_id][context_id]->write(spr_address_t(num_group,num_reg),
                                                                                      sm,
                                                                                      sumra);	
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * SM           : %d",sm);
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * SUMRA        : %d",sumra);
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * valid        : %d",valid);

                if (valid)
                  {
                    Tspr_t wdata = PORT_READ(in_SPR_ACCESS_WDATA [i]);

                    log_printf(TRACE,Special_Register_unit,FUNCTION,"    * wdata        : %.8x",wdata);

                    _spr[front_end_id][context_id][num_group][num_reg]->write(wdata);
                  }
		
	      }
	
	// ===================================================================
	// =====[ SPR_COMMIT ]-===============================================
	// ===================================================================
	for (uint32_t i=0; i<_param->_nb_front_end; i++)
	  for (uint32_t j=0; j<_param->_nb_context[i]; j++)
            {
              if (PORT_READ(in_SPR_COMMIT_VAL [i][j])) // out_SPR_COMMIT_ACK [i][j]
                {
                  log_printf(TRACE,Special_Register_unit,FUNCTION,"  * SPR_COMMIT [%d][%d]",i,j);
                  log_printf(TRACE,Special_Register_unit,FUNCTION,"    * F            : %d, %d",PORT_READ(in_SPR_COMMIT_SR_F_VAL  [i][j]),PORT_READ(in_SPR_COMMIT_SR_F  [i][j]));
                  log_printf(TRACE,Special_Register_unit,FUNCTION,"    * CY           : %d, %d",PORT_READ(in_SPR_COMMIT_SR_CY_VAL [i][j]),PORT_READ(in_SPR_COMMIT_SR_CY [i][j]));
                  log_printf(TRACE,Special_Register_unit,FUNCTION,"    * OV           : %d, %d",PORT_READ(in_SPR_COMMIT_SR_OV_VAL [i][j]),PORT_READ(in_SPR_COMMIT_SR_OV [i][j]));

                  log_printf(TRACE,Special_Register_unit,FUNCTION,"    * SPR (before) : %.8x",_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_SR]->read());
                  SR * sr = static_cast<SR*>(_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_SR]);

                  if (PORT_READ(in_SPR_COMMIT_SR_F_VAL  [i][j]))
                    sr->f  = PORT_READ(in_SPR_COMMIT_SR_F  [i][j]);
                  
                  if (PORT_READ(in_SPR_COMMIT_SR_CY_VAL [i][j]))
                    sr->cy = PORT_READ(in_SPR_COMMIT_SR_CY [i][j]);
                  
                  if (PORT_READ(in_SPR_COMMIT_SR_OV_VAL [i][j]))
                    sr->ov = PORT_READ(in_SPR_COMMIT_SR_OV [i][j]);

                  log_printf(TRACE,Special_Register_unit,FUNCTION,"    * SPR (after)  : %.8x",_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_SR]->read());

                }

              if (PORT_READ(in_SPR_EVENT_VAL [i][j])) // out_SPR_EVENT_ACK [i][j]
                {
                  log_printf(TRACE,Special_Register_unit,FUNCTION,"  * SPR_EVENT [%d][%d]",i,j);
                  log_printf(TRACE,Special_Register_unit,FUNCTION,"    * SPR (before) : %.8x",_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_SR]->read());

                  SR * sr = static_cast<SR*>(_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_SR]);
                  sr->dsx = PORT_READ(in_SPR_EVENT_SR_DSX [i][j]);

                  _spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_EPCR]->write(PORT_READ(in_SPR_EVENT_EPCR [i][j]));
                  if (PORT_READ(in_SPR_EVENT_EEAR_WEN [i][j]))
                  _spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_EEAR]->write(PORT_READ(in_SPR_EVENT_EEAR [i][j]));
                  if (PORT_READ(in_SPR_EVENT_SR_TO_ESR [i][j]))
                  _spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_ESR ]->write(sr->read());

                  log_printf(TRACE,Special_Register_unit,FUNCTION,"    * SPR (after)  : %.8x",_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_SR]->read());
                }
            }

#if (DEBUG >= DEBUG_TRACE) and (DEBUG_Special_Register_unit == true)
        {
          log_printf(TRACE,Special_Register_unit,FUNCTION,"  * Dump SPR");

          for (uint32_t i=0; i<_param->_nb_front_end; i++)
            for (uint32_t j=0; j<_param->_nb_context[i]; j++)
              {
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * SR        [%d][%d] : %.8x",i,j,_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_SR          ]->read());
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * CID       [%d][%d] : %.8x",i,j,_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_CID         ]->read());
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * TID       [%d][%d] : %.8x",i,j,_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_TID         ]->read());
                log_printf(TRACE,Special_Register_unit,FUNCTION,"    * TSR       [%d][%d] : %.8x",i,j,_spr [i][j][GROUP_SYSTEM_AND_CONTROL][SPR_TSR         ]->read());
//                 log_printf(TRACE,Special_Register_unit,FUNCTION,"    * MACLO     [%d][%d] : %.8x",i,j,_spr [i][j][GROUP_MAC               ][SPR_MACLO      ]->read());
//                 log_printf(TRACE,Special_Register_unit,FUNCTION,"    * MACHI     [%d][%d] : %.8x",i,j,_spr [i][j][GROUP_MAC               ][SPR_MACHI      ]->read());
              }
        }
#endif
      }

#if defined(STATISTICS) or defined(VHDL_TESTBENCH)
    end_cycle ();
#endif

    log_end(Special_Register_unit,FUNCTION);
  };

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

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