/*
 * $Id$
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Custom/include/Random.h"

namespace morpheo {
namespace behavioural {
namespace custom {
namespace random {

  static uint32_t _num_group;

  Random::Random (uint32_t num_group)
  {
    _num_group = num_group;
  };

  uint32_t Random::get_nb_register (void)
  {
    return 4;
  };
    
  access_mode_t Random::get_access_mode (uint32_t reg)
  {
    // All reg is access by supervisor
    if (reg == num_register_random)
      return access_mode_t (SPR_ACCESS_MODE_READ_ONLY, SPR_ACCESS_MODE_READ_ONLY);

    return access_mode_t (SPR_ACCESS_MODE_READ_ONLY_COND, SPR_ACCESS_MODE_READ_WRITE);
  }

  custom_decod_t * Random::get_custom_decod (Toperation_t operation)
  {
    // TODO !!!!!
    return NULL;
  }

  custom_execute_genMoore_t * Random::get_custom_execute_genMoore (Toperation_t operation)
  {
    return &(morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::operation_unimplemented); // unimplemented function
  }

  custom_execute_transition_t * Random::get_custom_execute_transition (void)
  {
    // No treatment a the end cycle
    return &(function_transition);
  }

  custom_execute_transition_t * Random::get_custom_execute_reset (void)
  {
    // No treatment a the end cycle
    return &(function_reset);
  }

  void Random::function_transition (morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_register_t  * reg,
				    morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_param_t     * param)
  {
    std::cout << "<Random::function_transition> Transition" << std::endl;

    uint32_t num_group    = reg->_access_num_group;
    uint32_t num_register = reg->_access_num_register;
    if (num_group == _num_group)
      {
	// Test if have a read of num_register_random
	if ((reg->_i_read_spr) and
	    (num_register == num_register_random))
	  {
	    Tgeneral_data_t random = reg->_spr[num_group][num_register_random];
	    Tgeneral_data_t cst1   = reg->_spr[num_group][num_register_cst1  ];
	    Tgeneral_data_t cst2   = reg->_spr[num_group][num_register_cst2  ];
	    Tgeneral_data_t max    = reg->_spr[num_group][num_register_max   ];

	    // make a new value
	    reg->_spr[num_group][num_register_random] = (cst1*random+cst2)%max;
	  }

	// Test if write in register_max
	if (reg->_i_write_spr and
	    (reg->_spr[num_group][num_register] == 0))
	  {
	    reg->_spr[num_group][num_register] = reg->_spr_old;
	  }
      }
  };
  
  void Random::function_reset  (morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_register_t  * reg,
				morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_param_t     * param)
  {
    std::cout << "<Random::function_reset> Reset" << std::endl;

    reg->_spr[_num_group][num_register_random] = 0xbebe;
    reg->_spr[_num_group][num_register_cst1  ] = 0xdeadbeef;
    reg->_spr[_num_group][num_register_cst2  ] = 0x666;
    reg->_spr[_num_group][num_register_max   ] = 0xffffffff;
  };

}; // end namespace random 
}; // end namespace custom
}; // end namespace behavioural
}; // end namespace morpheo              
