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


#include "secbus_lib.h"
#include <systemc>
#include "types.h"
#include "cryptolib.h"
#include "my_interfaces.h"

SC_MODULE(MacController)
{

  public:

    sc_in<bool>                         clk;
    sc_in<bool>                         reset;
    //input inteface
    INTEGRITY_CONTROLLER_CMD_IN         cmd_in;
    INTEGRITY_CONTROLLER_ACK_OUT        ack_out;
    //mac cache controller if
    CACHE_CONTROLLER_CMD_OUT            cache_out_cmd;
    DATA_OUT<2>                         cache_out_wdata;
    CACHE_CONTROLLER_ACK_IN             cache_in_ack;
    DATA_IN<2>                          cache_in_rdata;
    //mac generator if
    CRYPTOGRAPHIC_ENGINE_CMD_OUT        mac_generator_out_cmd;
    DATA_OUT<12>                        mac_generator_out_data;
    DATA_OUT<2>                         mac_generator_out_iv;
    sc_in<bool>                         mac_generator_in_ack;
    DATA_IN<2>                          mac_generator_in_data;
    //mac engine is able to read security context registers
    SECURITY_CONTEXT_REGISTER_READ_OUT  sc_register;
    //register 1
    DATA_REGISTER_READ_IN               register_1_in;
    //register 2
    DATA_REGISTER_READ_IN               register_2_in;
    //memory interface for initialisation
    MEMORY_CONTROLLER_CMD_OUT           memory_out_cmd;
    DATA_OUT <2>                        memory_out_wdata;
    ACK_IN                              memory_in_ack;


    enum mc_step_e
    {
      IDLE = 0,
      //check
      C_START_IV_GENERATION, 
      C_START_MAC_GENERATION, 
      C_WAIT_MAC_GENERATION, 
      C_START_READ_PARENT,
      C_WAIT_READ_PARENT,
      //update
      U_START_UPDATE_PARENT,
      U_WAIT_UPDATE_PARENT,
      U_START_WRITE_PARENT,
      U_WAIT_WRITE_PARENT,
      //initialize
      I_START_READ_SET, //7
      I_START_MAC_GENERATION,
      I_WAIT_MAC_GENERATION,
      I_START_WRITE_PARENT,
      I_WAIT_WRITE_PARENT,
      //
      MAC_INTEGRITY_ERROR
    };

    //internal signals
    sc_signal<mc_step_e> state;
    sc_signal<addr_t> set_address_s;
    sc_signal<unsigned int> index_s;
    sc_signal<addr_t> mac_start_address_s;
    sc_signal<addr_t> mac_address_s;
    sc_signal<PageSize_e> mac_page_size_s;
    sc_signal<integrity_cmd_e> cmd_in_s;

    int *key_s;
    int *mac_s;
    int *reference_mac_s;

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


    ofstream *output;
    bool cache_enabled;
    unsigned long int mac_count;

    void print_stats(ofstream & file);
    void reset_stats();

    //Constructor
    MacController(sc_module_name name, ofstream * file, bool mac_cache_enabled);

    SC_HAS_PROCESS(MacController);

};

#endif

