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

#include "types.h"
#include "global.h"
#include "buffer.h"

//------------------------------ Cache -------------------------------//
class Cache
{
public:
  //storage constructor
  Cache(const cache_param_s & parameters);
  ~Cache();

  bool lookup(addr_t address, pCacheblock_t &victim_block);
  uint32_t* readCache(addr_t address);

  //this function overwrite a block in cache
  void writeCache(addr_t address, uint32_t* data, int size);

  //this function replace a block in cache and either set its dirty bit or not
  void replace(addr_t address, uint32_t* data, bool dirty);

protected :
  //2-dim array of "Buffer" objects
  cacheblock_t  **storage;
  //Index of the hit block
  int           blockIndex;
  //cache parameters
  cache_param_s cache_param;

  int getSetIndex(addr_t address);
  // when a hit occurs on a read/write operation the hit block is
  // shifted at top of stack : lru policy
  void lru(addr_t address);
  //When a miss occurs on a write operation all the block are shifted
  void shift (addr_t address);
  //copy a source block to a target block
  void copyCacheBlock(cacheblock_t & TargetCacheBlock, 
		      cacheblock_t & SourceCacheBlock);
};

//------------------------------- SCCache --------------------------//
/*
class SCCache : 
public Cache
{
public:
  bool rlookup(addr_t address, pCacheblock_t &victim_block);

private :
  int *bdata;
  int baddress;
};
*/
//------------------------ ComplexCache -----------------------//

class ComplexCache
{
public:
  //set constructor
  ComplexCache(const cache_param_s & parameters);
  ~ComplexCache();

  bool lookup(addr_t address, bool & dirty);
  uint32_t* readCache(addr_t address);
  void writeCache(addr_t address, uint32_t* data);
  void storeCache(addr_t address, uint32_t* data, bool dirty);
  void cleanBlock(addr_t address);
  void freeBlock(addr_t address);
  void UpdSetCounter(addr_t address, bool inc);
  int readNHVdirty(addr_t address, addr_t & victime_address);

private:
  //Array of "Buffer" objects
  CacheSet_st_t *set;
  //Index of a block
  uint32_t      blockIndex;
  //cache parameters
  cache_param_s cache_param;

  int getSetIndex(addr_t address);
  //Look  for a free block (valid = 0) 
  bool getFreeblock(addr_t address);
  //Look  for a clean block (dirty = 0)
  bool getCleanblock(addr_t address);
  void fifo(addr_t address, int blockIndex);
  //copy an object of type Buffer
  void copyCacheBlock(cacheblock_t & TargetCacheBlock, 
		      cacheblock_t & SourceCacheBlock);

};

#endif
