
#ifndef _SCONTROLLER_H_
#define _SCONTROLLER_H_

#include "systemc.h"
#include "global.h"
#include "types.h"
#include "buffer.h"
#include "my_interfaces.h"
#include "secbus_lib.h"

SC_MODULE(SecurityController)
{

private:

	enum sc_read_state_e
	{
		R_IDLE = 0,
		R_WAIT_FOR_READ_256,
		R_START_READ_256, 
		R_WAIT_READ_256,
		R_START_MASK_GENERATION,//4
		R_WAIT_MASK_GENERATION, 
		R_WAIT_FOR_BLOCK_DEC,
		R_START_BLOCK_DEC,
		R_WAIT_BLOCK_DEC,//8
		R_WRITE_64_TO_REGISTER_0,
		R_WRITE_256_TO_REGISTER_0 //10
	};
	enum sc_write_state_e
	{	
		W_IDLE = 0,
		W_WAIT_FOR_READ_256,
		W_START_READ_256,
		W_WAIT_READ_256,
		W_WAIT_FOR_READ_64,//4
		W_START_READ_64,
		W_WAIT_READ_64,
		W_START_BLOCK_DEC,
		W_WAIT_BLOCK_DEC,//8
		W_WRITE_64_TO_REGISTER_0,
		W_START_MASK_GENERATION,
		W_WAIT_MASK_GENERATION,
		W_START_BLOCK_ENC,//12
		W_WAIT_BLOCK_ENC,
		W_WRITE_64_TO_REGISTER_1,//14
		W_WRITE_256_TO_REGISTER_1,
		W_WAIT_FOR_WRITE_TO_MEMORY,
		W_START_WRITE_TO_MEMORY,
		W_WAIT_WRITE_TO_MEMORY,//18
		W_START_IU,
		W_WAIT_IU//20
	};

	//Master Block Read Steps
	enum mbsc_read_state_e
	{	
		MBR_IDLE = 0,
		MBR_WAIT_FOR_READ_256,
		MBR_START_READ_256,//2
		MBR_WAIT_READ_256,
		MBR_WAIT_FOR_BLOCK_DEC,
    MBR_START_BLOCK_DEC,
		MBR_WAIT_BLOCK_DEC//6
	};
	//Master Block Write Steps
	enum mbsc_write_state_e
	{
		MBW_IDLE = 0,
		MBW_START_BLOCK_ENC,
		MBW_WAIT_BLOCK_ENC,
		MBW_WAIT_FOR_READ_256,
		MBW_START_READ_256,//4
		MBW_WAIT_READ_256,
		MBW_WRITE_64_TO_REGISTER_1,
		MBW_WAIT_FOR_WRITE_TO_MEMORY,
		MBW_START_WRITE_TO_MEMORY,//8
		MBW_WAIT_WRITE_TO_MEMORY,
		MBW_START_HT_IU,//10
		MBW_WAIT_HT_IU
	};

	//internal signals
	sc_signal<sc_read_state_e>		sc_read_state;
	sc_signal<sc_write_state_e>		sc_write_state;
	sc_signal<mbsc_read_state_e>	mbsc_read_state;
	sc_signal<mbsc_write_state_e>	mbsc_write_state;
	sc_signal<bool>					start_mac_ic_s;
	sc_signal<bool>					start_ht_ic_s;
	sc_signal<bool>					start_ht_update;
	sc_signal<bool>					write_register_0_s;
	sc_signal<bool>					write_register_1_s;
	sc_signal<addr_t>				address_in_s;
	sc_signal<addr_t>				start_address_s;
	sc_signal<addr_t>				end_address_s;
	sc_signal<addr_t>				set_address_s;
	sc_signal<addr_t>				block_address_s;
	sc_signal<addr_t>				plen_s;
	sc_signal<bool>					pspe_s;
	sc_signal<unsigned int>			memory_cmd_id_s;
	sc_signal<unsigned int>			index_s;
	sc_signal<bool>					flush_register_1_s;
	sc_signal<bool>					flush_register_0_s;

	int *							plaintext_s;
	int *							ciphertext_s;
	int								be;
	int *							mask_s;
	bool							integrity_idle_v;
	bool							mb_integrity_idle_v;

public:
    //ports
	sc_in<bool>                         clk;
	sc_in<bool>                         reset;
	//block cipher if
	CRYPTOGRAPHIC_ENGINE_CMD_OUT        cb_out_cmd;
	DATA_OUT<2>                         cb_out_data;
	sc_in<bool>                         cb_in_ack;
	DATA_IN<2>                          cb_in_data;

	//regular access inteface
	SECURITY_CONTROLLER_IN              in;
	//master block access inteface
	MEMORY_CONTROLLER_CMD_IN            mb_in_cmd;
	DATA_IN<4>                          mb_in_wdata;
	ACK_OUT                             mb_out_ack;
	DATA_OUT<4>                         mb_out_rdata;
	//input security register if
	SECURITY_CONTEXT_REGISTER_READ_OUT  sc_register;
	//memory interface
	MEMORY_CONTROLLER_CMD_OUT           out_cmd;
	ACK_IN                              in_ack;
	//mac controller if
	INTEGRITY_CONTROLLER_CMD_OUT        mac_cmd_out;
	INTEGRITY_CONTROLLER_ACK_IN         mac_ack_in;
	//hash tree controller if
	INTEGRITY_CONTROLLER_CMD_OUT        hash_cmd_out;
	INTEGRITY_CONTROLLER_ACK_IN         hash_ack_in;
	//data register interfaces
	DATA_REGISTER_WRITE_OUT             register_0_out;
	DATA_REGISTER_READ_IN               register_0_in;
	DATA_REGISTER_WRITE_OUT             register_1_out;
	DATA_REGISTER_READ_IN               register_1_in;

	//Synchronous process
	void ps();
	//Conbinatory process
	void pc();

	void setBe(addr_t address);
	
	ofstream *output;

	//Constructor
	SecurityController(sc_module_name name, ofstream * file);

	SC_HAS_PROCESS(SecurityController);

};

#endif

