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

#include <systemc>

// soclib
#include "vci_signals.h"
#include "vci_target.h"
#include "vci_target_fsm.h"
#include "vci_initiator.h"

// secbus common
#include "secbus_lib.h"
#include "types.h"

// secbus module
#include "ms_ctrl.h"
#include "mscache_ctrl.h"
#include "mt_ctrl.h"
#include "mtcache_ctrl.h"
#include "irq_handler.h"
#include "mux.h"
#include "registers.h"
#include "vci_merge.h"
#include "vci_split.h"
#include "vci_mem_ctrl.h"
#include "vci_input_ctrl.h"
#include "securityctx_ctrl.h"
#include "mem_arbiter.h"
#include "cache.h"
#include "crypto_engine.h"
#include "security_ctrl.h"
#include "sc_arbiter.h"
#include "crypto_arbiter.h"
#include "generic_cmd_fifo.h"

namespace soclib
{
  namespace caba
  {
    template<typename vci_param>
      class VciSecbusV2 : public soclib::caba::BaseModule
    {

    protected:
      SC_HAS_PROCESS(VciSecbusV2);

    public:
      sc_in<bool> p_clk;
      sc_in<bool> p_resetn;

      // load/store from processor
      VciTarget<vci_param> p_vci_target;

      // rq to the memory controller
      VciInitiator<vci_param> p_vci_initiator;

      // SecBus IO
      VciTarget<vci_param> p_vci_io_target;
      VciTargetFsm<vci_param, true> m_vci_target_fsm;

      // Interrupt from SecBus
      sc_out<bool> p_irq_e;
      sc_out<bool> p_irq_c;

      VciSecbusV2(
	sc_module_name name,
	const soclib::common::MappingTable &mt,
	const soclib::common::IntTab &tgtid
	);
      ~VciSecbusV2();

      bool on_write(
	int seg,
	typename vci_param::addr_t addr,
	typename vci_param::data_t data,
	int be
	);

      bool on_read(
	int seg,
	typename vci_param::addr_t addr,
	typename vci_param::data_t &data,
	int be
	);

    private:
      enum secbus_io_register_e
      {
	secbus_io_config,        /** 0x00 **/
	secbus_io_status,        /** 0x04 **/
			         
	secbus_io_sp_0,          /** 0x08 **/
	secbus_io_sp_1,          /** 0x0c **/
	secbus_io_sp_2,          /** 0x10 **/
	secbus_io_sp_3,          /** 0x14 **/
	secbus_io_sp_4,          /** 0x18 **/
	secbus_io_sp_5,          /** 0x1c **/
	secbus_io_sp_6,          /** 0x20 **/
	secbus_io_sp_7,          /** 0x24 **/
	secbus_io_sp_8,          /** 0x28 **/
  	secbus_io_sp_9,          /** 0x2c **/
	secbus_io_sp_10,         /** 0x30 **/
	secbus_io_sp_11,         /** 0x34 **/
	secbus_io_sp_12,         /** 0x38 **/
	secbus_io_sp_13,         /** 0x3c **/
	secbus_io_sp_14,         /** 0x40 **/
	secbus_io_sp_15,         /** 0x44 **/
			         
	secbus_io_pspe_0,        /** 0x48 **/
	secbus_io_pspe_1,        /** 0x4c **/

	secbus_io_block_addr,    /** 0x50 **/
  
	secbus_io_block_data_0,  /** 0x54 **/
	secbus_io_block_data_1,  /** 0x58 **/
	secbus_io_block_data_2,  /** 0x5c **/
	secbus_io_block_data_3,  /** 0x60 **/
	secbus_io_block_data_4,  /** 0x64 **/
	secbus_io_block_data_5,  /** 0x68 **/
	secbus_io_block_data_6,  /** 0x6c **/
 	secbus_io_block_data_7,  /** 0x70 **/

	secbus_io_cmd            /** 0x74 **/
      };

      // io registers
      io_reg_32_t io_config_s;
      io_reg_32_t io_status_s;
      io_reg_32_t io_sp_s[SP_SIZE_IN_WORDS];
      io_reg_32_t io_pspe_s[PSPE_SIZE_IN_WORDS];
      io_reg_32_t io_block_data_s[BLOCK_DATA_SIZE_IN_WORDS];
      io_reg_32_t io_cmd_s;
      io_addr_t   io_block_addr_s;

      sc_signal<bool> irq_ack_s;

      // SecBus Block
      VciMerge<vci_param>     *vci_merge;
      VciSplit<vci_param>     *vci_split;

      VciInputCtrl<vci_param> *vci_input_ctrl;

      VciMemCtrl<vci_param>   *vci_mem_ctrl;
      MemArbiter              *mem_arbiter;
      CryptoEngine_conf       *crypto_engine_conf;
      CryptoEngine_int        *crypto_engine_int;
      CryptoArbiter           *crypto_arbiter;
      SecurityCtx_Ctrl        *securityctx_ctrl;
      Security_Ctrl           *security_ctrl;
      ScArbiter               *sc_arbiter;
      IrqHandler              *irq_handler;

      MT_Ctrl                 *mt_ctrl;
      MTCache_Ctrl            *mtcache_ctrl;

      MS_Ctrl                 *ms_ctrl;
      MSCache_Ctrl            *mscache_ctrl;

      DataRegister            *register_0;
      DataRegister            *register_1;
      DataRegister            *register_2;
      DataRegister            *register_3;
      DataRegister            *register_4;

      GenericCmdFifo<MEMORY_CTRL_CMD_IN, MEMORY_CTRL_CMD_OUT, MEMORY_CTRL_CMD_SIGNALS> *mt_mem_cmd;
      GenericCmdFifo<MEMORY_CTRL_CMD_IN, MEMORY_CTRL_CMD_OUT, MEMORY_CTRL_CMD_SIGNALS> *mtcache_mem_cmd;
      GenericCmdFifo<MEMORY_CTRL_CMD_IN, MEMORY_CTRL_CMD_OUT, MEMORY_CTRL_CMD_SIGNALS> *ms_mem_cmd;
      GenericCmdFifo<MEMORY_CTRL_CMD_IN, MEMORY_CTRL_CMD_OUT, MEMORY_CTRL_CMD_SIGNALS> *mscache_mem_cmd;
      GenericCmdFifo<CRYPTO_CMD_IN, CRYPTO_CMD_OUT, CRYPTO_CMD_SIGNALS> *mt_crypto_cmd;
      GenericCmdFifo<CRYPTO_CMD_IN, CRYPTO_CMD_OUT, CRYPTO_CMD_SIGNALS> *ms_crypto_cmd;

      Mux<DATA_REGISTER_WRITE_IN, DATA_REGISTER_WRITE_OUT> *mux_reg0;
      Mux<DATA_REGISTER_WRITE_IN, DATA_REGISTER_WRITE_OUT> *mux_reg1;
      Mux<DATA_REGISTER_WRITE_IN, DATA_REGISTER_WRITE_OUT> *mux_reg2;
      Mux<DATA_REGISTER_WRITE_IN, DATA_REGISTER_WRITE_OUT> *mux_reg3;

      Mux<SECURITY_CTX_CMD_IN, SECURITY_CTX_CMD_OUT> *mux_scctx;
      Mux<DATA_IN<2>, DATA_OUT<2> > *mux_direct_write;
      Mux<INTEGRITY_CTRL_CMD_IN, INTEGRITY_CTRL_CMD_OUT> *mux_mt_cmd;
      Mux<DATA_IN<12>, DATA_OUT<12> > *mux_int_direct_data;

      // signal
      VciSignals<vci_param> split_to_sec;
      VciSignals<vci_param> split_to_merge;
      VciSignals<vci_param> memctrl_to_merge;

      MEMORY_CTRL_CMD_SIGNALS     mem_arbiter_to_mem_ctrl;
      DATA_REGISTER_WRITE_SIGNALS mem_arbiter_to_register[5];
      DATA_REGISTER_WRITE_SIGNALS crypto_module_to_register[4];
      DATA_REGISTER_READ_SIGNALS  register_to_mem_arbiter[4];
      DATA_REGISTER_READ_SIGNALS  reg_to_mtcache_ctrl;
      DATA_SIGNALS<2>             direct_data;
      DATA_SIGNALS<2>             direct_data_mt;
      DATA_SIGNALS<2>             direct_data_mtcache;
      DATA_SIGNALS<2>             direct_data_ms;
      DATA_SIGNALS<2>             direct_data_mscache;

      MEMORY_CTRL_CMD_SIGNALS     mem_rq_to_mem_arbiter[2];
      DATA_REGISTER_WRITE_SIGNALS input_ctrl_to_mux_reg_0;
      DATA_REGISTER_WRITE_SIGNALS input_ctrl_to_mux_reg_3;
      DATA_REGISTER_WRITE_SIGNALS mux_to_reg0;
      DATA_REGISTER_WRITE_SIGNALS mux_to_reg1;
      DATA_REGISTER_WRITE_SIGNALS mux_to_reg2;
      DATA_REGISTER_WRITE_SIGNALS mux_to_reg3;
      DATA_REGISTER_WRITE_SIGNALS securityctx_ctrl_to_reg_2;
      DATA_REGISTER_WRITE_SIGNALS security_ctrl_to_mux_reg_0;

      CRYPTO_CMD_SIGNALS          crypto_cmd;
      DATA_SIGNALS<2>             crypto_mac;
      DATA_SIGNALS<12>            integrity_direct_data;
      DATA_SIGNALS<2>             direct_pspe;
      DATA_SIGNALS<8>             io_data_wr;
      DATA_SIGNALS<12>            data_from_mt;
      DATA_SIGNALS<12>            data_from_ms;
      
      SECURITY_CTX_CMD_SIGNALS    input_ctrl_to_ctx_cmd;
      SECURITY_RQ_SIGNALS         ctx_ctrl_to_sc;
      SECURITY_RQ_SIGNALS         input_ctrl_to_sc;
      SECURITY_RQ_SIGNALS         sc_rq;
      CTX_REGISTER_READ_SIGNALS   ctx_reg_to_sc;
      MASTER_CTX_REG_READ_SIGNALS master_ctx_from_input;
      MASTER_CTX_REG_READ_SIGNALS ht_to_master_ctx;
      MASTER_CTX_REG_READ_SIGNALS master_ctx_to_ht;
      IO_BLOCK_SIGNALS<8>         io_block;
      sc_signal<bool>             io_ack;

      INTEGRITY_CTRL_CMD_SIGNALS  sc_ctrl_to_mt;
      INTEGRITY_CTRL_CMD_SIGNALS  input_to_mt;
      INTEGRITY_CTRL_CMD_SIGNALS  mux_to_mt;
      INTEGRITY_CTRL_ACK_SIGNALS  mt_ack;
      CACHE_CTRL_CMD_SIGNALS      mt_to_cache_cmd;
      DATA_SIGNALS<2>             mt_to_cache_data;
      CACHE_CTRL_ACK_SIGNALS      mt_to_cache_ack;
      DATA_SIGNALS<2>             cache_to_mt_data;
      SECURITY_CTX_CMD_SIGNALS    mt_to_scctx_cmd;
      DATA_SIGNALS<2>             mt_to_scctx_data;
      CRYPTO_CMD_SIGNALS          mt_to_crypto_cmd;
      MEMORY_CTRL_CMD_SIGNALS     mt_to_memctrl;
      MEMORY_CTRL_CMD_SIGNALS     mtfifo_to_memctrl;
      DATA_SIGNALS<2>             mt_to_mem_data;
      SECURITY_CTX_CMD_SIGNALS    mux_to_scctx;

      MEMORY_CTRL_CMD_SIGNALS     mtcache_to_memctrl;
      MEMORY_CTRL_CMD_SIGNALS     mtcache_to_genfifo;
      CRYPTO_CMD_SIGNALS          mux_to_crypto_cmd;
      CRYPTO_CMD_SIGNALS          mt_to_genfifo;

      MEMORY_CTRL_CMD_SIGNALS     msfifo_to_memctrl;
      MEMORY_CTRL_CMD_SIGNALS     ms_to_memctrl;
      INTEGRITY_CTRL_CMD_SIGNALS  sc_ctrl_to_ms;
      INTEGRITY_CTRL_ACK_SIGNALS  ms_ack;
      CACHE_CTRL_CMD_SIGNALS      ms_to_cache_cmd;
      DATA_SIGNALS<2>             ms_to_cache_wdata;
      CACHE_CTRL_ACK_SIGNALS      ms_to_cache_ack;
      DATA_SIGNALS<2>             cache_to_ms_rdata;
      CRYPTO_CMD_SIGNALS          ms_to_crypto_cmd;
      
      MEMORY_CTRL_CMD_SIGNALS     mscache_to_genfifo;
      MEMORY_CTRL_CMD_SIGNALS     mscache_to_memctrl;
      CRYPTO_CMD_SIGNALS          ms_to_genfifo;

      IRQ_SIGNALS                 irq_out;
      IRQ_SIGNALS                 irq_ctxctrl;
      IRQ_SIGNALS                 irq_inputctrl;
      IRQ_SIGNALS                 irq_mtctrl;
      IRQ_SIGNALS                 irq_msctrl;

      sc_signal<unsigned int> reg_b_addr_s;
      sc_signal<unsigned int> reg_size_s;
      sc_signal<bool>         reg_enable_s;
      sc_signal<unsigned int> reg_mb_addr_s;
      sc_signal<bool>         reg_c_sp_s;
      sc_signal<bool>         reg_c_pspe_s;
      sc_signal<bool>         reg_c_mac_s;
      sc_signal<bool>         reg_c_hmac_s;
      sc_signal<bool>         reg_int_s;
//      sc_signal<unsigned int> reg_block_data_s[SIZE_256_IN_WORDS];
      sc_signal<unsigned int> reg_status_s;

      sc_signal<bool>         secbus_busy;
      sc_signal<bool>         irq_signal_s;

      sc_signal<bool>         sc_busy_s;

      size_t m_cycle;
      cache_param_s pspe_cache;
      cache_param_s sp_cache;
      cache_param_s mactree_cache;
      cache_param_s mac_cache;

      void transition();
      void genMoore();
    };
  }
}


#endif 
