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

#include <string.h>

typedef uint32_t addr_t;
class Buffer
{
public:
  //provide Buffer parameters to the Buffer constructor

  Buffer(){}
  ~Buffer(){};

  void reset()
  {
    base_address = 0xFFFFFFFF;
    rstDirty();
    rstData();
    rstValid();
  }

  void init(uint32_t size)
  {
    buffer_size = size;
    data        = new uint32_t[size];

    reset();
  }

  int getBaseAddress()
  {
    return base_address;
  }

  void setBaseAddress(addr_t baseAddress)
  {
    base_address = baseAddress;
  }

  bool lookup(addr_t address)
  //check if address is in buffer
  {
    addr_t aligned_address = address - address %(sizeof(int)*buffer_size);
    return (base_address == aligned_address);
  }

  uint32_t* getData()
  //get the address of first value in Buffer
  {
    return data;
  }

  uint32_t* rData(addr_t address)
  //read Buffer at a specific address
  {
    //get index of block in set
    int index = getIndex(address);

    return (data + index);
  }

  void wData(uint32_t* new_data, bool _dirty)
  //Replace the whole Buffer
  {
    memcpy(data, new_data, buffer_size*sizeof(int));
    dirty = _dirty;
  }

  void rstData()
  //set all data to 0
  {
    memset(data, 0x0, buffer_size*sizeof(int)); 
  }

  void rstDirty()
  //reset dirty
  {
    dirty = false; 
  }

  void rstValid()
  //reset dirty
  {
    valid = false; 
  }

  void setDirty()
  //set dirty
  {
    dirty = true;
  }

  void setValid(bool v)
  //set dirty
  {
    valid = v;
  }

  bool isDirty()
  //return dirty
  {
    return dirty;
  }

  bool isValid()
  //return dirty
  {
    return valid;
  }

protected :
  addr_t   base_address;	
  uint32_t *data;
  bool     dirty;
  bool     valid;	
  uint32_t buffer_size;

  uint32_t getIndex(addr_t address)
  {
    return ((address % (buffer_size*sizeof(int)))/sizeof(int));
  }
};

#endif
