/*
 * $Id: Encryption.cpp 86 2008-05-14 17:08:56Z rosiere $
 *
 * [ 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)
  {
    if (operation == _operation_encrypt)
      return &(morpheo::behavioural::custom::encryption::Encryption::decod_encrypt);
    if (operation == _operation_decrypt)
      return &(morpheo::behavioural::custom::encryption::Encryption::decod_decrypt);

    return &(morpheo::behavioural::core::multi_front_end::front_end::decod_unit::decod::instruction_illegal); // unimplemented function
  }

  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;
  };

  void Encryption::decod_encrypt (morpheo::behavioural::core::multi_front_end::front_end::decod_unit::decod::decod_instruction_t * inst, 
				  morpheo::behavioural::core::multi_front_end::front_end::decod_unit::decod::decod_param_t       * param)
  {
    log_printf(TRACE,Decod,"decod_encrypt","  * instruction   : encrypt");

    inst->_has_immediat       = 0;
//  inst->_immediat           = ;
    inst->_read_ra            = 1;
    inst->_num_reg_ra         = range<Tgeneral_address_t>(inst->_instruction,20,16);
    inst->_read_rb            = 0;
//  inst->_num_reg_rb         = ;
    inst->_read_rc            = 0;
//  inst->_num_reg_rc         = ;
    inst->_write_rd           = 1;
    inst->_num_reg_rd         = range<Tgeneral_address_t>(inst->_instruction,25,21);
    inst->_write_re           = 0;
//  inst->_num_reg_re         = ;
    inst->_exception_use      = EXCEPTION_USE_NONE;
    inst->_event_type         = EVENT_TYPE_NONE;
  }

  void Encryption::decod_decrypt (morpheo::behavioural::core::multi_front_end::front_end::decod_unit::decod::decod_instruction_t * inst, 
				  morpheo::behavioural::core::multi_front_end::front_end::decod_unit::decod::decod_param_t       * param)
  {
    log_printf(TRACE,Decod,"decod_decrypt","  * instruction   : decrypt");

    inst->_has_immediat       = 0;
//  inst->_immediat           = ;
    inst->_read_ra            = 1;
    inst->_num_reg_ra         = range<Tgeneral_address_t>(inst->_instruction,20,16);
    inst->_read_rb            = 0;
//  inst->_num_reg_rb         = ;
    inst->_read_rc            = 0;
//  inst->_num_reg_rc         = ;
    inst->_write_rd           = 1;
    inst->_num_reg_rd         = range<Tgeneral_address_t>(inst->_instruction,25,21);
    inst->_write_re           = 0;
//  inst->_num_reg_re         = ;
    inst->_exception_use      = EXCEPTION_USE_NONE;
    inst->_event_type         = EVENT_TYPE_NONE;
  }

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