/*
 * 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 SECURITYCTX_CTRL_H
#define SECURITYCTX_CTRL_H

#include <systemc>

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

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

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

  SECURITY_CTX_CMD_IN     ctx_cmd;
  CTX_REGISTER_READ_OUT   ctx_register;

  // return read PSPE/SP from register 0
  DATA_REGISTER_READ_IN   r_register_0;
  // update PSPE/SP with register 2
  DATA_REGISTER_WRITE_OUT w_register_2;

  SECURITY_RQ_OUT         sc_out_cmd;

  IRQ_OUT                 irq;

  DATA_IN<2>              w_data;
/*  DATA_OUT<8>           sc_out_wdata;*/
  
  SecurityCtx_Ctrl(sc_module_name name, 
		   const cache_param_s &pspe_param, 
		   const cache_param_s &sp_param);
  ~SecurityCtx_Ctrl();

private:
  void transition();
  void genMoore();
  void checkMPSPE();
  void checkSPSPE();
  void checkSP();

  void printPSPE();

  enum fsm_state_e
  {
    FSM_IDLE,
    FSM_FLUSH_REG2,
    FSM_HIT_PSPE,
    FSM_READ_PSPE,
    FSM_WREAD_PSPE,
    FSM_HIT_SP,
    FSM_READ_SP,
    FSM_WREAD_SP,
    FSM_WRITE_PSPE,
    FSM_WWRITE_PSPE,
    FSM_WRITE_SP,
    FSM_WWRITE_SP,
    FSM_INTERRUPT,
    FSM_WAIT_INTERRUPT
  };
  
  // signals
  sc_signal<int> fsm_s;
  sc_signal<bool>      hit_s;
  sc_signal<addr_t>    address_s;
  sc_signal<addr_t>    pspe_address_s;
  sc_signal<addr_t>    sp_address_s;
  sc_signal<addr_t>    spblock_to_come_s;
  sc_signal<size_t>    size_s;
  sc_signal<bool>      slave_s;
  sc_signal<int> cmd_s;
  sc_signal<uint32_t>  ctx_sp_s[SP_SIZE_IN_WORDS];
  sc_signal<uint32_t>  ctx_s_pspe_s[PSPE_SIZE_IN_WORDS];
  sc_signal<uint32_t>  ctx_m_pspe_s[PSPE_SIZE_IN_WORDS];
  sc_signal<addr_t>    ctx_page_address_s;
  sc_signal<addr_t>    ctx_s_pspe_address_s;
  sc_signal<addr_t>    pspe_write_address_s;
  sc_signal<addr_t>    sp_write_address_s;
  sc_signal<uint32_t>  pspe_write_data_s[PSPE_SIZE_IN_WORDS];
  sc_signal<uint32_t>  sp_write_data_s[SP_SIZE_IN_WORDS];
  sc_signal<bool>      first_s;
  sc_signal<bool>      is_pspe_s;
  sc_signal<uint32_t>  int_src_s;
  sc_signal<bool>      mt_s;

  sc_signal<int> round_s;

  // cache
  Cache *pspe_cache;
  Cache *sp_cache;
  
  cache_param_s pspe_cache_param;
  cache_param_s sp_cache_param;

  pCacheblock_t sp_victim_block;
  pCacheblock_t pspe_victim_block;

  pspe_t   current_pspe;
  sp_t     current_sp;

  size_t m_cycle;
};

#endif
