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

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

namespace morpheo {
namespace behavioural {
namespace custom {
namespace encryption {

  static uint32_t _num_group;

  Encryption::Encryption (uint32_t     num_group,
			  Toperation_t operation_encrypt,
			  Toperation_t operation_decrypt) :
    _operation_encrypt (operation_encrypt),
    _operation_decrypt (operation_decrypt)
  {
    _num_group = num_group;
  };

  uint32_t Encryption::get_nb_register (void)
  {
    return 3;
  };
    
  access_mode_t Encryption::get_access_mode (uint32_t reg)
  {
    // All reg is access by supervisor
    return access_mode_t (SPR_ACCESS_MODE_NONE, SPR_ACCESS_MODE_READ_WRITE);
  }

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

  custom_execute_genMoore_t * Encryption::get_custom_execute_genMoore (Toperation_t operation)
  {
    if (operation == _operation_encrypt)
      return &(morpheo::behavioural::custom::encryption::Encryption::function_encrypt);
    if (operation == _operation_decrypt)
      return &(morpheo::behavioural::custom::encryption::Encryption::function_decrypt);

    return &(morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::operation_unimplemented); // unimplemented function
  }

  custom_execute_transition_t * Encryption::get_custom_execute_transition (void)
  {
    // No treatment a the end cycle
    return NULL;
  }

  custom_execute_transition_t * Encryption::get_custom_execute_reset (void)
  {
    // No treatment a the end cycle
    return NULL;
  }

  void Encryption::function_encrypt (morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_operation_t * op,
				     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 << "<Encryption::function_decrypt> Operation : encrypt" << std::endl;

    Tgeneral_data_t data = unsigned(op->_data_ra);
    
    Tgeneral_data_t key   = reg->_spr[_num_group][num_register_key  ];
    Tgeneral_data_t shift = reg->_spr[_num_group][num_register_shift];
    Tgeneral_data_t rool  = reg->_spr[_num_group][num_register_role ];

    for (Tgeneral_data_t i=0 ; i<rool; i++)
      {
	data ^= key;
	data  = rotate_right<Tgeneral_data_t>(param->_size_data,data,shift);
      }
    
    // Result
    
    op->_timing       = morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_timing_t(rool, rool);
    op->_data_rd      = data;
  //op->_data_re      = 0;
    op->_exception    = EXCEPTION_ALU_NONE;
    op->_no_sequence  = 0;
  //op->_address      = 0;
  };
  
  void Encryption::function_decrypt (morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_operation_t * op,
				     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 << "<Encryption::function_decrypt> Operation : decrypt" << std::endl;

    Tgeneral_data_t data = unsigned(op->_data_ra);
    
    Tgeneral_data_t key   = reg->_spr[_num_group][num_register_key  ];
    Tgeneral_data_t shift = reg->_spr[_num_group][num_register_shift];
    Tgeneral_data_t rool  = reg->_spr[_num_group][num_register_role ];

    for (Tgeneral_data_t i=0 ; i<rool; i++)
      {
	data  = rotate_left<Tgeneral_data_t>(param->_size_data,data,shift);
	data ^= key;
      }
    
    // Result
    op->_timing       = morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::execute_timing_t(rool, rool);
    op->_data_rd      = data;
  //op->_data_re      = 0;
    op->_exception    = EXCEPTION_ALU_NONE;
    op->_no_sequence  = 0;
  //op->_address      = 0;
  };

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