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

#include "cache.h"
#include "types.h"
#include "global.h"
#include "buffer.h"
#include "systemc.h"
#include "secbus_lib.h"
#include "my_interfaces.h"
#include <iostream>

//--------------------------------------------------------------------- MacCacheController ------------------------------------------------------//

SC_MODULE(MacCacheController)
{

  public:

    sc_in<bool>					clk;
    sc_in<bool>					reset;
    //internal interface
    CACHE_CONTROLLER_CMD_IN   in_cmd;
    DATA_IN <2>               in_wdata;
    CACHE_CONTROLLER_ACK_OUT  out_ack;
    DATA_OUT <2>              out_rdata;
    //memory interface
    MEMORY_CONTROLLER_CMD_OUT out_cmd;
    DATA_OUT <2>              out_wdata;
    ACK_IN                    in_ack;
    DATA_REGISTER_READ_IN     register_2_in;


    enum cc_read_step_e
    {
      R_IDLE = 0,
      R_TEST_HIT_SIGNAL,
      R_START_READ_BLOCK,	
      R_WAIT_READ_BLOCK,
      R_START_WRITE_BACK_BLOCK,
      R_WAIT_WRITE_BACK_BLOCK
    };

    enum cc_write_step_e
    {
      W_IDLE = 0,
      W_TEST_HIT_SIGNAL,
      W_START_WRITE_BLOCK,//2
      W_START_WRITE_THROUGH_BLOCK,
      W_START_WRITE_BACK_BLOCK,//4
      W_WAIT_WRITE_BLOCK,
      W_WAIT_WRITE_THROUGH_BLOCK,//6
      W_WAIT_WRITE_BACK_BLOCK

    };

    //internal signals
    sc_signal<cc_read_step_e> read_state;
    sc_signal<cc_write_step_e> write_state;
    sc_signal<addr_t> address_in_s;
    sc_signal<addr_t> address_256_s;
    sc_signal<unsigned int> index_s;

    //instantiation of memory elements
    Cache * cache0;
    int * block_s;

    //others
    cache_param_st cache_param;
    bool hit_s;
    pCacheblock_t victim_block;

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

    //cache statistics
    uint64_t read_misses;
    uint64_t write_misses;
    uint64_t write_back;
    uint64_t read_accesses;
    uint64_t write_accesses;


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

    //Constructor
    MacCacheController(sc_module_name name, const cache_param_st & parameters, ofstream * file);

    SC_HAS_PROCESS(MacCacheController);

};

//-------------------------------------------------------------PspeCacheController ------------------------------------------------------//

SC_MODULE(PspeCacheController)
{

  public:

    sc_in<bool>               clk;
    sc_in<bool>               reset;
    //internal interface
    CACHE_CONTROLLER_CMD_IN   in_cmd;
    DATA_IN <2>               in_wdata;
    CACHE_CONTROLLER_ACK_OUT  out_ack;
    DATA_OUT <2>              out_rdata;
    //memory interface
    MEMORY_CONTROLLER_CMD_OUT out_cmd;
    DATA_OUT <2>              out_wdata;
    ACK_IN                    in_ack;
    DATA_IN <2>               in_rdata;


    enum cc_read_step_e
    {
      R_IDLE = 0,
      R_START_READ_BLOCK,	
      R_WAIT_READ_BLOCK,
      R_START_WRITE_BACK_BLOCK,
      R_WAIT_WRITE_BACK_BLOCK
    };

    enum cc_write_step_e
    {
      W_IDLE = 0,
      W_TEST_HIT_SIGNAL,
      W_START_WRITE_BLOCK,//2
      W_START_WRITE_THROUGH_BLOCK,
      W_START_WRITE_BACK_BLOCK,//4
      W_WAIT_WRITE_BLOCK,
      W_WAIT_WRITE_THROUGH_BLOCK,//6
      W_WAIT_WRITE_BACK_BLOCK

    };

    //internal signals
    sc_signal<cc_read_step_e>  read_state;
    sc_signal<cc_write_step_e> write_state;
    sc_signal<addr_t>          address_in_s;
    sc_signal<addr_t>          address_256_s;
    sc_signal<unsigned int>    index_s;

    //instantiation of memory elements
    Cache * cache0;
    int * block_s;

    //others
    cache_param_st cache_param;
    bool hit_s;
    pCacheblock_t victim_block;

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

    //cache statistics
    uint64_t read_misses;
    uint64_t write_misses;
    uint64_t write_back;
    uint64_t read_accesses;
    uint64_t write_accesses;


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


    //Constructor
    PspeCacheController(sc_module_name name, const cache_param_st & parameters, ofstream * file);

    SC_HAS_PROCESS(PspeCacheController);

};

//---------------------------------------------------------------SpCacheController ------------------------------------------------------//

SC_MODULE(SpCacheController)
{

  public:

    sc_in<bool>               clk;
    sc_in<bool>               reset;
    //internal interface
    CACHE_CONTROLLER_CMD_IN   in_cmd;
    DATA_IN <4>               in_wdata;
    CACHE_CONTROLLER_ACK_OUT  out_ack;
    DATA_OUT <4>              out_rdata;
    //memory interface
    MEMORY_CONTROLLER_CMD_OUT out_cmd;
    DATA_OUT <4>              out_wdata;
    ACK_IN                    in_ack;
    DATA_IN <4>               in_rdata;


    enum cc_read_step_e
    {
      R_IDLE = 0,
      R_TEST_HIT_SIGNAL,
      R_START_READ_BLOCK,	
      R_WAIT_READ_BLOCK,
      R_START_WRITE_BACK_BLOCK,
      R_WAIT_WRITE_BACK_BLOCK
    };

    enum cc_write_step_e
    {
      W_IDLE = 0,
      W_TEST_HIT_SIGNAL,
      W_START_WRITE_BLOCK,//2
      W_START_WRITE_THROUGH_BLOCK,
      W_START_WRITE_BACK_BLOCK,//4
      W_WAIT_WRITE_BLOCK,
      W_WAIT_WRITE_THROUGH_BLOCK,//6
      W_WAIT_WRITE_BACK_BLOCK

    };

    //internal signals
    sc_signal<cc_read_step_e>  read_state;
    sc_signal<cc_write_step_e> write_state;
    sc_signal<addr_t>          address_in_s;
    sc_signal<addr_t>          address_256_s;
    sc_signal<unsigned int>    index_s;

    //instantiation of memory elements
    Cache * cache0;
    int * block_s;

    //others
    cache_param_st cache_param;
    bool hit_s;
    pCacheblock_t victim_block;

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

    //cache statistics
    uint64_t read_misses;
    uint64_t write_misses;
    uint64_t write_back;
    uint64_t read_accesses;
    uint64_t write_accesses;


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


    //Constructor
    SpCacheController(sc_module_name name, const cache_param_st & parameters, ofstream * file);
    ofstream *output;

    SC_HAS_PROCESS(SpCacheController);

};

//---------------------------------------------------------------HashCacheConrtoller ------------------------------------------------------//

SC_MODULE(HashCacheController)
{

  sc_in<bool>               clk;
  sc_in<bool>               reset;
  //input inteface
  CACHE_CONTROLLER_CMD_IN   in_cmd;
  DATA_IN <2>               in_wdata;
  CACHE_CONTROLLER_ACK_OUT  out_ack;
  DATA_OUT <2>              out_rdata;
  //output interfaces
  MEMORY_CONTROLLER_CMD_OUT out_cmd;
  DATA_OUT <2>              out_wdata;
  ACK_IN                    in_ack;
  DATA_REGISTER_READ_IN     register_2_in;

  enum rd_state_e
  {
    RD_IDLE = 0,
    RD_TEST_HIT_SIGNAL,
    RD_START_READ_BLOCK,	
    RD_WAIT_READ_BLOCK

  };
  enum i_state_e
  {
    I_IDLE = 0,
    I_TEST_HIT_SIGNAL
  };
  enum s_state_e
  {
    S_IDLE = 0,
    S_TEST_HIT_SIGNAL,
    S_START_READ_BLOCK,//4	
    S_START_WRITE_BLOCK,
    S_WAIT_WRITE_BLOCK,
    S_WAIT_READ_BLOCK
  };
  enum rst_state_e
  {
    RST_IDLE = 0,
    RST_TEST_HIT_SIGNAL,
    RST_START_RESTORE,
    RST_WAIT_RESTORE,
    RST_START_READ_BLOCK,
    RST_WAIT_READ_BLOCK,
    RST_WRITE_CACHE

  };
  enum wr_state_e
  {
    WR_IDLE = 0,
    WR_TEST_HIT_SIGNAL,
    WR_TEST_FULL_SIGNAL,
    WR_WRITE_CACHE
  };

  //internal signals

  sc_signal<i_state_e> i_state;
  sc_signal<s_state_e> s_state;
  sc_signal<rd_state_e> rd_state;
  sc_signal<rst_state_e> rst_state;
  sc_signal<wr_state_e> wr_state;
  sc_signal<addr_t> address_in_s;
  sc_signal<addr_t> address_256_s;
  sc_signal<unsigned int> index_s;
  addr_t victim_address_s;
  bool hit_s;
  bool dirty_s;
  bool full_s;

  //instantiation of memory elements
  ComplexCache * cache0;
  int * block_s;

  //others
  cache_param_st cache_param;

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

  //cache statistics
  uint64_t invalidate_accesses;
  uint64_t read_accesses;
  uint64_t write_accesses;
  uint64_t restore_accesses;
  uint64_t synchronize_accesses;
  uint64_t read_misses;
  uint64_t write_misses;
  uint64_t restore_misses;
  uint64_t synchronize_misses;



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

  //Constructor
  HashCacheController(sc_module_name name, const cache_param_st & parameters, ofstream * file);

  SC_HAS_PROCESS(HashCacheController);

};

#endif
