#ifndef _MUX_H_
#define _MUX_H_

#include "my_interfaces.h"
#include "systemc.h"


SC_MODULE(SecurityContextControllerMux)
{
	public:

  sc_in<bool> clk;
	sc_in<bool> reset;

	SECURITY_CONTEXT_CMD_IN in1;
	SECURITY_CONTEXT_CMD_IN in2;
	SECURITY_CONTEXT_CMD_OUT out;


	//Combinatory process
	void pc();
	void ps();

  enum security_context_controller_mux_state_e 
	{
		IDLE,
		IN1,
		IN2
	};

	sc_signal<security_context_controller_mux_state_e> state;
 
	SC_CTOR(SecurityContextControllerMux)
	{
		SC_METHOD(pc);
		sensitive << clk.neg();

		SC_METHOD(ps);
		sensitive << clk.pos();
	}

};

SC_MODULE(SecurityContextRegisterMux)
{
	public:

	SECURITY_CONTEXT_REGISTER_WRITE_IN in1;
	SECURITY_CONTEXT_REGISTER_WRITE_IN in2;
	SECURITY_CONTEXT_REGISTER_WRITE_OUT out;

	//Combinatory process
	void pc();

	SC_CTOR(SecurityContextRegisterMux)
	{
		SC_METHOD(pc);
		sensitive << in1.enable << in2.enable << in1.sel << in2.sel;
	}

};

SC_MODULE(DataRegisterMux2)
{
	public:

	DATA_REGISTER_WRITE_IN in1;
	DATA_REGISTER_WRITE_IN in2;

	DATA_REGISTER_WRITE_OUT out;

	//Combinatory process
	void pc();

	SC_CTOR(DataRegisterMux2)
	{
		SC_METHOD(pc);
		sensitive << in1.enable << in2.enable << in1.flush << in2.flush << in1.address << in2.address;
	}

};
SC_MODULE(DataRegisterMux3)
{
	public:

	DATA_REGISTER_WRITE_IN in1;
	DATA_REGISTER_WRITE_IN in2;
	DATA_REGISTER_WRITE_IN in3;

	DATA_REGISTER_WRITE_OUT out;

	//Combinatory process
	void pc();

	SC_CTOR(DataRegisterMux3)
	{
		SC_METHOD(pc);
		sensitive	<< in1.enable 
					<< in2.enable 
					<< in3.enable 
					<< in1.flush 
					<< in2.flush 
					<< in3.flush 
					<< in1.address
					<< in2.address
					<< in3.address;
	}

};

SC_MODULE(CacheControllerMux)
{
	public:

	CACHE_CONTROLLER_CMD_IN		sc_cmd;			
	CACHE_CONTROLLER_CMD_IN		ht_cmd;
	CACHE_CONTROLLER_CMD_OUT	out_cmd;

	DATA_IN<2>					sc_wdata;	
	DATA_IN<2>					ht_wdata;
	DATA_OUT<2>					out_wdata;

	//Combinatory process
	void pc();

	SC_CTOR(CacheControllerMux)
	{
		SC_METHOD(pc);
		sensitive << sc_cmd.enable << ht_cmd.enable;
	}

};
SC_MODULE(SecurityControllerMux)
{
	public:

	MEMORY_CONTROLLER_CMD_IN	sp_cmd;
	MEMORY_CONTROLLER_CMD_IN	pspe_cmd;
	MEMORY_CONTROLLER_CMD_OUT	out_cmd;

	DATA_IN <4>					sp_data;
	DATA_IN <2>					pspe_data;
	DATA_OUT <4>				out_data;


	//Combinatory process
	void pc();

	SC_CTOR(SecurityControllerMux)
	{
		SC_METHOD(pc);
		sensitive << sp_cmd.enable << pspe_cmd.enable;
	}

};
SC_MODULE(MemoryControllerMux)
{
	public:

	MEMORY_CONTROLLER_CMD_IN	security_controller_cmd;
	MEMORY_CONTROLLER_CMD_IN	hash_cache_controller_cmd;
	MEMORY_CONTROLLER_CMD_IN	hash_tree_controller_cmd;
	MEMORY_CONTROLLER_CMD_IN	mac_controller_cmd;
	MEMORY_CONTROLLER_CMD_IN	mac_cache_controller_cmd;
	MEMORY_CONTROLLER_CMD_OUT	memory_out_cmd;

  sc_in<bool> clk;
	sc_in<bool> reset;

	
	//Combinatory process
	void pc();
	void ps();

	enum memory_controller_mux_state_e
	{
		IDLE,
		SC,
		HC,
		HT,
		MC,
		MCC,
	};
	
	sc_signal<memory_controller_mux_state_e> state;

	SC_CTOR(MemoryControllerMux)
	{
		SC_METHOD(pc);
/*		sensitive << clk.neg();
		SC_METHOD(ps);
		sensitive << clk.pos();
*/

    sensitive	<< security_controller_cmd.enable 
					<< hash_cache_controller_cmd.enable 
					<< mac_cache_controller_cmd.enable
					<< hash_tree_controller_cmd.enable
					<< mac_controller_cmd.enable;

	}
};
SC_MODULE(CBCMux)
{
	public:

	CRYPTOGRAPHIC_ENGINE_CMD_IN		mac_cmd;
	CRYPTOGRAPHIC_ENGINE_CMD_IN		hash_cmd;
	CRYPTOGRAPHIC_ENGINE_CMD_IN   tool_cmd;
	CRYPTOGRAPHIC_ENGINE_CMD_OUT	out_cmd;

	DATA_IN<12>					mac_data;	
	DATA_IN<12>					hash_data;
	DATA_IN<12>         tool_data;
	DATA_OUT<12>				out_data;

	DATA_IN<2>					mac_iv;	
	DATA_IN<2>					hash_iv;
	DATA_IN<2>          tool_iv;
	DATA_OUT<2>					out_iv;

	//Combinatory process
	void pc();

	SC_CTOR(CBCMux)
	{
		SC_METHOD(pc);
		sensitive	<< mac_cmd.enable 
					<< hash_cmd.enable 
					<< tool_cmd.enable;
	}
};

SC_MODULE(IntegrityControllerMux)
{
	public:

	INTEGRITY_CONTROLLER_CMD_IN		in1;
	INTEGRITY_CONTROLLER_CMD_IN		in2;
	INTEGRITY_CONTROLLER_CMD_OUT	out;

	//Combinatory process
	void pc();

	SC_CTOR(IntegrityControllerMux)
	{
		SC_METHOD(pc);
		sensitive	<< in1.enable 
					<< in2.enable ;
	}
};

#endif
