#ifndef SOCLIB_CABA_VCI_SECBUS_H
#define SOCLIB_CABA_VCI_SECBUS_H



#include <systemc>
#include "vci_initiator.h"
#include "vci_target.h"
#include "vci_target_fsm.h"
#include "caba_base_module.h"
#include "security_context_controller.h"
#include "types.h"
#include <stdint.h>
#include "security_controller.h"
#include "ht_controller.h"
#include "cryptolib.h"
#include "my_interfaces.h"
#include "mac_controller.h"
#include "cache_controller.h"
#include "mux.h"
#include "registers.h"
#include "secbus_lib.h"


#define SOCLIB_MODULE_DEBUG
namespace soclib {
	namespace caba {

		using namespace sc_core;

		template<typename vci_param>
		class vci_secbus_hht
			: public soclib::caba::BaseModule
		{
		protected:
			SC_HAS_PROCESS(vci_secbus_hht);

		public:

			//Ports
			sc_in<bool> p_clk;
			sc_in<bool> p_resetn;

			sc_out<bool> p_irq;

			//memory 
				//target 
			soclib::caba::VciTarget<vci_param> 		p_vci_target;
				//initiator
			soclib::caba::VciInitiator<vci_param> 	p_vci_initiator;
			//io target 
			soclib::caba::VciTarget<vci_param> 			p_vci_io_target;
			soclib::caba::VciTargetFsm<vci_param, true> 	m_vci_target_fsm;
			

			//define secbus cache parameters
			cache_param_st pspe_cache;
			cache_param_st sp_cache;
			cache_param_st hash_cache;
			cache_param_st mac_cache;

			//Modules
			//instantiation of security controller fsm
			SecurityController			security_controller;  
			//instantiation of registers
			DataRegisterMux3			register_0_mux;
			DataRegister				register_0;
			DataRegisterMux2			register_1_mux;
			DataRegister				register_1;
			DataRegister				register_2;
			//instantiation of hash tree controller
			IntegrityControllerMux		hash_tree_controller_mux;
			HashTreeController			hash_tree_controller;
			//instantiation of cryptographic engines
			CBCMux						cipher_block_chaining_mux;
			CBEngine					cipher_block;
			CBCEngine					cipher_block_chaining;
			//memory controller mux
			MemoryControllerMux			memory_controller_mux;
			//instantiation of mac tree controller
			IntegrityControllerMux		mac_controller_mux;
			MacController				*mac_controller;
			//instantiation of security context controller 
			SecurityContextController	 *security_context_controller;  
			//instantiation of cache controllers
			MacCacheController			*mac_cache_controller;
			HashCacheController			*hash_cache_controller;

			//Signals
			//Security context controller signals
			SECURITY_CONTEXT_CMD_SIGNALS	sc_controller_regular_cmd_sig;
			DATA_SIGNALS<4>					sc_controller_regular_data_sig;
			SECURITY_CONTEXT_CMD_SIGNALS	sc_controller_ht_cmd_sig;
			DATA_SIGNALS<2>					sc_controller_ht_data_sig;
			ACK_SIGNALS						sc_controller_ack_sig;
			DATA_SIGNALS<4>					sc_controller_wdata_sig;
			SECURITY_CONTEXT_REGISTER_READ_SIGNALS  sc_register_read_sig;
			//Security controller signals
			SECURITY_CONTROLLER_SIGNALS		security_controller_regular_sig;
			MEMORY_CONTROLLER_CMD_SIGNALS	mb_controller_cmd_sig;
			DATA_SIGNALS<4>					mb_controller_wdata_sig;
			ACK_SIGNALS						mb_controller_ack_sig;
			DATA_SIGNALS<4>					mb_controller_rdata_sig;
			//Security controller mux signals
			MEMORY_CONTROLLER_CMD_SIGNALS	mb_controller_pspe_cmd_sig;
			DATA_SIGNALS<2>					mb_controller_pspe_wdata_sig;
			MEMORY_CONTROLLER_CMD_SIGNALS	mb_controller_sp_cmd_sig;
			DATA_SIGNALS<4>					mb_controller_sp_wdata_sig;
			//Integrity controllers signals
			INTEGRITY_CONTROLLER_CMD_SIGNALS	mac_controller_cmd_1_sig;
			INTEGRITY_CONTROLLER_CMD_SIGNALS	mac_controller_cmd_2_sig;
			INTEGRITY_CONTROLLER_CMD_SIGNALS	mac_controller_cmd_sig;
			INTEGRITY_CONTROLLER_ACK_SIGNALS	mac_controller_ack_sig;
			INTEGRITY_CONTROLLER_CMD_SIGNALS	hash_controller_cmd_1_sig;
			INTEGRITY_CONTROLLER_CMD_SIGNALS	hash_controller_cmd_2_sig;
			INTEGRITY_CONTROLLER_CMD_SIGNALS	hash_controller_cmd_sig;
			INTEGRITY_CONTROLLER_ACK_SIGNALS	hash_controller_ack_sig;
			//Cache controllers signals
			//pspe_mux
			CACHE_CONTROLLER_CMD_SIGNALS	pspe_cache_sc_cmd_sig;
			DATA_SIGNALS<2>					pspe_cache_sc_wdata_sig;
			CACHE_CONTROLLER_CMD_SIGNALS	pspe_cache_ht_cmd_sig;
			DATA_SIGNALS<2>					pspe_cache_ht_wdata_sig;
			//mac
			CACHE_CONTROLLER_CMD_SIGNALS	mac_cache_cmd_sig;
			DATA_SIGNALS<2>					mac_cache_wdata_sig;
			CACHE_CONTROLLER_ACK_SIGNALS	mac_cache_ack_sig;
			DATA_SIGNALS<2>					mac_cache_rdata_sig;
			//hash
			CACHE_CONTROLLER_CMD_SIGNALS	hash_cache_cmd_sig;
			DATA_SIGNALS<2>					hash_cache_wdata_sig;
			CACHE_CONTROLLER_ACK_SIGNALS	hash_cache_ack_sig;
			DATA_SIGNALS<2>					hash_cache_rdata_sig;
			//Cryptographic engine signals
			//Cipher block engine
			CRYPTOGRAPHIC_ENGINE_CMD_SIGNALS	cb_cmd_sig;
			DATA_SIGNALS<2>						cb_data_in_sig;
			sc_signal<bool>						cb_ack_sig;
			DATA_SIGNALS<2>						cb_data_out_sig;
			//Cipher block chaining engine
			CRYPTOGRAPHIC_ENGINE_CMD_SIGNALS	cbc_cmd_sig;
			DATA_SIGNALS<12>					cbc_data_in_sig;
			DATA_SIGNALS<2>						cbc_iv_sig;
			sc_signal<bool>						cbc_ack_sig;
			DATA_SIGNALS<2>						cbc_data_out_sig;
			//cbc mux
			CRYPTOGRAPHIC_ENGINE_CMD_SIGNALS	mac_cmd_sig;
			DATA_SIGNALS<12>					mac_data_in_sig;
			DATA_SIGNALS<2>						mac_iv_sig;
			CRYPTOGRAPHIC_ENGINE_CMD_SIGNALS	hash_cmd_sig;
			DATA_SIGNALS<12>					hash_data_in_sig;
			DATA_SIGNALS<2>						hash_iv_sig;
			CRYPTOGRAPHIC_ENGINE_CMD_SIGNALS tool_cmd_sig;
			DATA_SIGNALS<12>          tool_data_in_sig;
			DATA_SIGNALS<2>           tool_iv_sig;
			//Memory controller mux signals
			MEMORY_CONTROLLER_CMD_SIGNALS	memory_hash_cache_cmd_sig;
			DATA_SIGNALS<2>					memory_hash_cache_data_sig;
			MEMORY_CONTROLLER_CMD_SIGNALS	memory_ht_controller_cmd_sig;
			DATA_SIGNALS<2>					memory_ht_controller_data_sig;
			MEMORY_CONTROLLER_CMD_SIGNALS	memory_mac_cache_cmd_sig;
			DATA_SIGNALS<2>					memory_mac_cache_data_sig;
			MEMORY_CONTROLLER_CMD_SIGNALS	memory_mac_controller_cmd_sig;
			DATA_SIGNALS<2>					memory_mac_controller_data_sig;
			MEMORY_CONTROLLER_CMD_SIGNALS	memory_security_controller_cmd_sig;
			DATA_REGISTER_READ_SIGNALS		memory_security_controller_data_sig;
			MEMORY_CONTROLLER_CMD_SIGNALS	initiator_cmd_in_sig;
			DATA_REGISTER_READ_SIGNALS		initiator_data_in_sig;
			ACK_SIGNALS						memory_ack_sig;
			DATA_REGISTER_WRITE_SIGNALS		initiator_cmd_out_sig;
			//data input register mux
			DATA_REGISTER_WRITE_SIGNALS		register_0_in_target_sig;
			DATA_REGISTER_WRITE_SIGNALS		register_0_in_security_controller_sig;
			DATA_REGISTER_WRITE_SIGNALS		register_0_in_initiator_sig;
			DATA_REGISTER_WRITE_SIGNALS		register_0_in_sig;
			DATA_REGISTER_READ_SIGNALS		register_0_out_sig;
			//data output register mux
			DATA_REGISTER_WRITE_SIGNALS		register_1_in_initiator_sig;
			DATA_REGISTER_WRITE_SIGNALS		register_1_in_security_controller_sig;
			DATA_REGISTER_WRITE_SIGNALS		register_1_in_sig;
			DATA_REGISTER_READ_SIGNALS		register_1_out_sig;
			//mac or hash data register mux
			DATA_REGISTER_WRITE_SIGNALS		register_2_in_initiator_sig;
			DATA_REGISTER_WRITE_SIGNALS		register_2_in_hash_sig;
			DATA_REGISTER_WRITE_SIGNALS		register_2_in_mac_sig;
			DATA_REGISTER_WRITE_SIGNALS		register_2_in_sig;
			DATA_REGISTER_READ_SIGNALS		register_2_out_sig;

			typedef enum 
			{
				CMD = 0,
				ARG_0, 
				ARG_1,
				ARG_2,
				RUN,
				STATUT,
				RESET_IRQ,
				OUT_0,
				OUT_1
			}secbus_io_register_e;

			enum vci_target_state_e
			{
				TARGET_IDLE,
				TARGET_CMD_ACK,
				START_READ,//2
				WAIT_READ,
				READ_RSP,
				FLUSH_REGISTER_0,
				WRITE_REGISTER_0,//6
				WRITE_RSP,
				START_WRITE,
				WAIT_WRITE,//9
				READ_SECURITY_CONTEXT,//10
				WAIT_READ_SECURITY_CONTEXT,
				WRITE_SECURITY_CONTEXT,//12
				WAIT_WRITE_SECURITY_CONTEXT,
				START_INITIALIZE_INTEGRITY,
				WAIT_INITIALIZE_INTEGRITY,//15
        START_INIT_MASTER_TREE,
        WAIT_INIT_MASTER_TREE,
				START_CBC_TOOL,
				WAIT_CBC_TOOL,
				START_IRQ,
				WAIT_FOR_ACK,
				ACK
			};
			enum vci_initiator_cmd_state_e
			{
				CMD_IDLE,
				CMD_READ,
				CMD_WRITE
			};
			enum vci_initiator_rsp_state_e
			{
				RSP_IDLE,
				RSP_READ,
				RSP_LAST_READ,
				RSP_WRITE
			};

			ofstream dump_in;
			ofstream dump_out;
			ofstream debug_info;
      ofstream stat_info;


			void print_stats();
      void reset_stats();

			sc_signal<vci_target_state_e>			vci_target_state;
			sc_signal<typename vci_param::srcid_t>	srcid_s;
			sc_signal<typename vci_param::trdid_t>	trdid_s;
			sc_signal<typename vci_param::pktid_t>	pktid_s;


			sc_signal<vci_initiator_cmd_state_e>	vci_initiator_cmd_state;
			sc_signal<vci_initiator_rsp_state_e>	vci_initiator_rsp_state;
			sc_signal<unsigned int>			initiator_rsp_cpt_s;
			sc_signal<unsigned int>			initiator_cmd_cpt_s;
			sc_signal<addr_t>						initiator_address_s;
			sc_signal<cmd_e>						initiator_cmd_s;
			sc_signal<unsigned int>			initiator_plen_s;
			sc_signal<bool>							write_register;
			sc_signal<unsigned int>			initiator_id_s;
			sc_signal<unsigned int>			initiator_index_s;
			sc_signal<unsigned int>			initiator_cells_to_come_s;


			sc_signal<bool>							cmdack_s;
			sc_signal<addr_t>						target_address_s;
			sc_signal<addr_t>						target_start_address_s;
			sc_signal<addr_t>						target_end_address_s;
			sc_signal<typename					vci_param::cmd_t> target_cmd_s;
			sc_signal<unsigned int>					target_cpt_s;
			sc_signal<bool>							target_eop_s;
			sc_signal<unsigned int>					target_plen_s;
			sc_signal<unsigned int>					target_index_s;
			sc_signal<int>      					initiator_be_s;
			sc_signal<unsigned int>					target_cells_to_come_s;
			sc_signal<bool>							target_pending_packet_s;
      
			unsigned int							index_v;
			int										target_rdata_s;
			int										target_wdata_s;
			int										initiator_data_s;
			unsigned int							target_be_s;

			bool									ht_update_idle;
			bool									ht_idle;

			//io registers
			sc_signal<int>				cmd_s;
			sc_signal<int>				arg_0_s;
			sc_signal<int>				arg_1_s;
			sc_signal<int>				arg_2_s;
			sc_signal<bool>				run_s;
			sc_signal<secbus_status_e>	statut_s;
			sc_signal<int>        out_0_s;
			sc_signal<int>        out_1_s;

      sc_signal<bool>       r_irq_s;

			// Activity counters
			unsigned long int m_cpt_r;
			unsigned long int m_cpt_rcycle;
			unsigned long int m_cpt_w;
			unsigned long int m_cpt_wcycle;
			unsigned long int scr_misses;
			unsigned long int scr_accesses;
       addr_t reset_cpt_address;
			

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

			//io management
			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);

			~vci_secbus_hht(); 

		private:
			void ps();
			void pc();
		};
	}}
#endif 

