#ifndef IOB_TRANSACTION_H_
#define IOB_TRANSACTION_H_
 
#include <inttypes.h>
#include <systemc>
#include <cassert>
#include "arithmetics.h"

#define DEBUG_IOB_TRANSACTION 0

// The index of Transaction Tab Entry corresponds to the trdid of the VCI packet on XRAM network

////////////////////////////////////////////////////////////////////////
//                  A transaction tab entry         
////////////////////////////////////////////////////////////////////////

class TransactionTabIOEntry {
  typedef uint32_t              size_t;

 public:
  bool 		            valid;     	    // entry valid 
  size_t 	            srcid;     	    // processor requesting the transaction
  size_t 	            trdid;     	    // processor requesting the transaction

  /////////////////////////////////////////////////////////////////////
  // The init() function initializes the entry 
  /////////////////////////////////////////////////////////////////////
  void init()
  {
    valid		= false;
  }

  ////////////////////////////////////////////////////////////////////
  // The copy() function copies an existing entry
  // Its arguments are :
  // - source : the transaction tab entry to copy
  ////////////////////////////////////////////////////////////////////
  void copy(const TransactionTabIOEntry &source)
  {
    valid	    = source.valid;
    srcid	    = source.srcid;
    trdid	    = source.trdid;
  }

  ////////////////////////////////////////////////////////////////////
  // The print() function prints the entry 
  ////////////////////////////////////////////////////////////////////
  void print(){
    std::cout << "valid       = " << valid        << std::endl;
    std::cout << "srcid       = " << srcid        << std::endl;
    std::cout << "trdid       = " << trdid        << std::endl;
  }

  /////////////////////////////////////////////////////////////////////
  // 		Constructors
  /////////////////////////////////////////////////////////////////////

  TransactionTabIOEntry()
    {
      valid=false;
    }

  TransactionTabIOEntry(const TransactionTabIOEntry &source){
    valid	    = source.valid;
    srcid	    = source.srcid;
    trdid	    = source.trdid;
  }

}; // end class TransactionTabIOEntry

////////////////////////////////////////////////////////////////////////
//                  The transaction tab                              
////////////////////////////////////////////////////////////////////////
class TransactionTabIO{
//  typedef uint32_t size_t;

 private:
  size_t size_tab;                // The size of the tab

 public:
  TransactionTabIOEntry *tab;       // The transaction tab

  ////////////////////////////////////////////////////////////////////
  //		Constructors
  ////////////////////////////////////////////////////////////////////
  TransactionTabIO()
    {
      size_tab=0;
      tab=NULL;
    }

  TransactionTabIO(size_t n_entries)
    {
      size_tab = n_entries;
      tab = new TransactionTabIOEntry[size_tab];
    }

  ~TransactionTabIO()
    {
      delete [] tab;
    }

  /////////////////////////////////////////////////////////////////////
  // The size() function returns the size of the tab
  /////////////////////////////////////////////////////////////////////
  size_t size()
  {
    return size_tab;
  }

  /////////////////////////////////////////////////////////////////////
  // The init() function initializes the transaction tab entries
  /////////////////////////////////////////////////////////////////////
  void init()
  {
    for ( size_t i=0; i<size_tab; i++) {
      tab[i].init();
    }
  }

  /////////////////////////////////////////////////////////////////////
  // The print() function prints a transaction tab entry
  // Arguments :
  // - index : the index of the entry to print
  /////////////////////////////////////////////////////////////////////
  void print(const size_t index)
  {
    assert( (index < size_tab) 
	    && "Invalid Transaction Tab Entry");
    tab[index].print();
    return;
  }

  /////////////////////////////////////////////////////////////////////
  // The read() function returns a transaction tab entry.
  // Arguments :
  // - index : the index of the entry to read
  /////////////////////////////////////////////////////////////////////
  TransactionTabIOEntry read(const size_t index)
  {
    assert( (index < size_tab) 
	    && "Invalid Transaction Tab Entry");
    return tab[index];
  }
  
  /////////////////////////////////////////////////////////////////////
  // The readSrcid() function returns the srcid field of a transaction tab entry.
  // Arguments :
  // - index : the index of the entry to read
  /////////////////////////////////////////////////////////////////////
  size_t readSrcid(const size_t index)
  {
    assert( (index < size_tab) 
	    && "Invalid Transaction Tab Entry");
    return tab[index].srcid;
  }

  /////////////////////////////////////////////////////////////////////
  // The readTrdid() function returns the trdid field of a transaction tab entry.
  // Arguments :
  // - index : the index of the entry to read
  /////////////////////////////////////////////////////////////////////
  size_t readTrdid(const size_t index)
  {
    assert( (index < size_tab) 
	    && "Invalid Transaction Tab Entry");
    return tab[index].trdid;
  }

  /////////////////////////////////////////////////////////////////////
  // The full() function returns the state of the transaction tab
  // Arguments :
  // - index : (return argument) the index of an empty entry 
  // The function returns true if the transaction tab is full
  /////////////////////////////////////////////////////////////////////
  bool full(size_t &index)
  {
    for(size_t i=0; i<size_tab; i++){
      if(!tab[i].valid){
	    index=i;
	    return false;	
      }
    }
    return true;
  }

  /////////////////////////////////////////////////////////////////////
  // The set() function registers a transaction (read or write)
  // to the XRAM in the transaction tab.
  // Arguments :
  // - index : index in the transaction tab
  // - srcid : srcid of the initiator that caused the transaction
  // - trdid : trdid of the initiator that caused the transaction
  /////////////////////////////////////////////////////////////////////
  void set(const size_t index,
	   const size_t srcid,
	   const size_t trdid) 
  {
    assert( (index < size_tab) 
	    && "The selected entry is out of range in set() Transaction Tab");

    tab[index].valid	        = true;
    tab[index].srcid	        = srcid;
    tab[index].trdid	        = trdid;
  }

  /////////////////////////////////////////////////////////////////////
  // The erase() function erases an entry in the transaction tab.
  // Arguments :
  // - index : the index of the request in the transaction tab
  /////////////////////////////////////////////////////////////////////
  void erase(const size_t index)
  {
    assert( (index < size_tab) 
	    && "The selected entry is out of range in erase() Transaction Tab");
    tab[index].valid	= false;
  }
}; // end class TransactionTabIO

#endif

// Local Variables:
// tab-width: 4
// c-basic-offset: 4
// c-file-offsets:((innamespace . 0)(inline-open . 0))
// indent-tabs-mode: nil
// End:

// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4

