/*
 * SecBus - This file is part of SecBus
 * Copyright (C) 2012 - Telecom ParisTech
 * 
 * This file must be used under the terms of the CeCILL.
 * This source file is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at    
 * http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.txt
 *
 */

#ifndef SECURITY_CTRL_H
#define SECURITY_CTRL_H

#include <systemc>

#include "secbus_lib.h"
#include "types.h"
#include "my_interfaces.h"

SC_MODULE(Security_Ctrl)
{
protected:
  SC_HAS_PROCESS(Security_Ctrl);

public:
  sc_in<bool> p_clk;
  sc_in<bool> p_resetn;
  sc_in<uint32_t> p_b_address;
  sc_in<uint32_t> p_size;
  sc_in<uint32_t> p_mb_address;

  // incoming request (from securityctx_ctrl & input_ctrl)
  SECURITY_RQ_IN          cmd;

  // memory access
  MEMORY_CTRL_CMD_OUT     mem_rq;

  // crypto module access
  CRYPTO_CMD_OUT          crypto_cmd;

  INTEGRITY_CTRL_CMD_OUT  mt_cmd;
  INTEGRITY_CTRL_ACK_IN   mt_ack;

  INTEGRITY_CTRL_CMD_OUT  ms_cmd;
  INTEGRITY_CTRL_ACK_IN   ms_ack;

  // uncrypted data
  DATA_REGISTER_READ_IN   r_register_0;
  DATA_REGISTER_WRITE_OUT w_register_0;

  // encrypted data
  DATA_REGISTER_READ_IN   r_register_1;
  // for PSPE/SP
  DATA_REGISTER_READ_IN   r_register_2;
  // for normal memory access
  DATA_REGISTER_READ_IN   r_register_ad;

  // security ctx
  CTX_REGISTER_READ_IN    ctx_register;
  // master security ctx
  MASTER_CTX_REG_READ_IN  master_ctx_init;
  // master security ctx out
  MASTER_CTX_REG_READ_OUT master_ctx;
  // master security ctx update
  MASTER_CTX_REG_READ_IN  master_update;

  // secbus enable/disable
  sc_in<bool>             secbus_enable;

  // little hack 
  sc_out<bool>            ack;

  Security_Ctrl(sc_module_name name);
  ~Security_Ctrl();

private:
  void transition();
  void genMealy();

  // internal functions
  void copySP();

  enum fsm_read_e
  {
    R_IDLE,
    R_START_READ,
    R_WAIT_FOR_CINT,
    R_START_CINT,
    R_WAIT_READ,
    R_WAIT_CINT,
    R_UPDATE_REG_0,
    R_START_BLOCK_DEC,
    R_WAIT_BLOCK_DEC,
    R_SLEEP
  };

  enum fsm_write_e
  {
    W_IDLE,
    W_START_READ,
    W_WAIT_READ,
    W_WAIT_FOR_CINTEGRITY,
    W_START_CINTEGRITY,
    W_WAIT_CINTEGRITY, // 5
    W_START_BLOCK_DEC,
    W_WAIT_BLOCK_DEC,
    W_START_BLOCK_ENC,
    W_WAIT_BLOCK_ENC,
    W_UPDATE_REG_0, // 10
    W_START_WRITE,
    W_WAIT_WRITE,
    W_START_UINT,
    W_WAIT_UINT,
    W_SLEEP // 15
  };

  sc_signal<int>  fsm_read_s;
  sc_signal<int> fsm_write_s;

  sc_signal<int> cmd_crypto_s;
  sc_signal<uint32_t> src_id_s;
  sc_signal<uint32_t> dest_id_s;
  sc_signal<bool> is_cipher_s;
  sc_signal<addr_t> address_s;
  sc_signal<uint32_t> plen_s;
  sc_signal<uint32_t> crypto_size_s;
  sc_signal<bool> is_mac_s;
  sc_signal<bool> is_int_s;
  sc_signal<bool> start_check_mac_s;
  sc_signal<bool> start_check_mactree_s;
  sc_signal<uint32_t> int_src_s;
  sc_signal<bool> mb_s;
  sc_signal<bool> start_up_mac_s;

  sc_signal<uint32_t> master_sp[SP_SIZE_IN_WORDS];
  sc_signal<uint32_t> master_pspe[PSPE_SIZE_IN_WORDS];

  size_t m_cycle;
  sp_t   current_sp;
  sp_key_c_t key;
};

#endif
