Index: /trunk/modules/vci_mem_cache_v2s/caba/metadata/vci_mem_cache_v2s.sd
===================================================================
--- /trunk/modules/vci_mem_cache_v2s/caba/metadata/vci_mem_cache_v2s.sd	(revision 41)
+++ /trunk/modules/vci_mem_cache_v2s/caba/metadata/vci_mem_cache_v2s.sd	(revision 41)
@@ -0,0 +1,47 @@
+
+# -*- python -*-
+
+__id__ = "$Id: vci_mem_cache_v2s.sd 20 2010-04-14 03:27:59Z nipo $"
+__version__ = "$Revision: 20 $"
+
+Module('caba:vci_mem_cache_v2s',
+       classname = 'soclib::caba::VciMemCacheV2S',
+       tmpl_parameters = [parameter.Module('vci_param', default = 'caba:vci_param'),],
+       header_files = ['../source/include/vci_mem_cache_v2s.h',
+                       '../source/include/xram_transaction_v2.h',
+                       '../source/include/mem_cache_directory_v2.h',
+                       '../source/include/atomic_tab_v2.h',
+                       '../source/include/update_tab_v2.h',],
+       implementation_files = ['../source/src/vci_mem_cache_v2s.cpp',],
+       uses = [Uses('caba:base_module'),
+               Uses('common:loader'),
+               Uses('common:mapping_table'),
+               Uses('caba:generic_fifo'),
+               ],
+       ports = [Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:vci_target','p_vci_tgt_cleanup'),
+		Port('caba:vci_initiator','p_vci_ini'),
+		Port('caba:vci_initiator','p_vci_ixr'),
+                Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+                Port('caba:clock_in', 'p_clk', auto = 'clock'),],
+       instance_parameters = [
+		parameter.Module('mtp', 'common:mapping_table'),
+		parameter.Module('mtc', 'common:mapping_table'),
+		parameter.Module('mtx', 'common:mapping_table'),
+		parameter.IntTab('vci_ixr_index'),
+		parameter.IntTab('vci_ini_index'),
+		parameter.IntTab('vci_tgt_index'),
+		parameter.IntTab('vci_tgt_index_cleanup'),
+       		parameter.Int('nways'),
+		parameter.Int('nsets'),
+		parameter.Int('nwords'),
+		],
+       extensions = [
+          'dsx:get_ident='
+          'vci_ini_index:p_vci_ini:mtc,'
+          'vci_tgt_index_cleanup:p_vci_tgt_cleanup:mtc,'
+          'vci_tgt_index:p_vci_tgt:mtp,'
+          'vci_ixr_index:p_vci_ixr:mtx',
+		'dsx:addressable=vci_tgt_index,vci_tgt_index_cleanup',
+       ],
+)
Index: /trunk/modules/vci_mem_cache_v2s/caba/source/include/atomic_tab_v2.h
===================================================================
--- /trunk/modules/vci_mem_cache_v2s/caba/source/include/atomic_tab_v2.h	(revision 41)
+++ /trunk/modules/vci_mem_cache_v2s/caba/source/include/atomic_tab_v2.h	(revision 41)
@@ -0,0 +1,122 @@
+#ifndef ATOMIC_TAB_V2_H_
+#define ATOMIC_TAB_V2_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+/*                  The atomic access tab                             */
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+class AtomicTab{
+    typedef uint32_t size_t;
+    typedef sc_dt::sc_uint<40> addr_t;
+
+private:
+    size_t size_tab;                            // The size of the tab
+    std::vector<addr_t> addr_tab;               // Address entries
+    std::vector<bool>   valid_tab;              // Valid entries
+
+public:
+
+    AtomicTab()
+	: addr_tab(0),
+	  valid_tab(0)
+	{
+    	size_tab=0;
+    }
+
+    AtomicTab(size_t size_tab_i)
+	: addr_tab(size_tab_i),
+	  valid_tab(size_tab_i)
+	{
+	    size_tab=size_tab_i;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The size() function returns the size of the tab */
+    /////////////////////////////////////////////////////////////////////
+    const 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++) {
+		    addr_tab[i]=0;
+		    valid_tab[i]=false;
+    	}
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The set() function sets an entry 
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void set(const size_t id, const addr_t addr){
+	    assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	    addr_tab[id]=addr;
+	    valid_tab[id]=true;
+	    return;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The isatomic() function tests if the SC request corresponds to an entry
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+
+       This function return true if the request corresponds
+     */
+    /////////////////////////////////////////////////////////////////////
+    bool isatomic(const size_t id, const addr_t addr){
+	    assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	    bool test=valid_tab[id];
+	    test=test && (addr == addr_tab[id]);
+	    return test;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The reset() function resets all the entries for this lock
+       Arguments :
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void reset(const addr_t addr){
+	    for(size_t i=0 ; i<size_tab ; i++){
+		    if(addr == addr_tab[i]){
+			    valid_tab[i]=false;
+std::cout << std::hex << "inval @:" << addr << std::endl;
+		    }
+	    }
+	    return;
+    }
+
+};
+ 
+#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
+
Index: /trunk/modules/vci_mem_cache_v2s/caba/source/include/mem_cache_directory_v2.h
===================================================================
--- /trunk/modules/vci_mem_cache_v2s/caba/source/include/mem_cache_directory_v2.h	(revision 41)
+++ /trunk/modules/vci_mem_cache_v2s/caba/source/include/mem_cache_directory_v2.h	(revision 41)
@@ -0,0 +1,311 @@
+#ifndef SOCLIB_CABA_MEM_CACHE_DIRECTORY_V2_H
+#define SOCLIB_CABA_MEM_CACHE_DIRECTORY_V2_H 
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+namespace soclib { namespace caba {
+
+  using namespace sc_core;
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A LRU entry 
+  ////////////////////////////////////////////////////////////////////////
+  class LruEntry {
+
+    public:
+
+      bool recent;            
+
+      void init()
+      {
+        recent=false;
+      }
+
+  }; // end class LruEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A directory entry                               
+  ////////////////////////////////////////////////////////////////////////
+  class DirectoryEntry {
+
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+    typedef uint32_t copy_t;
+
+    public:
+
+    bool    valid;                  // entry valid
+    bool    is_cnt;                 // directory entry is a counter
+    bool    dirty;                  // entry dirty
+    bool    lock;                   // entry locked
+    tag_t   tag;                    // tag of the entry
+    copy_t  d_copies;               // vector of copies for data
+    copy_t  i_copies;               // vector of copies for instructions
+    size_t  count;                  // number of copies
+
+    DirectoryEntry()
+    {
+      valid    = false;
+      is_cnt   = false;
+      dirty    = false;
+      lock     = false;
+      tag      = 0;
+      d_copies = 0;
+      i_copies = 0;
+      count    = 0;
+    }
+
+    DirectoryEntry(const DirectoryEntry &source)
+    {
+      valid    = source.valid;
+      is_cnt   = source.is_cnt;
+      dirty    = source.dirty;
+      tag      = source.tag;
+      lock     = source.lock;
+      d_copies = source.d_copies;
+      i_copies = source.i_copies;
+      count    = source.count;
+    }          
+
+    /////////////////////////////////////////////////////////////////////
+    // The init() function initializes the entry 
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      valid = false;
+      is_cnt= false;
+      dirty = false;
+      lock  = false;
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    // The copy() function copies an existing source entry to a target 
+    /////////////////////////////////////////////////////////////////////
+    void copy(const DirectoryEntry &source)
+    {
+      valid	= source.valid;
+      is_cnt    = source.is_cnt;
+      dirty	= source.dirty;
+      tag	= source.tag;
+      lock	= source.lock;
+      d_copies	= source.d_copies;
+      i_copies	= source.i_copies;
+      count     = source.count;
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // The print() function prints the entry 
+    ////////////////////////////////////////////////////////////////////
+    void print()
+    {
+      std::cout << "Valid = " << valid << " ; IS COUNT = " << is_cnt << " ; Dirty = " << dirty << " ; Lock = " 
+        << lock << " ; Tag = " << std::hex << tag << " ; d_copies = " << d_copies << " ; i_copies = " << i_copies << " ; count = " << count << std::endl;
+    }
+
+  }; // end class DirectoryEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                       The directory  
+  ////////////////////////////////////////////////////////////////////////
+  class CacheDirectory {
+
+    typedef sc_dt::sc_uint<40> addr_t;
+    typedef uint32_t data_t;
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+
+    private:
+
+    // Directory constants
+    size_t					m_ways;
+    size_t					m_sets;
+    size_t					m_words;
+    size_t					m_width;
+
+    // the directory & lru tables
+    DirectoryEntry 				**m_dir_tab;
+    LruEntry	 				**m_lru_tab;
+
+    public:
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+    CacheDirectory( size_t ways, size_t sets, size_t words, size_t address_width)	 
+    {
+      m_ways  = ways; 
+      m_sets  = sets;
+      m_words = words;
+      m_width = address_width;
+
+      m_dir_tab = new DirectoryEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_dir_tab[i] = new DirectoryEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_dir_tab[i][j].init();
+      }
+      m_lru_tab = new LruEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_lru_tab[i] = new LruEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_lru_tab[i][j].init();
+      }
+    } // end constructor
+
+    /////////////////
+    // Destructor
+    /////////////////
+    ~CacheDirectory()
+    {
+      for(size_t i=0 ; i<m_sets ; i++){
+        delete [] m_dir_tab[i];
+        delete [] m_lru_tab[i];
+      }
+      delete [] m_dir_tab;
+      delete [] m_lru_tab;
+    } // end destructor
+
+    /////////////////////////////////////////////////////////////////////
+    // The read() function reads a directory entry. In case of hit, the
+    // LRU is updated.
+    // Arguments :
+    // - address : the address of the entry 
+    // - way : (return argument) the way of the entry in case of hit
+    // The function returns a copy of a (valid or invalid) entry  
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry read(const addr_t &address,size_t &way)
+    {
+
+#define L2 soclib::common::uint32_log2
+      const size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
+      const tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
+#undef L2
+
+      bool hit       = false;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        bool equal = ( m_dir_tab[set][i].tag == tag );
+        bool valid = m_dir_tab[set][i].valid;
+        hit = equal && valid;
+        if ( hit ) {			
+          way = i;
+          break;
+        } 
+      }
+      if ( hit ) {
+        m_lru_tab[set][way].recent = true;
+        return DirectoryEntry(m_dir_tab[set][way]);
+      } else {
+        return DirectoryEntry();
+      }
+    } // end read()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write function writes a new entry, 
+    // and updates the LRU bits if necessary.
+    // Arguments :
+    // - set : the set of the entry
+    // - way : the way of the entry
+    // - entry : the entry value
+    /////////////////////////////////////////////////////////////////////
+    void write(const size_t &set, const size_t &way, const DirectoryEntry &entry)
+    {
+      assert( (set<m_sets) 
+          && "Cache Directory write : The set index is invalid");
+      assert( (way<m_ways) 
+          && "Cache Directory write : The way index is invalid");
+
+      // update Directory
+      m_dir_tab[set][way].copy(entry);
+
+      // update LRU bits
+      bool all_recent = true;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
+      }
+      if ( all_recent ) {
+        for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
+      } else {
+        m_lru_tab[set][way].recent = true;
+      }
+    } // end write()
+
+    /////////////////////////////////////////////////////////////////////
+    // The print() function prints a selected directory entry
+    // Arguments :
+    // - set : the set of the entry to print
+    // - way : the way of the entry to print
+    /////////////////////////////////////////////////////////////////////
+    void print(const size_t &set, const size_t &way)
+    {
+      std::cout << std::dec << " set : " << set << " ; way : " << way << " ; " ;
+      m_dir_tab[set][way].print();
+    } // end print()
+
+    /////////////////////////////////////////////////////////////////////
+    // The select() function selects a directory entry to evince.
+    // Arguments :
+    // - set   : (input argument) the set to modify
+    // - way   : (return argument) the way to evince
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry select(const size_t &set, size_t &way)
+    {
+      assert( (set < m_sets) 
+          && "Cache Directory : (select) The set index is invalid");
+
+      for(size_t i=0; i<m_ways; i++){
+        if(!m_dir_tab[set][i].valid){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if(!(m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( !(m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( (m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      way = 0;
+      return DirectoryEntry(m_dir_tab[set][0]);
+    } // end select()
+
+    /////////////////////////////////////////////////////////////////////
+    // 		Global initialisation function
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      for ( size_t set=0 ; set<m_sets ; set++ ) {
+        for ( size_t way=0 ; way<m_ways ; way++ ) {
+          m_dir_tab[set][way].init();
+          m_lru_tab[set][way].init();
+        }
+      }
+    } // end init()
+
+  }; // end class CacheDirectory
+
+}} // end namespaces
+
+#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
+
Index: /trunk/modules/vci_mem_cache_v2s/caba/source/include/update_tab_v2.h
===================================================================
--- /trunk/modules/vci_mem_cache_v2s/caba/source/include/update_tab_v2.h	(revision 41)
+++ /trunk/modules/vci_mem_cache_v2s/caba/source/include/update_tab_v2.h	(revision 41)
@@ -0,0 +1,402 @@
+#ifndef UPDATE_TAB_V2_H_
+#define UPDATE_TAB_V2_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+////////////////////////////////////////////////////////////////////////
+//                  An update tab entry    
+////////////////////////////////////////////////////////////////////////
+class UpdateTabEntry {
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  public:
+  bool 	valid;                // It is a valid pending transaction
+  bool	update;               // It is an update transaction
+  bool  brdcast;              // It is a broadcast invalidate
+  bool  rsp;                  // It needs a response to the initiator
+  size_t 	srcid;        // The srcid of the initiator which wrote the data
+  size_t 	trdid;        // The trdid of the initiator which wrote the data
+  size_t 	pktid;        // The pktid of the initiator which wrote the data
+  addr_t	nline;	      // The identifier of the cache line
+  size_t 	count;        // The number of acknowledge responses to receive
+
+  UpdateTabEntry(){
+    valid	= false;
+    update  = false;
+    brdcast = false;
+    rsp     = false;
+    srcid	= 0;
+    trdid	= 0;
+    pktid	= 0;
+    nline	= 0;
+    count	= 0;
+  }
+
+  UpdateTabEntry(bool   i_valid, 
+      bool   i_update,
+      bool   i_brdcast,
+      bool   i_rsp,
+      size_t i_srcid, 
+      size_t i_trdid, 
+      size_t i_pktid, 
+      addr_t i_nline,
+      size_t i_count) 
+  {
+    valid		= i_valid;
+    update	    = i_update;
+    brdcast     = i_brdcast;
+    rsp         = i_rsp;
+    srcid		= i_srcid;
+    trdid		= i_trdid;
+    pktid		= i_pktid;
+    nline		= i_nline;
+    count		= i_count;
+  }
+
+  UpdateTabEntry(const UpdateTabEntry &source)
+  {
+    valid   = source.valid;
+    update  = source.update;
+    brdcast = source.brdcast;
+    rsp     = source.rsp;
+    srcid   = source.srcid;
+    trdid   = source.trdid;
+    pktid   = source.pktid;
+    nline   = source.nline;
+    count   = source.count;
+  }
+
+  ////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  ///////////////////////////////////////////////////
+  void init()
+  {
+    valid  = false;
+    update = false;
+    brdcast= false;
+    rsp    = false;
+    srcid  = 0;
+    trdid  = 0;
+    pktid  = 0;
+    nline  = 0;
+    count  = 0;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the update tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const UpdateTabEntry &source)
+  {
+    valid  = source.valid;
+    update = source.update;
+    brdcast= source.brdcast;
+    rsp    = source.rsp;
+    srcid  = source.srcid;
+    trdid  = source.trdid;
+    pktid  = source.pktid;
+    nline  = source.nline;
+    count  = source.count;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << std::dec << "valid  = " << valid  << std::endl;
+    std::cout << "update = " << update << std::endl;
+    std::cout << "brdcast= " << brdcast<< std::endl;
+    std::cout << "rsp    = " << rsp    << std::endl;
+    std::cout << "srcid  = " << srcid  << std::endl; 
+    std::cout << "trdid  = " << trdid  << std::endl; 
+    std::cout << "pktid  = " << pktid  << std::endl; 
+    std::cout << std::hex << "nline  = " << nline  << std::endl;
+    std::cout << std::dec << "count  = " << count  << std::endl;
+  }
+};
+
+////////////////////////////////////////////////////////////////////////
+//                        The update tab             
+////////////////////////////////////////////////////////////////////////
+class UpdateTab{
+
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  private:
+  size_t size_tab;
+  std::vector<UpdateTabEntry> tab;
+
+  public:
+
+  UpdateTab()
+    : tab(0)
+  {
+    size_tab=0;
+  }
+
+  UpdateTab(size_t size_tab_i)
+    : tab(size_tab_i)
+  {
+    size_tab=size_tab_i;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  const size_t size(){
+    return size_tab;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    for(size_t i=0; i<size_tab; i++) {
+      std::cout << "UPDATE TAB ENTRY " << std::dec << i << "--------" << std::endl;
+      tab[i].print();
+    }
+    return;
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the tab 
+  /////////////////////////////////////////////////////////////////////
+  void init(){
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The reads() function reads an entry 
+  // Arguments :
+  // - entry : the entry to read
+  // This function returns a copy of the entry.
+  /////////////////////////////////////////////////////////////////////
+  UpdateTabEntry read (size_t entry)
+  {
+    assert(entry<size_tab && "Bad Update Tab Entry");
+    return UpdateTabEntry(tab[entry]);
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // The set() function writes an entry in the Update Table
+  // Arguments :
+  // - update : transaction type (bool)
+  // - srcid : srcid of the initiator
+  // - trdid : trdid of the initiator
+  // - pktid : pktid of the initiator
+  // - count : number of expected responses
+  // - index : (return argument) index of the selected entry
+  // This function returns true if the write successed (an entry was empty).
+  ///////////////////////////////////////////////////////////////////////////
+  bool set(const bool	update,
+      const bool   brdcast,
+      const bool   rsp,
+      const size_t srcid,
+      const size_t trdid,
+      const size_t pktid,
+      const addr_t nline,
+      const size_t count,
+      size_t &index)
+  {
+    for ( size_t i=0 ; i<size_tab ; i++ ) {
+      if( !tab[i].valid ) {
+        tab[i].valid		= true;
+        tab[i].update		= update;
+        tab[i].brdcast      = brdcast;
+        tab[i].rsp          = rsp;
+        tab[i].srcid		= (size_t) srcid;
+        tab[i].trdid		= (size_t) trdid;
+        tab[i].pktid		= (size_t) pktid;
+        tab[i].nline		= (addr_t) nline;
+        tab[i].count		= (size_t) count;
+        index			    = i;
+        return true;
+      }
+    }
+    return false;
+  } // end set()
+
+  /////////////////////////////////////////////////////////////////////
+  // The decrement() function decrements the counter for a given entry.
+  // Arguments :
+  // - index   : the index of the entry
+  // - counter : (return argument) value of the counter after decrement
+  // This function returns true if the entry is valid.
+  /////////////////////////////////////////////////////////////////////
+  bool decrement( const size_t index,
+      size_t &counter ) 
+  {
+    assert((index<size_tab) && "Bad Update Tab Entry");
+    if ( tab[index].valid ) {
+      tab[index].count--;
+      counter = tab[index].count;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_full() function returns true if the table is full
+  /////////////////////////////////////////////////////////////////////
+  bool is_full()
+  {
+    for(size_t i = 0 ; i < size_tab ; i++){
+      if(!tab[i].valid){
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The need_rsp() function returns the need of a response
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool need_rsp(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].rsp;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_brdcast(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].brdcast;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_update(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].update;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The srcid() function returns the srcid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t srcid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].srcid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The trdid() function returns the trdid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t trdid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].trdid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The pktid() function returns the pktid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t pktid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].pktid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The nline() function returns the nline value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  addr_t nline(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].nline;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The search_inval() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool search_inval(const addr_t nline,size_t &index)
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        if(!tab[i].update){
+          index = i ;
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read_nline() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool read_nline(const addr_t nline,size_t &index) 
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        index = i ;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The clear() function erases an entry of the tab
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////       
+  void clear(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    tab[index].valid=false;
+    return;	
+  }
+
+};
+
+#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
+
Index: /trunk/modules/vci_mem_cache_v2s/caba/source/include/vci_mem_cache_v2s.h
===================================================================
--- /trunk/modules/vci_mem_cache_v2s/caba/source/include/vci_mem_cache_v2s.h	(revision 41)
+++ /trunk/modules/vci_mem_cache_v2s/caba/source/include/vci_mem_cache_v2s.h	(revision 41)
@@ -0,0 +1,653 @@
+/* -*- c++ -*-
+ * File         : vci_mem_cache_v2s.h
+ * Date         : 26/10/2008
+ * Copyright    : UPMC / LIP6
+ * Authors      : Alain Greiner / Eric Guthmuller
+ *
+ * SOCLIB_LGPL_HEADER_BEGIN
+ *
+ * This file is part of SoCLib, GNU LGPLv2.1.
+ *
+ * SoCLib is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 of the License.
+ *
+ * SoCLib is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SoCLib; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * SOCLIB_LGPL_HEADER_END
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+/*
+ *
+ * Modifications done by Christophe Choichillon on the 7/04/2009:
+ * - Adding new states in the CLEANUP FSM : CLEANUP_UPT_LOCK and CLEANUP_UPT_WRITE
+ * - Adding a new VCI target port for the CLEANUP network
+ * - Adding new state in the ALLOC_UPT_FSM : ALLOC_UPT_CLEANUP
+ * 
+ * Modifications to do :
+ * - Adding new variables used by the CLEANUP FSM
+ *
+ */
+
+#ifndef SOCLIB_CABA_MEM_CACHE_V2S_H
+#define SOCLIB_CABA_MEM_CACHE_V2S_H
+
+#include <inttypes.h>
+#include <systemc>
+#include <list>
+#include <cassert>
+#include "arithmetics.h"
+#include "alloc_elems.h"
+#include "caba_base_module.h"
+#include "vci_target.h"
+#include "vci_initiator.h"
+#include "generic_fifo.h"
+#include "mapping_table.h"
+#include "int_tab.h"
+#include "mem_cache_directory_v2.h"
+#include "xram_transaction_v2.h"
+#include "update_tab_v2.h"
+#include "atomic_tab_v2.h"
+
+#define TRANSACTION_TAB_LINES 4     // Number of lines in the transaction tab
+#define UPDATE_TAB_LINES 4          // Number of lines in the update tab
+#define BROADCAST_ADDR 0x0000000003 // Address to send the broadcast invalidate
+
+namespace soclib {  namespace caba {
+  using namespace sc_core;
+
+  template<typename vci_param>
+    class VciMemCacheV2S
+    : public soclib::caba::BaseModule
+    {
+      typedef sc_dt::sc_uint<40> addr_t;
+      typedef typename vci_param::fast_addr_t vci_addr_t;
+      typedef uint32_t data_t;
+      typedef uint32_t tag_t;
+      typedef uint32_t size_t;
+      typedef uint32_t be_t;
+      typedef uint32_t copy_t;
+
+      /* States of the TGT_CMD fsm */
+      enum tgt_cmd_fsm_state_e{
+        TGT_CMD_IDLE,
+        TGT_CMD_READ,
+        TGT_CMD_READ_EOP,
+        TGT_CMD_WRITE,
+        TGT_CMD_ATOMIC,
+      };
+
+      /* States of the TGT_RSP fsm */
+      enum tgt_rsp_fsm_state_e{
+        TGT_RSP_READ_IDLE,
+        TGT_RSP_WRITE_IDLE,
+        TGT_RSP_LLSC_IDLE,
+        TGT_RSP_XRAM_IDLE,
+        TGT_RSP_INIT_IDLE,
+        TGT_RSP_CLEANUP_IDLE,
+        TGT_RSP_READ,
+        TGT_RSP_WRITE,
+        TGT_RSP_LLSC,
+        TGT_RSP_XRAM,
+        TGT_RSP_INIT,
+        TGT_RSP_CLEANUP,
+      };
+
+      /* States of the INIT_CMD fsm */
+      enum init_cmd_fsm_state_e{
+        INIT_CMD_INVAL_IDLE,
+        INIT_CMD_INVAL_SEL,
+        INIT_CMD_INVAL_NLINE,
+        INIT_CMD_UPDT_IDLE,
+        INIT_CMD_UPDT_SEL,
+        INIT_CMD_BRDCAST,
+        INIT_CMD_UPDT_NLINE,
+        INIT_CMD_UPDT_INDEX,
+        INIT_CMD_UPDT_DATA,
+        INIT_CMD_SC_UPDT_IDLE,
+        INIT_CMD_SC_UPDT_SEL,
+        INIT_CMD_SC_BRDCAST,
+        INIT_CMD_SC_UPDT_NLINE,
+        INIT_CMD_SC_UPDT_INDEX,
+        INIT_CMD_SC_UPDT_DATA,
+      };
+
+      /* States of the INIT_RSP fsm */
+      enum init_rsp_fsm_state_e{
+        INIT_RSP_IDLE,
+        INIT_RSP_UPT_LOCK,
+        INIT_RSP_UPT_CLEAR,
+        INIT_RSP_END,
+      };
+
+      /* States of the READ fsm */
+      enum read_fsm_state_e{
+        READ_IDLE,
+        READ_DIR_LOCK,
+        READ_DIR_HIT,
+        READ_RSP,
+        READ_TRT_LOCK,
+        READ_TRT_SET,
+        READ_XRAM_REQ,
+      };
+
+      /* States of the WRITE fsm */
+      enum write_fsm_state_e{
+        WRITE_IDLE,
+        WRITE_NEXT,
+        WRITE_DIR_LOCK,
+        WRITE_DIR_HIT_READ,
+        WRITE_DIR_HIT,
+        WRITE_DIR_HIT_RSP,
+        WRITE_UPT_LOCK,
+        WRITE_WAIT_UPT,
+        WRITE_UPDATE,
+        WRITE_RSP,
+        WRITE_TRT_LOCK,
+        WRITE_TRT_DATA,
+        WRITE_TRT_SET,
+        WRITE_WAIT_TRT,
+        WRITE_XRAM_REQ,
+        WRITE_TRT_WRITE_LOCK,
+        WRITE_INVAL_LOCK,
+        WRITE_DIR_INVAL,
+        WRITE_INVAL,
+        WRITE_XRAM_SEND,
+      };
+
+      /* States of the IXR_RSP fsm */
+      enum ixr_rsp_fsm_state_e{
+        IXR_RSP_IDLE,
+        IXR_RSP_ACK,
+        IXR_RSP_TRT_ERASE,
+        IXR_RSP_TRT_READ,
+      };
+
+      /* States of the XRAM_RSP fsm */
+      enum xram_rsp_fsm_state_e{
+        XRAM_RSP_IDLE,
+        XRAM_RSP_TRT_COPY,
+        XRAM_RSP_TRT_DIRTY,
+        XRAM_RSP_DIR_LOCK,
+        XRAM_RSP_DIR_UPDT,
+        XRAM_RSP_DIR_RSP,
+        XRAM_RSP_INVAL_LOCK,
+        XRAM_RSP_INVAL_WAIT,
+        XRAM_RSP_INVAL,
+        XRAM_RSP_WRITE_DIRTY,
+      };
+
+      /* States of the IXR_CMD fsm */
+      enum ixr_cmd_fsm_state_e{
+        IXR_CMD_READ_IDLE,
+        IXR_CMD_WRITE_IDLE,
+        IXR_CMD_LLSC_IDLE,
+        IXR_CMD_XRAM_IDLE,
+        IXR_CMD_READ_NLINE,
+        IXR_CMD_WRITE_NLINE,
+        IXR_CMD_LLSC_NLINE,
+        IXR_CMD_XRAM_DATA,
+      };
+
+      /* States of the LLSC fsm */
+      enum llsc_fsm_state_e{
+        LLSC_IDLE,
+        LL_DIR_LOCK,
+        LL_DIR_HIT,
+        LL_RSP,
+        SC_DIR_LOCK,
+        SC_DIR_HIT,
+        SC_UPT_LOCK,
+        SC_WAIT_UPT,
+        SC_UPDATE,
+        SC_TRT_LOCK,
+        SC_INVAL_LOCK,
+        SC_DIR_INVAL,
+        SC_INVAL,
+        SC_XRAM_SEND,
+        SC_RSP_FALSE,
+        SC_RSP_TRUE,
+        LLSC_TRT_LOCK,
+        LLSC_TRT_SET,
+        LLSC_XRAM_REQ,
+      };
+
+      /* States of the CLEANUP fsm */
+      enum cleanup_fsm_state_e{
+        CLEANUP_IDLE,
+        CLEANUP_DIR_LOCK,
+        CLEANUP_DIR_WRITE,
+        CLEANUP_UPT_LOCK,
+        CLEANUP_UPT_WRITE,
+        CLEANUP_WRITE_RSP,
+        CLEANUP_RSP,
+      };
+
+      /* States of the ALLOC_DIR fsm */
+      enum alloc_dir_fsm_state_e{
+        ALLOC_DIR_READ,
+        ALLOC_DIR_WRITE,
+        ALLOC_DIR_LLSC,
+        ALLOC_DIR_CLEANUP,
+        ALLOC_DIR_XRAM_RSP,
+      };
+
+      /* States of the ALLOC_TRT fsm */
+      enum alloc_trt_fsm_state_e{
+        ALLOC_TRT_READ,
+        ALLOC_TRT_WRITE,
+        ALLOC_TRT_LLSC,
+        ALLOC_TRT_XRAM_RSP,
+        ALLOC_TRT_IXR_RSP,
+      };
+
+      /* States of the ALLOC_UPT fsm */
+      enum alloc_upt_fsm_state_e{
+        ALLOC_UPT_WRITE,
+        ALLOC_UPT_XRAM_RSP,
+        ALLOC_UPT_INIT_RSP,
+        ALLOC_UPT_CLEANUP,
+        ALLOC_UPT_LLSC,
+      };
+
+      uint32_t	   m_cpt_cycles;            // Counter of cycles 
+      uint32_t	   m_cpt_read;              // Number of READ transactions
+      uint32_t	   m_cpt_read_miss;         // Number of MISS READ 
+      uint32_t	   m_cpt_write;             // Number of WRITE transactions
+      uint32_t	   m_cpt_write_miss;        // Number of MISS WRITE
+      uint32_t     m_cpt_write_cells;	    // Cumulated length for WRITE transactions
+      uint32_t     m_cpt_write_dirty;	    // Cumulated length for WRITE transactions
+      uint32_t	   m_cpt_update;            // Number of UPDATE transactions
+      uint32_t	   m_cpt_update_mult;       // Number of targets for UPDATE
+      uint32_t	   m_cpt_inval;             // Number of INVAL  transactions
+      uint32_t	   m_cpt_inval_mult;        // Number of targets for INVAL  
+      uint32_t	   m_cpt_inval_brdcast;     // Number of BROADCAST INVAL  
+      uint32_t	   m_cpt_cleanup;           // Number of CLEANUP transactions
+      uint32_t	   m_cpt_ll;                // Number of LL transactions
+      uint32_t	   m_cpt_sc;                // Number of SC transactions
+
+      protected:
+
+      SC_HAS_PROCESS(VciMemCacheV2S);
+
+      public:
+      sc_in<bool> 			  	p_clk;
+      sc_in<bool> 			  	p_resetn;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt_cleanup;
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ini;	
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ixr;
+
+      VciMemCacheV2S(
+          sc_module_name name,                              // Instance Name 
+          const soclib::common::MappingTable &mtp,          // Mapping table for primary requets
+          const soclib::common::MappingTable &mtc,          // Mapping table for coherence requets
+          const soclib::common::MappingTable &mtx,          // Mapping table for XRAM
+          const soclib::common::IntTab &vci_ixr_index,      // VCI port to XRAM (initiator)
+          const soclib::common::IntTab &vci_ini_index,      // VCI port to PROC (initiator)
+          const soclib::common::IntTab &vci_tgt_index,      // VCI port to PROC (target)
+          const soclib::common::IntTab &vci_tgt_index_cleanup,    // VCI port to PROC (target) for cleanup
+          size_t nways,                                   // Number of ways per set 
+          size_t nsets,                                   // Number of sets
+          size_t nwords);                                 // Number of words per line
+
+      ~VciMemCacheV2S();
+
+      void transition();
+
+      void genMoore();
+
+      void print_stats();
+
+      private:
+
+      // Component attributes
+      const size_t              m_initiators;           // Number of initiators
+      const size_t              m_ways;                 // Number of ways in a set
+      const size_t              m_sets;                 // Number of cache sets
+      const size_t              m_words;		        // Number of words in a line
+      const size_t              m_srcid_ixr;		    // Srcid for requests to XRAM 
+      const size_t              m_srcid_ini;		    // Srcid for requests to processors
+      std::list<soclib::common::Segment>  m_seglist;    // memory cached into the cache
+      std::list<soclib::common::Segment>  m_cseglist;   // coherence segment for the cache
+      vci_addr_t        		*m_coherence_table; 	// address(srcid)
+      AtomicTab                 m_atomic_tab;           // atomic access table
+      TransactionTab      		m_transaction_tab;	    // xram transaction table
+      UpdateTab                 m_update_tab;		    // pending update & invalidate 
+      CacheDirectory			m_cache_directory;	    // data cache directory
+
+      data_t	        	       ***m_cache_data;		// data array[set][way][word]
+
+      // adress masks
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_x;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_y;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_z;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_nline; 
+
+      //////////////////////////////////////////////////
+      // Others registers
+      //////////////////////////////////////////////////
+      sc_signal<size_t>   r_copies_limit; // Limit of the number of copies for one line
+
+      //////////////////////////////////////////////////
+      // Registers controlled by the TGT_CMD fsm
+      //////////////////////////////////////////////////
+
+      // Fifo between TGT_CMD fsm and READ fsm
+      GenericFifo<uint64_t>  m_cmd_read_addr_fifo;
+      GenericFifo<size_t>    m_cmd_read_length_fifo;
+      GenericFifo<size_t>    m_cmd_read_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_read_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_read_pktid_fifo;
+
+      // Fifo between TGT_CMD fsm and WRITE fsm    
+      GenericFifo<uint64_t>  m_cmd_write_addr_fifo;
+      GenericFifo<bool>      m_cmd_write_eop_fifo;
+      GenericFifo<size_t>    m_cmd_write_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_write_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_write_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_write_data_fifo;
+      GenericFifo<be_t>	     m_cmd_write_be_fifo;
+
+      // Fifo between TGT_CMD fsm and LLSC fsm
+      GenericFifo<uint64_t>  m_cmd_llsc_addr_fifo;
+      GenericFifo<bool>      m_cmd_llsc_sc_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_llsc_wdata_fifo;
+
+      sc_signal<int>         r_tgt_cmd_fsm;
+
+      sc_signal<size_t>	     r_index;
+      size_t nseg;
+      size_t ncseg;
+      soclib::common::Segment  **m_seg;
+      soclib::common::Segment  **m_cseg;
+      ///////////////////////////////////////////////////////
+      // Registers controlled by the READ fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>         r_read_fsm;        // FSM state 
+      sc_signal<copy_t>      r_read_d_copies;   // bit-vector of copies 
+      sc_signal<copy_t>      r_read_i_copies;   // bit-vector of copies 
+      sc_signal<tag_t>       r_read_tag;	    // cache line tag (in directory)
+      sc_signal<bool>        r_read_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>        r_read_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_read_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>      r_read_count;      // number of copies
+      sc_signal<data_t>     *r_read_data;       // data (one cache line)
+      sc_signal<size_t>      r_read_way;        // associative way (in cache)
+      sc_signal<size_t>      r_read_trt_index;  // Transaction Table index
+
+      // Buffer between READ fsm and IXR_CMD fsm (ask a missing cache line to XRAM)   
+      sc_signal<bool>        r_read_to_ixr_cmd_req;     // valid request
+      sc_signal<addr_t>      r_read_to_ixr_cmd_nline;   // cache line index
+      sc_signal<size_t>      r_read_to_ixr_cmd_trdid;   // index in Transaction Table
+
+      // Buffer between READ fsm and TGT_RSP fsm (send a hit read response to L1 cache)
+      sc_signal<bool>	   r_read_to_tgt_rsp_req;       // valid request
+      sc_signal<size_t>	   r_read_to_tgt_rsp_srcid;	    // Transaction srcid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_trdid;	    // Transaction trdid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_pktid;	    // Transaction pktid
+      sc_signal<data_t>   *r_read_to_tgt_rsp_data;	    // data (one cache line)
+      sc_signal<size_t>    r_read_to_tgt_rsp_word;      // first word of the response
+      sc_signal<size_t>    r_read_to_tgt_rsp_length;    // length of the response
+
+      ///////////////////////////////////////////////////////////////
+      // Registers controlled by the WRITE fsm
+      ///////////////////////////////////////////////////////////////
+
+      sc_signal<int>       r_write_fsm;             // FSM state
+      sc_signal<addr_t>	   r_write_address;         // first word address
+      sc_signal<size_t>    r_write_word_index;      // first word index in line
+      sc_signal<size_t>    r_write_word_count;      // number of words in line
+      sc_signal<size_t>    r_write_srcid;           // transaction srcid
+      sc_signal<size_t>    r_write_trdid;           // transaction trdid
+      sc_signal<size_t>    r_write_pktid;           // transaction pktid
+      sc_signal<data_t>	  *r_write_data;            // data (one cache line)	
+      sc_signal<be_t>     *r_write_be;              // one byte enable per word
+      sc_signal<bool>      r_write_byte;            // is it a byte write
+      sc_signal<bool>      r_write_is_cnt;          // is_cnt bit (in directory)
+      sc_signal<bool>      r_write_lock;            // lock bit (in directory)
+      sc_signal<tag_t>     r_write_tag;             // cache line tag (in directory)
+      sc_signal<copy_t>    r_write_d_copies;        // bit vector of copies
+      sc_signal<copy_t>    r_write_i_copies;        // bit vector of copies
+      sc_signal<size_t>	   r_write_count;           // number of copies
+      sc_signal<size_t>	   r_write_way;		        // way of the line
+      sc_signal<size_t>    r_write_trt_index;	    // index in Transaction Table
+      sc_signal<size_t>    r_write_upt_index;	    // index in Update Table
+
+      // Buffer between WRITE fsm and TGT_RSP fsm (acknowledge a write command from L1)
+      sc_signal<bool>      r_write_to_tgt_rsp_req;		// valid request
+      sc_signal<size_t>    r_write_to_tgt_rsp_srcid;    // transaction srcid
+      sc_signal<size_t>    r_write_to_tgt_rsp_trdid;	// transaction trdid
+      sc_signal<size_t>    r_write_to_tgt_rsp_pktid;	// transaction pktid
+
+      // Buffer between WRITE fsm and IXR_CMD fsm (ask a missing cache line to XRAM) 
+      sc_signal<bool>	   r_write_to_ixr_cmd_req;      // valid request
+      sc_signal<bool>	   r_write_to_ixr_cmd_write;    // write request
+      sc_signal<addr_t>    r_write_to_ixr_cmd_nline; 	// cache line index
+      sc_signal<data_t>	  *r_write_to_ixr_cmd_data;	    // cache line data
+      sc_signal<size_t>    r_write_to_ixr_cmd_trdid;	// index in Transaction Table
+
+      // Buffer between WRITE fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>	   r_write_to_init_cmd_req;         // valid request
+      sc_signal<bool>	   r_write_to_init_cmd_brdcast;     // brdcast request
+      sc_signal<addr_t>	   r_write_to_init_cmd_nline;	    // cache line index
+      sc_signal<size_t>	   r_write_to_init_cmd_trdid;	    // index in Update Table
+      sc_signal<copy_t>    r_write_to_init_cmd_d_copies;    // bit_vector of L1 to update
+      sc_signal<data_t>   *r_write_to_init_cmd_data;	    // data (one cache line)
+      sc_signal<bool>     *r_write_to_init_cmd_we;	        // word enable
+      sc_signal<size_t>	   r_write_to_init_cmd_count;	    // number of words in line
+      sc_signal<size_t>	   r_write_to_init_cmd_index;	    // index of first word in line
+
+      /////////////////////////////////////////////////////////
+      // Registers controlled by INIT_RSP fsm
+      //////////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_init_rsp_fsm;        // FSM state
+      sc_signal<size_t>	   r_init_rsp_upt_index;  // index in the Update Table
+      sc_signal<size_t>	   r_init_rsp_srcid;	  // pending write srcid      
+      sc_signal<size_t>	   r_init_rsp_trdid;	  // pending write trdid      
+      sc_signal<size_t>	   r_init_rsp_pktid;	  // pending write pktid      
+      sc_signal<addr_t>	   r_init_rsp_nline;	  // pending write nline      
+
+      // Buffer between INIT_RSP fsm and TGT_RSP fsm (complete write/update transaction)
+      sc_signal<bool>	     r_init_rsp_to_tgt_rsp_req;   	// valid request
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_srcid;		// Transaction srcid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_trdid;		// Transaction trdid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_pktid;		// Transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by CLEANUP fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int> 	     r_cleanup_fsm;         // FSM state
+      sc_signal<size_t>      r_cleanup_srcid;       // transaction srcid
+      sc_signal<size_t>      r_cleanup_trdid;       // transaction trdid
+      sc_signal<size_t>      r_cleanup_pktid;       // transaction pktid
+      sc_signal<addr_t>      r_cleanup_nline;       // cache line index
+
+      sc_signal<copy_t>      r_cleanup_d_copies;    // bit-vector of copies 
+      sc_signal<copy_t>      r_cleanup_i_copies;    // bit-vector of copies 
+      sc_signal<copy_t>      r_cleanup_count;       // number of copies 
+      sc_signal<tag_t>       r_cleanup_tag;	        // cache line tag (in directory)
+      sc_signal<bool>        r_cleanup_is_cnt;      // inst bit (in directory)
+      sc_signal<bool>        r_cleanup_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_cleanup_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>      r_cleanup_way;	        // associative way (in cache)
+
+      sc_signal<size_t>      r_cleanup_write_srcid; // srcid of write response
+      sc_signal<size_t>      r_cleanup_write_trdid; // trdid of write rsp
+      sc_signal<size_t>      r_cleanup_write_pktid; // pktid of write rsp
+      sc_signal<bool>        r_cleanup_need_rsp;    // needs a write rsp
+
+      sc_signal<size_t>      r_cleanup_index;	    // index of the INVAL line (in the UPT)
+
+      // Buffer between CLEANUP fsm and TGT_RSP fsm (acknowledge a write command from L1)
+      sc_signal<bool>      r_cleanup_to_tgt_rsp_req;    // valid request
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_srcid;  // transaction srcid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_trdid;	// transaction trdid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_pktid;	// transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by LLSC fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>       r_llsc_fsm;          // FSM state
+      sc_signal<data_t>	   r_llsc_data;		    // read data word
+      sc_signal<uint32_t>  r_llsc_lfsr;         // lfsr for random introducing
+      sc_signal<copy_t>    r_llsc_i_copies;	    // bit_vector of copies
+      sc_signal<copy_t>    r_llsc_d_copies;	    // bit_vector of copies
+      sc_signal<copy_t>    r_llsc_count;	    // number of copies
+      sc_signal<bool>      r_llsc_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>      r_llsc_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>    r_llsc_way;		    // way in directory
+      sc_signal<size_t>    r_llsc_set;		    // set in directory
+      sc_signal<data_t>    r_llsc_tag;		    // cache line tag (in directory)
+      sc_signal<size_t>    r_llsc_trt_index;    // Transaction Table index
+      sc_signal<size_t>    r_llsc_upt_index;    // Update Table index
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (XRAM read)	
+      sc_signal<bool>	   r_llsc_to_ixr_cmd_req;   // valid request
+      sc_signal<addr_t>	   r_llsc_to_ixr_cmd_nline; // cache line index
+      sc_signal<size_t>	   r_llsc_to_ixr_cmd_trdid; // index in Transaction Table
+      sc_signal<bool>	   r_llsc_to_ixr_cmd_write; // write request
+      sc_signal<data_t>	  *r_llsc_to_ixr_cmd_data;  // cache line data
+
+
+      // Buffer between LLSC fsm and TGT_RSP fsm
+      sc_signal<bool>	   r_llsc_to_tgt_rsp_req;   // valid request
+      sc_signal<data_t>    r_llsc_to_tgt_rsp_data;  // read data word
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_srcid; // Transaction srcid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_trdid; // Transaction trdid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_pktid; // Transaction pktid
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>	   r_llsc_to_init_cmd_req;          // valid request
+      sc_signal<bool>	   r_llsc_to_init_cmd_brdcast;      // brdcast request
+      sc_signal<addr_t>	   r_llsc_to_init_cmd_nline;	    // cache line index
+      sc_signal<size_t>	   r_llsc_to_init_cmd_trdid;	    // index in Update Table
+      sc_signal<copy_t>    r_llsc_to_init_cmd_d_copies;     // bit_vector of L1 to update
+      sc_signal<data_t>    r_llsc_to_init_cmd_wdata;        // data (one word)
+      sc_signal<size_t>	   r_llsc_to_init_cmd_index;	    // index of the word in line
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_rsp_fsm;       // FSM state
+      sc_signal<size_t>	   r_ixr_rsp_trt_index;	// TRT entry index
+      sc_signal<size_t>    r_ixr_rsp_cpt;	    // word counter
+
+      // Buffer between IXR_RSP fsm and XRAM_RSP fsm  (response from the XRAM)
+      sc_signal<bool>	  *r_ixr_rsp_to_xram_rsp_rok;	// A xram response is ready
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the XRAM_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_xram_rsp_fsm;		        // FSM state
+      sc_signal<size_t>	   r_xram_rsp_trt_index;	    // TRT entry index
+      TransactionTabEntry  r_xram_rsp_trt_buf;		    // TRT entry local buffer
+      sc_signal<bool>	   r_xram_rsp_victim_inval;	    // victim line invalidate 
+      sc_signal<bool>	   r_xram_rsp_victim_is_cnt;    // victim line inst bit
+      sc_signal<bool>	   r_xram_rsp_victim_dirty;	    // victim line dirty bit
+      sc_signal<size_t>    r_xram_rsp_victim_way;	    // victim line way
+      sc_signal<size_t>    r_xram_rsp_victim_set;	    // victim line set
+      sc_signal<addr_t>    r_xram_rsp_victim_nline;     // victim line index
+      sc_signal<copy_t>    r_xram_rsp_victim_d_copies;	// victim line copies
+      sc_signal<copy_t>    r_xram_rsp_victim_i_copies;	// victim line copies
+      sc_signal<copy_t>    r_xram_rsp_victim_count;	    // victim line number of copies
+      sc_signal<data_t>	  *r_xram_rsp_victim_data;	    // victim line data
+      sc_signal<size_t>	   r_xram_rsp_upt_index;	    // UPT entry index
+
+      // Buffer between XRAM_RSP fsm and TGT_RSP fsm  (response to L1 cache)
+      sc_signal<bool>	   r_xram_rsp_to_tgt_rsp_req;	// Valid request
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_srcid;	// Transaction srcid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_trdid;	// Transaction trdid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_pktid;	// Transaction pktid
+      sc_signal<data_t>   *r_xram_rsp_to_tgt_rsp_data;	// data (one cache line)
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_word;  // first word index
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_length;// length of the response
+
+      // Buffer between XRAM_RSP fsm and INIT_CMD fsm (Inval L1 Caches) 
+      sc_signal<bool>	     r_xram_rsp_to_init_cmd_req;    // Valid request
+      sc_signal<bool>      r_xram_rsp_to_init_cmd_brdcast;  // Broadcast request
+      sc_signal<addr_t>    r_xram_rsp_to_init_cmd_nline;    // cache line index;
+      sc_signal<size_t>	   r_xram_rsp_to_init_cmd_trdid;    // index of UPT entry
+      sc_signal<copy_t>    r_xram_rsp_to_init_cmd_d_copies; // bit_vector of copies
+      sc_signal<copy_t>    r_xram_rsp_to_init_cmd_i_copies; // bit_vector of copies
+
+      // Buffer between XRAM_RSP fsm and IXR_CMD fsm (XRAM write)
+      sc_signal<bool>	   r_xram_rsp_to_ixr_cmd_req;	// Valid request
+      sc_signal<addr_t>	   r_xram_rsp_to_ixr_cmd_nline;	// cache line index
+      sc_signal<data_t>	  *r_xram_rsp_to_ixr_cmd_data;	// cache line data
+      sc_signal<size_t>	   r_xram_rsp_to_ixr_cmd_trdid;	// index in transaction table
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_cmd_fsm;
+      sc_signal<size_t>	   r_ixr_cmd_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by TGT_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_tgt_rsp_fsm;
+      sc_signal<size_t>    r_tgt_rsp_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by INIT_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	  r_init_cmd_fsm;
+      sc_signal<size_t>   r_init_cmd_cpt;
+      sc_signal<size_t>	  r_init_cmd_target;
+      sc_signal<bool>     r_init_cmd_inst;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_DIR fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_dir_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_TRT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_trt_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_UPT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_upt_fsm;
+
+    }; // end class VciMemCacheV2S
+
+}}
+
+#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
+
Index: /trunk/modules/vci_mem_cache_v2s/caba/source/include/xram_transaction_v2.h
===================================================================
--- /trunk/modules/vci_mem_cache_v2s/caba/source/include/xram_transaction_v2.h	(revision 41)
+++ /trunk/modules/vci_mem_cache_v2s/caba/source/include/xram_transaction_v2.h	(revision 41)
@@ -0,0 +1,404 @@
+#ifndef XRAM_TRANSACTION_V2_H_
+#define XRAM_TRANSACTION_V2_H_
+ 
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+#define DEBUG_XRAM_TRANSACTION 0
+
+////////////////////////////////////////////////////////////////////////
+//                  A transaction tab entry         
+////////////////////////////////////////////////////////////////////////
+
+class TransactionTabEntry {
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ public:
+  bool 		      valid;     	    // entry valid 
+  bool 		      xram_read; 	    // read request to XRAM
+  addr_t   	      nline;    	    // index (zy) of the requested line
+  size_t 	      srcid;     	    // processor requesting the transaction
+  size_t 	      trdid;     	    // processor requesting the transaction
+  size_t 	      pktid;     	    // processor requesting the transaction
+  bool 		      proc_read;	    // read request from processor
+  size_t 		  read_length;      // length of the read (for the response)
+  size_t 	      word_index;    	// index of the first read word (for the response)
+  std::vector<data_t> wdata;        // write buffer (one cache line)
+  std::vector<be_t>   wdata_be;    	// be for each data in the write buffer
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    valid		= false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The alloc() function initializes the vectors of an entry
+  // Its arguments are :
+  // - n_words : number of words per line in the cache
+  /////////////////////////////////////////////////////////////////////
+  void alloc(size_t n_words)
+  {
+    wdata_be.reserve( (int)n_words );
+    wdata.reserve( (int)n_words );
+    for(size_t i=0; i<n_words; i++){
+      wdata_be.push_back(false);
+      wdata.push_back(0);
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the transaction tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const TransactionTabEntry &source)
+  {
+    valid	    = source.valid;
+    xram_read 	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read 	= source.proc_read;
+    read_length = source.read_length;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry 
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << "valid       = " << valid        << std::endl;
+    std::cout << "xram_read   = " << xram_read    << std::endl;
+    std::cout << "nline       = " << std::hex << nline << std::endl;
+    std::cout << "srcid       = " << srcid        << std::endl;
+    std::cout << "trdid       = " << trdid        << std::endl;
+    std::cout << "pktid       = " << pktid        << std::endl;
+    std::cout << "proc_read   = " << proc_read    << std::endl;
+    std::cout << "read_length = " << read_length  << std::endl;
+    std::cout << "word_index  = " << word_index   << std::endl; 
+    for(size_t i=0; i<wdata_be.size() ; i++){
+      std::cout << "wdata_be [" << i <<"] = " << wdata_be[i] << std::endl;
+    }
+    for(size_t i=0; i<wdata.size() ; i++){
+      std::cout << "wdata [" << i <<"] = " << wdata[i] << std::endl;
+    }
+    std::cout << std::endl;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // 		Constructors
+  /////////////////////////////////////////////////////////////////////
+
+  TransactionTabEntry()
+    {
+      wdata_be.clear();
+      wdata.clear();
+      valid=false;
+    }
+
+  TransactionTabEntry(const TransactionTabEntry &source){
+    valid	    = source.valid;
+    xram_read	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read	= source.proc_read;
+    read_length = source.read_length;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+}; // end class TransactionTabEntry
+
+////////////////////////////////////////////////////////////////////////
+//                  The transaction tab                              
+////////////////////////////////////////////////////////////////////////
+class TransactionTab{
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ private:
+  size_t size_tab;                // The size of the tab
+
+  data_t be_to_mask(be_t be)
+  {
+    data_t ret = 0;
+    if ( be&0x1 ) {
+      ret = ret | 0x000000FF;
+    }
+    if ( be&0x2 ) {
+      ret = ret | 0x0000FF00;
+    }
+    if ( be&0x4 ) {
+      ret = ret | 0x00FF0000;
+    }
+    if ( be&0x8 ) {
+      ret = ret | 0xFF000000;
+    }
+    return ret;
+  }
+
+ public:
+  TransactionTabEntry *tab;       // The transaction tab
+
+  ////////////////////////////////////////////////////////////////////
+  //		Constructors
+  ////////////////////////////////////////////////////////////////////
+  TransactionTab()
+    {
+      size_tab=0;
+      tab=NULL;
+    }
+
+  TransactionTab(size_t n_entries, size_t n_words)
+    {
+      size_tab = n_entries;
+      tab = new TransactionTabEntry[size_tab];
+      for ( size_t i=0; i<size_tab; i++) {
+	tab[i].alloc(n_words);
+      }
+    }
+
+  ~TransactionTab()
+    {
+      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
+  /////////////////////////////////////////////////////////////////////
+  TransactionTabEntry read(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    return tab[index];
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // 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 hit_read() function checks if an XRAM read transaction exists 
+  // for a given cache line.
+  // Arguments :
+  // - index : (return argument) the index of the hit entry, if there is 
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a read request has already been sent
+  //////////////////////////////////////////////////////////////////////
+  bool hit_read(const addr_t nline,size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if((tab[i].valid && (nline==tab[i].nline)) && (tab[i].xram_read)) {
+	    index=i;
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  ///////////////////////////////////////////////////////////////////////
+  // The hit_write() function looks if an XRAM write transaction exists 
+  // for a given line.
+  // Arguments :
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a write request has already been sent
+  ///////////////////////////////////////////////////////////////////////
+  bool hit_write(const addr_t nline)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(tab[i].valid && (nline==tab[i].nline) && !(tab[i].xram_read)) {
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_data_mask() function writes a vector of data (a line).
+  // The data is written only if the corresponding bits are set
+  // in the be vector. 
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  // - be   : vector of be 
+  // - data : vector of data
+  /////////////////////////////////////////////////////////////////////
+  void write_data_mask(const size_t index, 
+		       const std::vector<be_t> &be, 
+		       const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    assert(be.size()==tab[index].wdata_be.size() 
+	   && "Bad data mask in write_data_mask in TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data in write_data_mask in TransactionTab");
+
+    for(size_t i=0; i<tab[index].wdata_be.size() ; i++) {
+      tab[index].wdata_be[i] = tab[index].wdata_be[i] | be[i];
+      data_t mask = be_to_mask(be[i]);
+      tab[index].wdata[i] = (tab[index].wdata[i] & ~mask) | (data[i] & mask);
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The set() function registers a transaction (read or write)
+  // to the XRAM in the transaction tab.
+  // Arguments :
+  // - index : index in the transaction tab
+  // - xram_read : transaction type (read or write a cache line)
+  // - nline : the index (zy) of the cache line
+  // - srcid : srcid of the initiator that caused the transaction
+  // - trdid : trdid of the initiator that caused the transaction
+  // - pktid : pktid of the initiator that caused the transaction
+  // - proc_read : does the initiator want a copy
+  // - read_length : length of read (in case of processor read)
+  // - word_index : index in the line (in case of single word read)
+  // - data : the data to write (in case of write)
+  // - data_be : the mask of the data to write (in case of write)
+  /////////////////////////////////////////////////////////////////////
+  void set(const size_t index,
+	   const bool xram_read,
+	   const addr_t nline,
+	   const size_t srcid,
+	   const size_t trdid,
+	   const size_t pktid,
+	   const bool proc_read,
+	   const size_t read_length,
+	   const size_t word_index,
+	   const std::vector<be_t> &data_be,
+	   const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in set() Transaction Tab");
+    assert(data_be.size()==tab[index].wdata_be.size() 
+	   && "Bad data_be argument in set() TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data argument in set() TransactionTab");
+
+    tab[index].valid	        = true;
+    tab[index].xram_read        = xram_read;
+    tab[index].nline	        = nline;
+    tab[index].srcid	        = srcid;
+    tab[index].trdid	        = trdid;
+    tab[index].pktid	        = pktid;
+    tab[index].proc_read	    = proc_read;
+    tab[index].read_length	    = read_length;
+    tab[index].word_index	    = word_index;
+    for(size_t i=0; i<tab[index].wdata.size(); i++) {
+      tab[index].wdata_be[i]    = data_be[i];
+      tab[index].wdata[i]       = data[i];
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_rsp() function writes a word of the response to an 
+  // XRAM read transaction.
+  // The data is only written when the corresponding BE field is Ox0.
+  // Arguments :
+  // - index : the index of the transaction in the transaction tab
+  // - word_index : the index of the data in the line
+  // - data : the data to write
+  /////////////////////////////////////////////////////////////////////
+  void write_rsp(const size_t index,
+		 const size_t word,
+		 const data_t data)
+  {
+    assert( (index < size_tab) 
+	    && "Selected entry  out of range in write_rsp() Transaction Tab");
+    assert( (word <= tab[index].wdata_be.size()) 
+	    && "Bad word_index in write_rsp() in TransactionTab");
+    assert( tab[index].valid 
+	    && "Transaction Tab Entry invalid in write_rsp()");
+    assert( tab[index].xram_read 
+	    && "Selected entry is not an XRAM read transaction in write_rsp()");
+
+    data_t mask = be_to_mask(tab[index].wdata_be[word]);
+    tab[index].wdata[word] = (tab[index].wdata[word] & mask) | (data & ~mask);
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // 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 TransactionTab
+
+#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
+
Index: /trunk/modules/vci_mem_cache_v2s/caba/source/src/vci_mem_cache_v2s.cpp
===================================================================
--- /trunk/modules/vci_mem_cache_v2s/caba/source/src/vci_mem_cache_v2s.cpp	(revision 41)
+++ /trunk/modules/vci_mem_cache_v2s/caba/source/src/vci_mem_cache_v2s.cpp	(revision 41)
@@ -0,0 +1,3837 @@
+/* -*- c++ -*-
+ * File 	: vci_mem_cache_v2s.cpp
+ * Date 	: 30/10/2008
+ * Copyright 	: UPMC / LIP6
+ * Authors 	: Alain Greiner / Eric Guthmuller
+ *
+ * SOCLIB_LGPL_HEADER_BEGIN
+ *
+ * This file is part of SoCLib, GNU LGPLv2.1.
+ *
+ * SoCLib is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 of the License.
+ *
+ * SoCLib is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SoCLib; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * SOCLIB_LGPL_HEADER_END
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+#include "../include/vci_mem_cache_v2s.h"
+
+//#define TDEBUG // Transaction tab debug
+//#define IDEBUG // Update tab debug
+//#define DDEBUG // Directory debug
+//#define DEBUG_VCI_MEM_CACHE 1
+#define RANDOMIZE_SC
+
+namespace soclib { namespace caba {
+
+#ifdef DEBUG_VCI_MEM_CACHE 
+  const char *tgt_cmd_fsm_str[] = {
+    "TGT_CMD_IDLE",
+    "TGT_CMD_READ",
+    "TGT_CMD_READ_EOP",
+    "TGT_CMD_WRITE",
+    "TGT_CMD_ATOMIC",
+  };
+  const char *tgt_rsp_fsm_str[] = {
+    "TGT_RSP_READ_IDLE",
+    "TGT_RSP_WRITE_IDLE",
+    "TGT_RSP_LLSC_IDLE",
+    "TGT_RSP_XRAM_IDLE",
+    "TGT_RSP_INIT_IDLE",
+    "TGT_RSP_CLEANUP_IDLE",
+    "TGT_RSP_READ",
+    "TGT_RSP_WRITE",
+    "TGT_RSP_LLSC",
+    "TGT_RSP_XRAM",
+    "TGT_RSP_INIT",
+    "TGT_RSP_CLEANUP",
+  };
+  const char *init_cmd_fsm_str[] = {
+    "INIT_CMD_INVAL_IDLE",
+    "INIT_CMD_INVAL_SEL",
+    "INIT_CMD_INVAL_NLINE",
+    "INIT_CMD_UPDT_IDLE",
+    "INIT_CMD_UPDT_SEL",
+    "INIT_CMD_BRDCAST",
+    "INIT_CMD_UPDT_NLINE",
+    "INIT_CMD_UPDT_INDEX",
+    "INIT_CMD_UPDT_DATA",
+    "INIT_CMD_SC_UPDT_IDLE",
+    "INIT_CMD_SC_UPDT_SEL",
+    "INIT_CMD_SC_BRDCAST",
+    "INIT_CMD_SC_UPDT_NLINE",
+    "INIT_CMD_SC_UPDT_INDEX",
+    "INIT_CMD_SC_UPDT_DATA",
+  };
+  const char *init_rsp_fsm_str[] = {
+    "INIT_RSP_IDLE",
+    "INIT_RSP_UPT_LOCK",
+    "INIT_RSP_UPT_CLEAR",
+    "INIT_RSP_END",
+  };
+  const char *read_fsm_str[] = {
+    "READ_IDLE",
+    "READ_DIR_LOCK",
+    "READ_DIR_HIT",
+    "READ_RSP",
+    "READ_TRT_LOCK",
+    "READ_TRT_SET",
+    "READ_XRAM_REQ",
+  };
+  const char *write_fsm_str[] = {
+    "WRITE_IDLE",
+    "WRITE_NEXT",
+    "WRITE_DIR_LOCK",
+    "WRITE_DIR_HIT_READ",
+    "WRITE_DIR_HIT",
+    "WRITE_DIR_HIT_RSP",
+    "WRITE_UPT_LOCK",
+    "WRITE_WAIT_UPT",
+    "WRITE_UPDATE",
+    "WRITE_RSP",
+    "WRITE_TRT_LOCK",
+    "WRITE_TRT_DATA",
+    "WRITE_TRT_SET",
+    "WRITE_WAIT_TRT",
+    "WRITE_XRAM_REQ",
+    "WRITE_TRT_WRITE_LOCK",
+    "WRITE_INVAL_LOCK",
+    "WRITE_DIR_INVAL",
+    "WRITE_INVAL",
+    "WRITE_XRAM_SEND",
+  };
+  const char *ixr_rsp_fsm_str[] = {
+    "IXR_RSP_IDLE",
+    "IXR_RSP_ACK",
+    "IXR_RSP_TRT_ERASE",
+    "IXR_RSP_TRT_READ",
+  };
+  const char *xram_rsp_fsm_str[] = {
+    "XRAM_RSP_IDLE",
+    "XRAM_RSP_TRT_COPY",
+    "XRAM_RSP_TRT_DIRTY",
+    "XRAM_RSP_DIR_LOCK",
+    "XRAM_RSP_DIR_UPDT",
+    "XRAM_RSP_DIR_RSP",
+    "XRAM_RSP_INVAL_LOCK",
+    "XRAM_RSP_INVAL_WAIT",
+    "XRAM_RSP_INVAL",
+    "XRAM_RSP_WRITE_DIRTY",
+  };
+  const char *ixr_cmd_fsm_str[] = {
+    "IXR_CMD_READ_IDLE",
+    "IXR_CMD_WRITE_IDLE",
+    "IXR_CMD_LLSC_IDLE",
+    "IXR_CMD_XRAM_IDLE",
+    "IXR_CMD_READ_NLINE",
+    "IXR_CMD_WRITE_NLINE",
+    "IXR_CMD_LLSC_NLINE",
+    "IXR_CMD_XRAM_DATA",
+  };
+  const char *llsc_fsm_str[] = {
+    "LLSC_IDLE",
+    "LL_DIR_LOCK",
+    "LL_DIR_HIT",
+    "LL_RSP",
+    "SC_DIR_LOCK",
+    "SC_DIR_HIT",
+    "SC_UPT_LOCK",
+    "SC_WAIT_UPT",
+    "SC_UPDATE",
+    "SC_TRT_LOCK",
+    "SC_INVAL_LOCK",
+    "SC_DIR_INVAL",
+    "SC_INVAL",
+    "SC_XRAM_SEND",
+    "SC_RSP_FALSE",
+    "SC_RSP_TRUE",
+    "LLSC_TRT_LOCK",
+    "LLSC_TRT_SET",
+    "LLSC_XRAM_REQ",
+  };
+  const char *cleanup_fsm_str[] = {
+    "CLEANUP_IDLE",
+    "CLEANUP_DIR_LOCK",
+    "CLEANUP_DIR_WRITE",
+    "CLEANUP_UPT_LOCK",
+    "CLEANUP_UPT_WRITE",
+    "CLEANUP_WRITE_RSP",
+    "CLEANUP_RSP",
+  };
+  const char *alloc_dir_fsm_str[] = {
+    "ALLOC_DIR_READ",
+    "ALLOC_DIR_WRITE",
+    "ALLOC_DIR_LLSC",
+    "ALLOC_DIR_CLEANUP",
+    "ALLOC_DIR_XRAM_RSP",
+  };
+  const char *alloc_trt_fsm_str[] = {
+    "ALLOC_TRT_READ",
+    "ALLOC_TRT_WRITE",
+    "ALLOC_TRT_LLSC",
+    "ALLOC_TRT_XRAM_RSP",
+    "ALLOC_TRT_IXR_RSP",
+  };
+  const char *alloc_upt_fsm_str[] = {
+    "ALLOC_UPT_WRITE",
+    "ALLOC_UPT_XRAM_RSP",
+    "ALLOC_UPT_INIT_RSP",
+    "ALLOC_UPT_CLEANUP",
+  };
+#endif
+
+#define tmpl(x) template<typename vci_param> x VciMemCacheV2S<vci_param>
+
+  using soclib::common::uint32_log2;
+
+  ////////////////////////////////
+  // 	Constructor 
+  ////////////////////////////////
+
+  tmpl(/**/)::VciMemCacheV2S( 
+      sc_module_name name,
+      const soclib::common::MappingTable &mtp,
+      const soclib::common::MappingTable &mtc,
+      const soclib::common::MappingTable &mtx,
+      const soclib::common::IntTab &vci_ixr_index,
+      const soclib::common::IntTab &vci_ini_index,
+      const soclib::common::IntTab &vci_tgt_index,
+      const soclib::common::IntTab &vci_tgt_index_cleanup,
+      size_t nways,
+      size_t nsets,
+      size_t nwords)
+
+    : soclib::caba::BaseModule(name),
+
+    p_clk("clk"),
+    p_resetn("resetn"),
+    p_vci_tgt("vci_tgt"),
+    p_vci_tgt_cleanup("vci_tgt_cleanup"),
+    p_vci_ini("vci_ini"),
+    p_vci_ixr("vci_ixr"),
+
+    m_initiators( 32 ),
+    m_ways( nways ),
+    m_sets( nsets ),
+    m_words( nwords ),
+    m_srcid_ixr( mtx.indexForId(vci_ixr_index) ),
+    m_srcid_ini( mtc.indexForId(vci_ini_index) ),
+    m_seglist(mtp.getSegmentList(vci_tgt_index)),
+    m_cseglist(mtc.getSegmentList(vci_tgt_index_cleanup)),
+    m_coherence_table( mtc.getCoherenceTable<vci_addr_t>() ),
+    m_atomic_tab( m_initiators ),
+    m_transaction_tab( TRANSACTION_TAB_LINES, nwords ),
+    m_update_tab( UPDATE_TAB_LINES ),
+    m_cache_directory( nways, nsets, nwords, vci_param::N ),
+#define L2 soclib::common::uint32_log2
+    m_x( L2(m_words), 2),
+    m_y( L2(m_sets), L2(m_words) + 2),
+    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
+    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
+#undef L2
+
+    //  FIFOs 
+    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
+    m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
+    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
+    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
+    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
+
+    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
+    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
+    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
+    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
+    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
+    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
+    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
+
+    m_cmd_llsc_addr_fifo("m_cmd_llsc_addr_fifo",4),
+    m_cmd_llsc_sc_fifo("m_cmd_llsc_sc_fifo",4),
+    m_cmd_llsc_srcid_fifo("m_cmd_llsc_srcid_fifo",4),
+    m_cmd_llsc_trdid_fifo("m_cmd_llsc_trdid_fifo",4),
+    m_cmd_llsc_pktid_fifo("m_cmd_llsc_pktid_fifo",4),
+    m_cmd_llsc_wdata_fifo("m_cmd_llsc_wdata_fifo",4),
+
+    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
+    
+    nseg(0),	
+    ncseg(0),	
+
+    r_read_fsm("r_read_fsm"),
+    r_write_fsm("r_write_fsm"),
+    r_init_rsp_fsm("r_init_rsp_fsm"),
+    r_cleanup_fsm("r_cleanup_fsm"),
+    r_llsc_fsm("r_llsc_fsm"),
+    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
+    r_xram_rsp_fsm("r_xram_rsp_fsm"),
+    r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
+    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
+    r_init_cmd_fsm("r_init_cmd_fsm"),
+    r_alloc_dir_fsm("r_alloc_dir_fsm"),
+    r_alloc_trt_fsm("r_alloc_trt_fsm"),
+    r_alloc_upt_fsm("r_alloc_upt_fsm")
+    {
+      assert(IS_POW_OF_2(nsets));
+      assert(IS_POW_OF_2(nwords));
+      assert(IS_POW_OF_2(nways));
+      assert(nsets);
+      assert(nwords);
+      assert(nways);
+      assert(nsets <= 1024);
+      assert(nwords <= 32);
+      assert(nways <= 32);
+
+
+      // Get the segments associated to the MemCache 
+      std::list<soclib::common::Segment>::iterator seg;
+
+      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
+        nseg++;
+      }
+      for(seg = m_cseglist.begin(); seg != m_cseglist.end() ; seg++) {
+        ncseg++;
+      }
+
+      m_seg = new soclib::common::Segment*[nseg];
+      size_t i = 0;
+      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) { 
+        m_seg[i] = &(*seg);
+        i++;
+      }
+      m_cseg = new soclib::common::Segment*[ncseg];
+      i = 0;
+      for ( seg = m_cseglist.begin() ; seg != m_cseglist.end() ; seg++ ) { 
+          m_cseg[i] = &(*seg);
+          i++;
+      }
+
+      // Memory cache allocation & initialisation
+      m_cache_data = new data_t**[nways];
+      for ( size_t i=0 ; i<nways ; ++i ) {
+        m_cache_data[i] = new data_t*[nsets];
+      }
+      for ( size_t i=0; i<nways; ++i ) {
+        for ( size_t j=0; j<nsets; ++j ) {
+          m_cache_data[i][j] = new data_t[nwords];
+          for ( size_t k=0; k<nwords; k++){
+            m_cache_data[i][j][k]=0;
+          }	
+        }
+      }
+
+      // Allocation for IXR_RSP FSM
+      r_ixr_rsp_to_xram_rsp_rok	    = new sc_signal<bool>[TRANSACTION_TAB_LINES];
+
+      // Allocation for XRAM_RSP FSM
+      r_xram_rsp_victim_data        = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_tgt_rsp_data    = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
+
+      // Allocation for READ FSM
+      r_read_data 			        = new sc_signal<data_t>[nwords];
+      r_read_to_tgt_rsp_data 		= new sc_signal<data_t>[nwords];
+
+      // Allocation for WRITE FSM
+      r_write_data 			        = new sc_signal<data_t>[nwords];
+      r_write_be 			        = new sc_signal<be_t>[nwords];
+      r_write_to_init_cmd_data 		= new sc_signal<data_t>[nwords];
+      r_write_to_init_cmd_we		= new sc_signal<bool>[nwords];
+      r_write_to_ixr_cmd_data	    = new sc_signal<data_t>[nwords];
+
+      // Allocation for LLSC FSM
+      r_llsc_to_ixr_cmd_data	    = new sc_signal<data_t>[nwords];
+
+
+      // Simulation
+
+      SC_METHOD(transition);
+      dont_initialize();
+      sensitive << p_clk.pos();
+
+      SC_METHOD(genMoore);
+      dont_initialize();
+      sensitive << p_clk.neg();
+
+    } // end constructor
+
+  /////////////////////////////////////////
+  // This function prints the statistics 
+  /////////////////////////////////////////
+
+  tmpl(void)::print_stats()
+  {
+    std::cout << "----------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
+      << "- READ RATE            = " << (double)m_cpt_read/m_cpt_cycles << std::endl
+      << "- READ MISS RATE       = " << (double)m_cpt_read_miss/m_cpt_read << std::endl
+      << "- WRITE RATE           = " << (double)m_cpt_write/m_cpt_cycles << std::endl
+      << "- WRITE MISS RATE      = " << (double)m_cpt_write_miss/m_cpt_write << std::endl
+      << "- WRITE BURST LENGTH   = " << (double)m_cpt_write_cells/m_cpt_write << std::endl
+      << "- UPDATE RATE          = " << (double)m_cpt_update/m_cpt_cycles << std::endl
+      << "- UPDATE ARITY         = " << (double)m_cpt_update_mult/m_cpt_update << std::endl
+      << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
+      << "- INVAL MULTICAST ARITY= " << (double)m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
+      << "- INVAL BROADCAST RATE = " << (double)m_cpt_inval_brdcast/m_cpt_cycles << std::endl
+      << "- SAVE DIRTY RATE      = " << (double)m_cpt_write_dirty/m_cpt_cycles << std::endl
+      << "- CLEANUP RATE         = " << (double)m_cpt_cleanup/m_cpt_cycles << std::endl
+      << "- LL RATE              = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
+      << "- SC RATE              = " << (double)m_cpt_sc/m_cpt_cycles << std::endl;
+  }
+
+  /////////////////////////////////
+  tmpl(/**/)::~VciMemCacheV2S()
+    /////////////////////////////////
+  {
+    for(size_t i=0; i<m_ways ; i++){
+      for(size_t j=0; j<m_sets ; j++){
+        delete [] m_cache_data[i][j];
+      }
+    }
+    for(size_t i=0; i<m_ways ; i++){
+      delete [] m_cache_data[i];
+    }
+    delete [] m_cache_data;
+    delete [] m_coherence_table;
+
+    delete [] r_ixr_rsp_to_xram_rsp_rok;
+
+    delete [] r_xram_rsp_victim_data;
+    delete [] r_xram_rsp_to_tgt_rsp_data;
+    delete [] r_xram_rsp_to_ixr_cmd_data;
+
+    delete [] r_read_data;
+    delete [] r_read_to_tgt_rsp_data;
+
+    delete [] r_write_data;
+    delete [] r_write_be;
+    delete [] r_write_to_init_cmd_data;
+  }
+
+  //////////////////////////////////
+  tmpl(void)::transition()
+    //////////////////////////////////
+  {
+    using soclib::common::uint32_log2;
+    //  RESET          
+    if ( ! p_resetn.read() ) {
+
+      //     Initializing FSMs
+      r_tgt_cmd_fsm 	= TGT_CMD_IDLE;
+      r_tgt_rsp_fsm 	= TGT_RSP_READ_IDLE;
+      r_init_cmd_fsm 	= INIT_CMD_INVAL_IDLE;
+      r_init_rsp_fsm 	= INIT_RSP_IDLE;
+      r_read_fsm 	= READ_IDLE;
+      r_write_fsm 	= WRITE_IDLE;
+      r_llsc_fsm 	= LLSC_IDLE;
+      r_cleanup_fsm 	= CLEANUP_IDLE;
+      r_alloc_dir_fsm   = ALLOC_DIR_READ;
+      r_alloc_trt_fsm   = ALLOC_TRT_READ;
+      r_alloc_upt_fsm   = ALLOC_UPT_WRITE;
+      r_ixr_rsp_fsm 	= IXR_RSP_IDLE;
+      r_xram_rsp_fsm 	= XRAM_RSP_IDLE;
+      r_ixr_cmd_fsm 	= IXR_CMD_READ_IDLE;
+
+      //  Initializing Tables
+      m_cache_directory.init();
+      m_atomic_tab.init();	
+      m_transaction_tab.init();
+
+      // initializing FIFOs and communication Buffers
+
+      m_cmd_read_addr_fifo.init();
+      m_cmd_read_length_fifo.init();
+      m_cmd_read_srcid_fifo.init();
+      m_cmd_read_trdid_fifo.init();
+      m_cmd_read_pktid_fifo.init();
+
+      m_cmd_write_addr_fifo.init();
+      m_cmd_write_eop_fifo.init();
+      m_cmd_write_srcid_fifo.init();
+      m_cmd_write_trdid_fifo.init();
+      m_cmd_write_pktid_fifo.init();
+      m_cmd_write_data_fifo.init();
+
+      m_cmd_llsc_addr_fifo.init();
+      m_cmd_llsc_srcid_fifo.init();
+      m_cmd_llsc_trdid_fifo.init();
+      m_cmd_llsc_pktid_fifo.init();
+      m_cmd_llsc_wdata_fifo.init();
+      m_cmd_llsc_sc_fifo.init();
+
+      r_read_to_tgt_rsp_req	    = false;
+      r_read_to_ixr_cmd_req	    = false;
+
+      r_write_to_tgt_rsp_req	= false;
+      r_write_to_ixr_cmd_req	= false;
+      r_write_to_init_cmd_req	= false;
+
+      r_cleanup_to_tgt_rsp_req	= false;
+
+      r_init_rsp_to_tgt_rsp_req	= false;
+
+      r_llsc_lfsr                       = -1;
+      r_llsc_to_tgt_rsp_req	    = false;
+      r_llsc_to_ixr_cmd_req	    = false;
+      r_llsc_to_init_cmd_req	= false;
+
+      for(size_t i=0; i<TRANSACTION_TAB_LINES ; i++){
+        r_ixr_rsp_to_xram_rsp_rok[i] = false;
+      }
+
+      r_xram_rsp_to_tgt_rsp_req	    = false;
+      r_xram_rsp_to_init_cmd_req    = false;
+      r_xram_rsp_to_ixr_cmd_req	    = false;
+      r_xram_rsp_trt_index	        = 0;
+
+      r_ixr_cmd_cpt         = 0;
+
+      r_copies_limit        = 3;
+
+      // Activity counters
+      m_cpt_cycles		    = 0;
+      m_cpt_read		    = 0;
+      m_cpt_read_miss	    = 0;
+      m_cpt_write		    = 0;
+      m_cpt_write_miss	    = 0;
+      m_cpt_write_cells	    = 0;
+      m_cpt_write_dirty	    = 0;
+      m_cpt_update		    = 0;
+      m_cpt_update_mult     = 0;
+      m_cpt_inval_brdcast 	= 0;
+      m_cpt_inval 		    = 0;
+      m_cpt_inval_mult 		= 0;
+      m_cpt_cleanup		    = 0;
+      m_cpt_ll     		    = 0;
+      m_cpt_sc     		    = 0;
+
+      return;
+    }
+
+    bool    cmd_read_fifo_put = false;
+    bool    cmd_read_fifo_get = false;
+
+    bool    cmd_write_fifo_put = false;
+    bool    cmd_write_fifo_get = false;
+
+    bool    cmd_llsc_fifo_put = false;
+    bool    cmd_llsc_fifo_get = false;
+
+#if DEBUG_VCI_MEM_CACHE 
+    std::cout << "---------------------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
+      << " - TGT_CMD FSM   = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
+      << " - TGT_RSP FSM   = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
+      << " - INIT_CMD FSM  = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
+      << " - INIT_RSP FSM  = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
+      << " - READ FSM      = " << read_fsm_str[r_read_fsm] << std::endl
+      << " - WRITE FSM     = " << write_fsm_str[r_write_fsm] << std::endl
+      << " - LLSC FSM      = " << llsc_fsm_str[r_llsc_fsm] << std::endl
+      << " - CLEANUP FSM   = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
+      << " - IXR_CMD FSM  = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
+      << " - IXR_RSP FSM   = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
+      << " - XRAM_RSP FSM  = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
+      << " - ALLOC_DIR FSM = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
+      << " - ALLOC_TRT FSM = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
+      << " - ALLOC_UPT FSM = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl;
+#endif
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
+    //
+    // There is 4 types of packets for the m_mem_segment :
+    // - READ    : a READ request has a length of 1 VCI cell. It can be a single word 
+    //             or an entire cache line, depending on the PLEN value.
+    // - WRITE   : a WRITE request has a maximum length of 16 cells, and can only
+    //             concern words in a same line.
+    // - LL      : The LL request has a length of 1 cell.
+    // - SC      : The SC request has a length of 1 cell. 
+    //             The WDATA field contains the data to write.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_cmd_fsm.read() ) {
+
+      //////////////////
+      case TGT_CMD_IDLE:
+        {
+          if ( p_vci_tgt.cmdval ) {
+            assert( (p_vci_tgt.srcid.read() < m_initiators)
+                && "VCI_MEM_CACHE error in VCI_MEM_CACHE : The received SRCID is larger than 31");
+
+            bool reached = false;
+            for ( size_t index = 0 ; index < nseg && !reached ; index++) 
+            {
+//              if ( m_seg[index]->contains((addr_t)(p_vci_tgt.address.read())) ) {
+              if ( m_seg[index]->contains(p_vci_tgt.address.read()) ) {
+                reached = true;
+                r_index = index;
+              }
+            }
+
+
+            if ( !reached ) 
+            { 
+              std::cout << "VCI_MEM_CACHE Out of segment access in VCI_MEM_CACHE" << std::endl;
+              std::cout << "Faulty address = " << std::hex << (addr_t)(p_vci_tgt.address.read()) << std::endl;
+              std::cout << "Faulty initiator = " << std::dec << p_vci_tgt.srcid.read() << std::endl;
+              exit(0);
+            } 
+            else if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_READ;
+            } 
+            else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ))
+            {  
+              r_tgt_cmd_fsm = TGT_CMD_WRITE;
+            } 
+            else if ((p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ) || 
+                (p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND) ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case TGT_CMD_READ:
+
+        {
+          assert(((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2))<=16)
+              && "VCI_MEM_CACHE All read request to the MemCache must stay within a cache line"); 
+
+          if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) {
+            cmd_read_fifo_put = true;
+            if ( p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+            else                  r_tgt_cmd_fsm = TGT_CMD_READ_EOP;		
+          } 
+          break;
+        }
+        //////////////////////
+      case TGT_CMD_READ_EOP:
+        {
+          if ( p_vci_tgt.cmdval && p_vci_tgt.eop ){
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_CMD_WRITE:
+        {
+
+          if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() ) {
+            cmd_write_fifo_put = true;
+            if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+
+          }
+          break;
+        }
+        ////////////////////
+      case TGT_CMD_ATOMIC:
+        {
+          assert(p_vci_tgt.eop && "Memory Cache Error: LL or SC command with length > 1 ");
+
+          if ( p_vci_tgt.cmdval && m_cmd_llsc_addr_fifo.wok() ) {
+            cmd_llsc_fifo_put = true;
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+    } // end switch tgt_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////////
+    //		INIT_RSP FSM
+    /////////////////////////////////////////////////////////////////////////
+    // This FSM controls the response to the update or invalidate requests
+    // sent by the memory cache to the L1 caches :
+    //
+    // - update request initiated by the WRITE FSM.  
+    //   The FSM decrements the proper entry in the Update/Inval Table.
+    //   It sends a request to the TGT_RSP FSM to complete the pending 
+    //   write transaction (acknowledge response to the writer processor), 
+    //   and clear the UPT entry when all responses have been received.  
+    // - invalidate request initiated by the XRAM_RSP FSM.
+    //   The FSM decrements the proper entry in the Update/Inval_Table,
+    //   and clear the entry when all responses have been received.
+    //
+    // All those response packets are one word, compact
+    // packets complying with the VCI advanced format. 
+    // The index in the Table is defined in the RTRDID field, and
+    // the Transaction type is defined in the Update/Inval Table.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_rsp_fsm.read() ) {
+
+      ///////////////////
+      case INIT_RSP_IDLE:
+        {
+
+          if ( p_vci_ini.rspval ) {
+            assert ( ( p_vci_ini.rtrdid.read() < m_update_tab.size() )
+                && "VCI_MEM_CACHE UPT index too large in VCI response paquet received by memory cache" );
+            assert ( p_vci_ini.reop 
+                && "VCI_MEM_CACHE All response packets to update/invalidate requests must be one cell" );
+            r_init_rsp_upt_index = p_vci_ini.rtrdid.read(); 
+            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_RSP_UPT_LOCK:	// decrement the number of expected responses
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) { 
+            size_t count = 0;
+            bool valid  = m_update_tab.decrement(r_init_rsp_upt_index.read(), count);
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+#endif
+            assert ( valid 
+                && "VCI_MEM_CACHE Invalid UPT entry in VCI response paquet received by memory cache" );
+
+            if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
+            else              r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_RSP_UPT_CLEAR:	// clear the UPT entry
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) {
+            r_init_rsp_srcid = m_update_tab.srcid(r_init_rsp_upt_index.read());
+            r_init_rsp_trdid = m_update_tab.trdid(r_init_rsp_upt_index.read());
+            r_init_rsp_pktid = m_update_tab.pktid(r_init_rsp_upt_index.read());
+            r_init_rsp_nline = m_update_tab.nline(r_init_rsp_upt_index.read());
+            bool need_rsp = m_update_tab.need_rsp(r_init_rsp_upt_index.read());
+            if ( need_rsp ) r_init_rsp_fsm = INIT_RSP_END;
+            else            r_init_rsp_fsm = INIT_RSP_IDLE;
+            m_update_tab.clear(r_init_rsp_upt_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_CLEAR update table : " << std::endl;
+	m_update_tab.print();
+#endif
+          }
+          break;
+        }
+        //////////////////
+      case INIT_RSP_END:
+        {
+
+          if ( !r_init_rsp_to_tgt_rsp_req ) {
+            r_init_rsp_to_tgt_rsp_req = true;
+            r_init_rsp_to_tgt_rsp_srcid = r_init_rsp_srcid.read();
+            r_init_rsp_to_tgt_rsp_trdid = r_init_rsp_trdid.read();
+            r_init_rsp_to_tgt_rsp_pktid = r_init_rsp_pktid.read();
+            r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+    } // end switch r_init_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		READ FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The READ FSM controls the read requests sent by processors.
+    // It takes the lock protecting the cache directory to check the cache line status:
+    // - In case of HIT, the fsm copies the data (one line, or one single word)
+    //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
+    //   The requesting initiator is registered in the cache directory.
+    // - In case of MISS, the READ fsm takes the lock protecting the transaction tab.
+    //   If a read transaction to the XRAM for this line already exists,
+    //   or if the transaction tab is full, the fsm is stalled.
+    //   If a transaction entry is free, the READ fsm sends a request to the XRAM.
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_read_fsm.read() ) {
+
+      ///////////////
+      case READ_IDLE:
+        {
+          if (m_cmd_read_addr_fifo.rok()) {
+            m_cpt_read++;
+            r_read_fsm = READ_DIR_LOCK;
+          }
+          break;
+        }
+        ///////////////////
+      case READ_DIR_LOCK:	// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            size_t way = 0;
+            DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
+#ifdef DDEBUG
+	   std::cout << "In READ_DIR_LOCK printing the entry of address is : " << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+            r_read_is_cnt   = entry.is_cnt;
+            r_read_dirty    = entry.dirty;
+            r_read_tag	    = entry.tag;
+            r_read_lock	    = entry.lock;
+            r_read_way	    = way;
+            r_read_d_copies = entry.d_copies; 
+            r_read_i_copies = entry.i_copies; 
+            r_read_count    = entry.count;
+
+            // In case of hit, the read acces must be registered in the copies bit-vector
+            if( entry.valid )  { 
+              r_read_fsm = READ_DIR_HIT;
+            } else {
+              r_read_fsm = READ_TRT_LOCK;
+              m_cpt_read_miss++;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_DIR_HIT:	// read hit : update the memory cache
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            // signals generation
+            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
+            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
+            bool is_cnt = ((r_read_count.read() >= r_copies_limit.read()) && cached_read) || r_read_is_cnt.read() || (m_cmd_read_trdid_fifo.read() & 0x4);
+            bool is_tlb = (m_cmd_read_trdid_fifo.read() & 0x4);
+
+            // read data in the cache
+            size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            size_t way = r_read_way.read();
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_data[i] = m_cache_data[way][set][i];
+            }
+
+            // update the cache directory (for the copies)
+            DirectoryEntry entry;
+            entry.valid	  = true;
+            entry.is_cnt  = is_cnt; // when we reach the limit of copies
+            entry.dirty	  = r_read_dirty.read();
+            entry.tag	  = r_read_tag.read();
+            entry.lock	  = r_read_lock.read();
+            if(cached_read && !is_tlb){  // Cached read, we update the copies vector
+              if(inst_read && !is_cnt){ // Instruction read, vector mode
+                assert(!(r_read_i_copies.read() & (0x1 << m_cmd_read_srcid_fifo.read())) && "MemCache Error : processor read on an already owned cache line");
+                entry.d_copies  = r_read_d_copies.read();
+                entry.i_copies  = r_read_i_copies.read() | (0x1 << m_cmd_read_srcid_fifo.read()); 
+                entry.count     = r_read_count.read() + 1;
+              }
+              if(!inst_read && !is_cnt){ // Data read, vector mode
+                assert(!(r_read_d_copies.read() & (0x1 << m_cmd_read_srcid_fifo.read())) && "MemCache Error : processor read on an already owned cache line");
+                entry.d_copies  = r_read_d_copies.read() | (0x1 << m_cmd_read_srcid_fifo.read()); 
+                entry.i_copies  = r_read_i_copies.read();
+                entry.count     = r_read_count.read() + 1;
+              }
+              if( is_cnt ) { // Counter mode
+                entry.count     = r_read_count.read() + 1;
+                entry.d_copies  = 0;
+                entry.i_copies  = 0;
+              } 
+            } else if( is_tlb && is_cnt ) { // Uncached read for TLB
+                entry.count     = r_read_count.read() + 1;
+                entry.d_copies  = 0;
+                entry.i_copies  = 0;
+            } else { // Uncached read
+              entry.d_copies = r_read_d_copies.read();
+              entry.i_copies = r_read_i_copies.read();
+              entry.count    = r_read_count.read();
+            }
+#ifdef DDEBUG
+	   std::cout << "In READ_DIR_HIT printing the entry of address is : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            m_cache_directory.write(set, way, entry);
+            r_read_fsm    = READ_RSP;
+          }
+          break;
+        }
+        //////////////
+      case READ_RSP: 		//  request the TGT_RSP FSM to return data
+        {
+          if( !r_read_to_tgt_rsp_req ) {	
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_to_tgt_rsp_data[i] = r_read_data[i];
+            }
+            r_read_to_tgt_rsp_word   = m_x[(vci_addr_t)m_cmd_read_addr_fifo.read()];
+            r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
+            cmd_read_fifo_get 		 = true;
+            r_read_to_tgt_rsp_req	 = true;
+            r_read_to_tgt_rsp_srcid	 = m_cmd_read_srcid_fifo.read();
+            r_read_to_tgt_rsp_trdid	 = m_cmd_read_trdid_fifo.read();
+            r_read_to_tgt_rsp_pktid	 = m_cmd_read_pktid_fifo.read();
+            r_read_fsm 			     = READ_IDLE;  
+          }
+          break;
+        }
+        ///////////////////
+      case READ_TRT_LOCK:	// read miss : check the Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t index = 0;
+            bool   hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())], index);
+            bool   hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())]);
+            bool   wok = !m_transaction_tab.full(index);
+            if( hit_read || !wok || hit_write ) {  // missing line already requested or no space
+              r_read_fsm = READ_IDLE;
+            } else {			   // missing line is requested to the XRAM
+              r_read_trt_index = index;
+              r_read_fsm       = READ_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_TRT_SET:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+            m_transaction_tab.set(r_read_trt_index.read(),
+                true,
+                m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
+                m_cmd_read_srcid_fifo.read(),
+                m_cmd_read_trdid_fifo.read(),
+                m_cmd_read_pktid_fifo.read(),
+                true,
+                m_cmd_read_length_fifo.read(),
+                m_x[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_read_fsm 	 = READ_XRAM_REQ;
+          }
+          break;
+        }
+        /////////////////////
+      case READ_XRAM_REQ:
+        {
+          if( !r_read_to_ixr_cmd_req ) {
+            cmd_read_fifo_get		= true;
+            r_read_to_ixr_cmd_req  	= true;
+            r_read_to_ixr_cmd_nline 	= m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            r_read_to_ixr_cmd_trdid 	= r_read_trt_index.read();
+            r_read_fsm 			          = READ_IDLE;
+          }
+          break;
+        }
+    } // end switch read_fsm
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //		WRITE FSM
+    ///////////////////////////////////////////////////////////////////////////////////
+    // The WRITE FSM handles the write bursts sent by the processors.
+    // All addresses in a burst must be in the same cache line.
+    // A complete write burst is consumed in the FIFO & copied to a local buffer.
+    // Then the FSM takes the lock protecting the cache directory, to check
+    // if the line is in the cache.
+    //
+    // - In case of HIT, the cache is updated.
+    //   If there is no other copy, an acknowledge response is immediately
+    //   returned to the writing processor.
+    //   if the data is cached by other processoris, the FSM takes the lock
+    //   protecting the Update Table (UPT) to register this update transaction.
+    //   If the UPT is full, it releases the lock  and waits. Then, it sends 
+    //   a multi-update request to all owners of the line (but the writer), 
+    //   through the INIT_CMD FSM. In case of multi-update transaction, the WRITE FSM 
+    //   does not respond to the writing processor, as this response will be sent by 
+    //   the INIT_RSP FSM when all update responses have been received.
+    //
+    // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
+    //   table (TRT). If a read transaction to the XRAM for this line already exists, 
+    //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free, 
+    //   the WRITE FSM register a new transaction in TRT, and sends a read line request 
+    //   to the XRAM. If the TRT is full, it releases the lock, and waits.
+    //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_write_fsm.read() ) {
+
+      ////////////////
+      case WRITE_IDLE:	// copy first word of a write burst in local buffer	
+        {
+          if ( m_cmd_write_addr_fifo.rok()) {
+            m_cpt_write++;
+            m_cpt_write_cells++;
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get	= true;
+            size_t index 	    = m_x[(vci_addr_t)(m_cmd_write_addr_fifo.read())];
+            r_write_address	    = (addr_t)(m_cmd_write_addr_fifo.read());
+            r_write_word_index	= index;
+            r_write_word_count	= 1;
+            r_write_data[index]	= m_cmd_write_data_fifo.read();
+            r_write_srcid	    = m_cmd_write_srcid_fifo.read();
+            r_write_trdid	    = m_cmd_write_trdid_fifo.read();
+            r_write_pktid	    = m_cmd_write_pktid_fifo.read();
+
+            // the be field must be set for all words 
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              if ( i == index ) r_write_be[i] = m_cmd_write_be_fifo.read();
+              else		        r_write_be[i] = 0x0;
+            }
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+                    r_write_byte=true;
+            else    r_write_byte=false;
+
+            if( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+            else                               r_write_fsm = WRITE_NEXT;
+          }
+          break;
+        }
+        ////////////////
+      case WRITE_NEXT:	// copy next word of a write burst in local buffer
+        {
+          if ( m_cmd_write_addr_fifo.rok() ) {
+            m_cpt_write_cells++;
+
+            // check that the next word is in the same cache line
+            assert( (m_nline[(vci_addr_t)(r_write_address.read())] == m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())])  
+                && "VCI_MEM_CACHE write error in vci_mem_cache : write burst over a line" );
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get=true;
+            size_t index 	        = r_write_word_index.read() + r_write_word_count.read();
+            r_write_be[index]       = m_cmd_write_be_fifo.read();
+            r_write_data[index]     = m_cmd_write_data_fifo.read();
+            r_write_word_count 	    = r_write_word_count.read() + 1;
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+              r_write_byte=true;
+            if ( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_LOCK:	// access directory to check hit/miss
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ) {
+            size_t  way = 0;
+            DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
+
+            // copy directory entry in local buffers in case of hit
+            if ( entry.valid )  {	
+              r_write_is_cnt    = entry.is_cnt;
+              r_write_lock	    = entry.lock;
+              r_write_tag       = entry.tag;
+              r_write_d_copies  = entry.d_copies;
+              r_write_i_copies  = entry.i_copies;
+              r_write_count     = entry.count;
+              r_write_way  	    = way;
+              if((entry.is_cnt && entry.count) ||
+                  entry.i_copies){
+                r_write_fsm      = WRITE_DIR_HIT_READ;
+              } else {
+                if(r_write_byte.read())
+                  r_write_fsm      = WRITE_DIR_HIT_READ;
+                else {
+                    bool owner     = (bool) (entry.d_copies & (0x1 << r_write_srcid.read()));
+                    bool no_update = (owner && (entry.count == 1)) || (entry.count==0);
+                    if( no_update ) r_write_fsm  = WRITE_DIR_HIT_RSP; 
+                    else            r_write_fsm  = WRITE_DIR_HIT;
+                }
+              }
+            } else {
+              r_write_fsm = WRITE_TRT_LOCK;
+              m_cpt_write_miss++;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_READ:	// read the cache and complete the buffer (data, when be!=0xF)
+        {
+          // update local buffer
+          size_t set	= m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	= r_write_way.read();
+          for(size_t i=0 ; i<m_words ; i++) {
+            data_t mask      = 0;
+            if  (r_write_be[i].read() & 0x1) mask = mask | 0x000000FF;
+            if  (r_write_be[i].read() & 0x2) mask = mask | 0x0000FF00;
+            if  (r_write_be[i].read() & 0x4) mask = mask | 0x00FF0000;
+            if  (r_write_be[i].read() & 0x8) mask = mask | 0xFF000000;
+            if(r_write_be[i].read()||r_write_is_cnt.read()||r_write_i_copies.read()) { // complete only if mask is not null (for energy consumption)
+              r_write_data[i]  = (r_write_data[i].read() & mask) | 
+                (m_cache_data[way][set][i] & ~mask);
+            }
+          } // end for
+
+          if((r_write_is_cnt.read() && r_write_count.read()) ||
+              r_write_i_copies.read()){
+              r_write_fsm    = WRITE_TRT_WRITE_LOCK;
+          } else {
+              bool owner     = (bool) (r_write_d_copies.read() & (0x1 << r_write_srcid.read()));
+              bool no_update = (owner && (r_write_count.read() == 1)) || (r_write_count.read()==0);
+              if( no_update )   r_write_fsm    = WRITE_DIR_HIT_RSP;
+              else              r_write_fsm    = WRITE_DIR_HIT;
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT:	// update the cache (data & dirty bit)
+        {
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.dirty	    = true;
+          entry.tag	        = r_write_tag.read();
+          entry.is_cnt      = r_write_is_cnt.read();
+          entry.lock	    = r_write_lock.read();
+          entry.d_copies    = r_write_d_copies.read();
+          entry.i_copies    = 0;
+          entry.count       = r_write_count.read();
+          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	    = r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          // write data in cache
+          for(size_t i=0 ; i<m_words ; i++) {
+            if  ( r_write_be[i].read() ) {
+              m_cache_data[way][set][i]  = r_write_data[i].read();
+            }
+          } // end for
+
+          // compute the actual number of copies & the modified bit vector
+          bool owner = (bool) (r_write_d_copies.read() & (0x1 << r_write_srcid.read()));
+          copy_t d_copies = r_write_d_copies.read() & ~(0x1 << r_write_srcid.read());
+          r_write_d_copies      = d_copies;
+          size_t count_signal   = r_write_count.read();
+          if(owner){
+            count_signal        = count_signal - 1;
+          }
+          r_write_count         = count_signal;
+
+          r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_RSP:	// update the cache (data & dirty bit) (no update)
+        {
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.dirty	    = true;
+          entry.tag	        = r_write_tag.read();
+          entry.is_cnt      = r_write_is_cnt.read();
+          entry.lock	    = r_write_lock.read();
+          entry.d_copies    = r_write_d_copies.read();
+          entry.i_copies    = 0;
+          entry.count       = r_write_count.read();
+          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	    = r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          // write data in cache
+          for(size_t i=0 ; i<m_words ; i++) {
+            if  ( r_write_be[i].read() ) {
+              m_cache_data[way][set][i]  = r_write_data[i].read();
+            }
+          } // end for
+
+          if ( !r_write_to_tgt_rsp_req.read() ) {
+            r_write_to_tgt_rsp_req	    = true;
+            r_write_to_tgt_rsp_srcid	= r_write_srcid.read();
+            r_write_to_tgt_rsp_trdid	= r_write_trdid.read();
+            r_write_to_tgt_rsp_pktid	= r_write_pktid.read();
+            r_write_fsm 		        = WRITE_IDLE;
+          } else {
+            r_write_fsm = WRITE_RSP;
+          }
+          break;
+        }
+
+        /////////////////////
+      case WRITE_UPT_LOCK: 	// Try to register the request in Update Table
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool        wok        = false;
+            size_t      index      = 0;
+            size_t      srcid      = r_write_srcid.read();
+            size_t      trdid      = r_write_trdid.read();
+            size_t      pktid      = r_write_pktid.read();
+            addr_t      nline      = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t      nb_copies  = r_write_count.read();
+
+            wok =m_update_tab.set(true,	// it's an update transaction
+                false,                  // it's not a broadcast
+                true,                   // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_write_fsm = WRITE_UPDATE;
+            else       r_write_fsm = WRITE_WAIT_UPT;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT_UPT:	// release the lock protecting UPT
+        {
+          r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        //////////////////
+      case WRITE_UPDATE:	// send a multi-update request to INIT_CMD fsm
+        {
+
+          if ( !r_write_to_init_cmd_req ) {
+            r_write_to_init_cmd_req      = true;
+            r_write_to_init_cmd_brdcast  = false;
+            r_write_to_init_cmd_trdid    = r_write_upt_index.read();
+            r_write_to_init_cmd_nline    = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index    = r_write_word_index.read();
+            r_write_to_init_cmd_count    = r_write_word_count.read();
+            r_write_to_init_cmd_d_copies = r_write_d_copies.read();
+
+            for(size_t i=0; i<m_words ; i++){
+              if(r_write_be[i].read())  r_write_to_init_cmd_we[i]=true;
+              else                      r_write_to_init_cmd_we[i]=false;
+            }
+
+            size_t min = r_write_word_index.read();
+            size_t max = r_write_word_index.read() + r_write_word_count.read();
+            for (size_t i=min ; i<max ; i++) {
+              r_write_to_init_cmd_data[i] = r_write_data[i];
+            }
+            r_write_fsm = WRITE_IDLE; // Response will be sent after receiving
+            // all update responses
+          }
+          break;
+        }
+        ///////////////
+      case WRITE_RSP:		// send a request to TGT_RSP FSM to acknowledge the write
+        {
+          if ( !r_write_to_tgt_rsp_req.read() ) {
+            r_write_to_tgt_rsp_req	    = true;
+            r_write_to_tgt_rsp_srcid	= r_write_srcid.read();
+            r_write_to_tgt_rsp_trdid	= r_write_trdid.read();
+            r_write_to_tgt_rsp_pktid	= r_write_pktid.read();
+            r_write_fsm 		        = WRITE_IDLE;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_LOCK:	// Miss : check Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t hit_index = 0;
+            size_t wok_index = 0;
+            bool hit_read  = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(r_write_address.read())],hit_index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(r_write_address.read())]);
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( hit_read ) {	// register the modified data in TRT 
+              r_write_trt_index = hit_index;
+              r_write_fsm       = WRITE_TRT_DATA;
+            } else if ( wok && !hit_write ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_TRT_SET;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT_TRT;
+            }
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT_TRT:	// release the lock protecting TRT
+        { 
+          r_write_fsm = WRITE_DIR_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_TRT_SET:	// register a new transaction in TRT (Write Buffer)
+        {  
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) 
+          {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) 
+            {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.set(r_write_trt_index.read(),
+                true,				// read request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                r_write_srcid.read(),
+                r_write_trdid.read(),
+                r_write_pktid.read(),
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                be_vector,
+                data_vector);
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_write_fsm = WRITE_XRAM_REQ;
+          }
+          break;
+        }  
+        ///////////////////
+      case WRITE_TRT_DATA:	// update an entry in TRT (Write Buffer)
+        { 
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.write_data_mask(r_write_trt_index.read(),
+                be_vector,
+                data_vector);
+            r_write_fsm = WRITE_RSP;
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_DATA transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_REQ:	// send a request to IXR_CMD FSM
+        {  
+
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req   = true;
+            r_write_to_ixr_cmd_write = false;
+            r_write_to_ixr_cmd_nline = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
+            r_write_fsm              = WRITE_RSP;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_WRITE_LOCK:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            size_t wok_index = 0;
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( wok ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_INVAL_LOCK;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT_TRT;
+            }
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool        wok       = false;
+            size_t      index     = 0;
+            size_t      srcid     = r_write_srcid.read();
+            size_t      trdid     = r_write_trdid.read();
+            size_t      pktid     = r_write_pktid.read();
+            addr_t	    nline     = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t      nb_copies = r_write_count.read();
+
+            wok =m_update_tab.set(false,	// it's an inval transaction
+                true,                       // it's a broadcast
+                true,                       // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_INVAL_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_write_fsm = WRITE_DIR_INVAL;
+            else       r_write_fsm = WRITE_WAIT_TRT;
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_INVAL:
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) &&
+              (r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) )
+          {
+            m_transaction_tab.set(r_write_trt_index.read(),
+                false,				// write request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                0,
+                0,
+                0,
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_DIR_INVAL transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            // invalidate directory entry
+            DirectoryEntry entry;
+            entry.valid	   = false;
+            entry.dirty	   = false;
+            entry.tag	   = 0;
+            entry.is_cnt   = false;
+            entry.lock	   = false;
+            entry.d_copies = 0;
+            entry.i_copies = 0;
+            entry.count    = 0;
+            size_t set	   = m_y[(vci_addr_t)(r_write_address.read())];
+            size_t way	   = r_write_way.read();
+            m_cache_directory.write(set, way, entry);
+
+            r_write_fsm = WRITE_INVAL;
+          } else {
+            assert(false && "LOCK ERROR in WRITE_FSM, STATE = WRITE_DIR_INVAL");
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_INVAL:
+        {
+          if ( !r_write_to_init_cmd_req ) {
+            r_write_to_init_cmd_req      = true;
+            r_write_to_init_cmd_brdcast  = true;
+            r_write_to_init_cmd_trdid    = r_write_upt_index.read();
+            r_write_to_init_cmd_nline    = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index    = 0;
+            r_write_to_init_cmd_count    = 0;
+            r_write_to_init_cmd_d_copies = 0;
+
+            for(size_t i=0; i<m_words ; i++){
+              r_write_to_init_cmd_we[i]=false;
+              r_write_to_init_cmd_data[i] = 0;
+            }
+            r_write_fsm = WRITE_XRAM_SEND;
+            // all update responses
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_SEND:
+        {
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req     = true;
+            r_write_to_ixr_cmd_write   = true;
+            r_write_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
+            for(size_t i=0; i<m_words; i++){
+              r_write_to_ixr_cmd_data[i] = r_write_data[i];
+            }
+            r_write_fsm                 = WRITE_IDLE;
+          }
+          break;
+        }
+    } // end switch r_write_fsm
+
+    ///////////////////////////////////////////////////////////////////////
+    //		IXR_CMD FSM
+    ///////////////////////////////////////////////////////////////////////
+    // The IXR_CMD fsm controls the command packets to the XRAM :
+    // - It sends a single cell VCI read to the XRAM in case of MISS request
+    // posted by the READ, WRITE or LLSC FSMs : the TRDID field contains 
+    // the Transaction Tab index.
+    // The VCI response is a multi-cell packet : the N cells contain
+    // the N data words.
+    // - It sends a multi-cell VCI write when the XRAM_RSP FSM request 
+    // to save a dirty line to the XRAM. 
+    // The VCI response is a single cell packet.
+    // This FSM handles requests from the READ, WRITE, LLSC & XRAM_RSP FSMs 
+    // with a round-robin priority.
+    ////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_cmd_fsm.read() ) {
+      //////////////////////// 
+      case IXR_CMD_READ_IDLE:
+        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_WRITE_IDLE:
+        if      ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_LLSC_IDLE:
+        if      ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_XRAM_IDLE:
+        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        break;
+        /////////////////////////
+      case IXR_CMD_READ_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;		
+          r_read_to_ixr_cmd_req = false;
+        }
+        break;
+        //////////////////////////
+      case IXR_CMD_WRITE_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          if( r_write_to_ixr_cmd_write.read()){
+            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+              r_ixr_cmd_cpt = 0;
+              r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
+              r_write_to_ixr_cmd_req = false;
+            } else {
+              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+            }
+          } else {
+            r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;		
+            r_write_to_ixr_cmd_req = false;
+          }
+        }
+        break;
+        /////////////////////////
+      case IXR_CMD_LLSC_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          if( r_llsc_to_ixr_cmd_write.read()){
+            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+              r_ixr_cmd_cpt = 0;
+              r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;
+              r_llsc_to_ixr_cmd_req = false;
+            } else {
+              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+            }
+          } else {
+            r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;		
+            r_llsc_to_ixr_cmd_req = false;
+          }
+        }
+        break;
+        ////////////////////////
+      case IXR_CMD_XRAM_DATA:
+        if ( p_vci_ixr.cmdack ) {
+          if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+            r_ixr_cmd_cpt = 0;
+            r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
+            r_xram_rsp_to_ixr_cmd_req = false;
+          } else {
+            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+          }
+        }
+        break;
+
+    } // end switch r_ixr_cmd_fsm
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                IXR_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The IXR_RSP FSM receives the response packets from the XRAM,
+    // for both write transaction, and read transaction.
+    //
+    // - A response to a write request is a single-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The FSM takes the lock protecting the TRT, and the corresponding
+    // entry is erased.
+    //	
+    // - A response to a read request is a multi-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The N cells contain the N words of the cache line in the RDATA field.
+    // The FSM takes the lock protecting the TRT to store the line in the TRT
+    // (taking into account the write requests already stored in the TRT).
+    // When the line is completely written, the corresponding rok signal is set.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_rsp_fsm.read() ) {
+
+      ///////////////////
+      case IXR_RSP_IDLE:	// test if it's a read or a write transaction
+        {
+          if ( p_vci_ixr.rspval ) {
+            r_ixr_rsp_cpt   = 0;
+            r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
+            if ( p_vci_ixr.reop )  r_ixr_rsp_fsm = IXR_RSP_ACK;
+            else                   r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
+          }
+          break;  
+        }
+        ////////////////////////
+      case IXR_RSP_ACK:        // Acknowledge the vci response
+        r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
+        break;
+        ////////////////////////
+      case IXR_RSP_TRT_ERASE: 	// erase the entry in the TRT
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP ) {
+            m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
+            r_ixr_rsp_fsm = IXR_RSP_IDLE;
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_ERASE transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ///////////////////////
+      case IXR_RSP_TRT_READ:		// write data in the TRT
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval ) {
+            bool   eop  	= p_vci_ixr.reop.read();
+            data_t data 	= p_vci_ixr.rdata.read();
+            size_t index        = r_ixr_rsp_trt_index.read();
+            assert( eop == (r_ixr_rsp_cpt.read() == (m_words-1)) 
+                && "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
+            m_transaction_tab.write_rsp(index, r_ixr_rsp_cpt.read(), data);
+            r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
+            if ( eop ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_READ transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+              r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
+              r_ixr_rsp_fsm = IXR_RSP_IDLE;
+            }
+          }
+          break;
+        }
+    } // end swich r_ixr_rsp_fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                XRAM_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
+    // The cache line has been written in the TRT buffer by the IXR_FSM.
+    //
+    // When a response is available, the corresponding TRT entry 
+    // is copied in a local buffer to be written in the cache. 
+    // Then, the FSM releases the lock protecting the TRT, and takes the lock 
+    // protecting the cache directory.
+    // It selects a cache slot and writes the line in the cache.
+    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
+    // FSM to return the cache line to the registered processor.
+    // If there is no empty slot, a victim line is evicted, and
+    // invalidate requests are sent to the L1 caches containing copies.
+    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD 
+    // FSM to save the victim line to the XRAM, and register the write transaction
+    // in the TRT (using the entry previously used by the read transaction).
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_xram_rsp_fsm.read() ) {
+
+      ///////////////////
+      case XRAM_RSP_IDLE:	// test if there is a response with a round robin priority
+        {
+          size_t ptr   = r_xram_rsp_trt_index.read();
+          size_t lines = TRANSACTION_TAB_LINES;
+          for(size_t i=0; i<lines; i++){
+            size_t index=(i+ptr+1)%lines;
+            if(r_ixr_rsp_to_xram_rsp_rok[index]){
+              r_xram_rsp_trt_index=index;
+              r_ixr_rsp_to_xram_rsp_rok[index]=false;
+              r_xram_rsp_fsm           = XRAM_RSP_DIR_LOCK;
+              break;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_IDLE state" << std::endl;
+#endif
+            }
+          }
+          break;  
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_LOCK: 	// Take the lock on the directory
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) {
+            r_xram_rsp_fsm           = XRAM_RSP_TRT_COPY;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_LOCK state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_TRT_COPY:		// Copy the TRT entry in the local buffer and eviction of a cache line
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) ) {
+            size_t index = r_xram_rsp_trt_index.read();
+            TransactionTabEntry    trt_entry(m_transaction_tab.read(index));	
+
+            r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
+
+            // selects & extracts a victim line from cache
+            size_t way = 0;
+            size_t set = m_y[(vci_addr_t)(trt_entry.nline * m_words * 4)];
+            DirectoryEntry victim(m_cache_directory.select(set, way));
+
+            for (size_t i=0 ; i<m_words ; i++) r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
+
+            bool inval = (victim.count && victim.valid) ;
+
+            r_xram_rsp_victim_d_copies = victim.d_copies;
+            r_xram_rsp_victim_i_copies = victim.i_copies;
+            r_xram_rsp_victim_count    = victim.count;
+            r_xram_rsp_victim_way      = way;
+            r_xram_rsp_victim_set      = set;
+            r_xram_rsp_victim_nline    = victim.tag*m_sets + set;
+            r_xram_rsp_victim_is_cnt   = victim.is_cnt;
+            r_xram_rsp_victim_inval    = inval ;
+            r_xram_rsp_victim_dirty    = victim.dirty;
+
+            r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_TRT_COPY state" << std::endl;
+	std::cout << "Victim way : " << std::hex << way << " set " << std::hex << set << std::endl;
+	victim.print();
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP ) {
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state" << std::endl;
+#endif
+            size_t index;
+            if(m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index)){
+              r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+
+            }
+	    else if(m_update_tab.is_full() && r_xram_rsp_victim_inval.read()){
+	      r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+	    }
+            else {
+              r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_DIR_UPDT state" << std::endl;
+#endif
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_WAIT:
+        {
+          r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
+          break;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_UPDT:		// updates the cache (both data & directory)
+        {
+          // signals generation
+          bool inst_read = (r_xram_rsp_trt_buf.trdid & 0x2) && r_xram_rsp_trt_buf.proc_read; // It is an instruction read
+          bool cached_read = (r_xram_rsp_trt_buf.trdid & 0x1) && r_xram_rsp_trt_buf.proc_read;
+          bool is_tlb = (r_xram_rsp_trt_buf.trdid & 0x4) && r_xram_rsp_trt_buf.proc_read;
+
+          // update data
+          size_t set   = r_xram_rsp_victim_set.read();
+          size_t way   = r_xram_rsp_victim_way.read();
+          for(size_t i=0; i<m_words ; i++){
+            m_cache_data[way][set][i] = r_xram_rsp_trt_buf.wdata[i];
+          }
+          // compute dirty 
+          bool dirty = false;
+          for(size_t i=0; i<m_words;i++){
+            dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
+          }
+
+          // update directory
+          DirectoryEntry entry;
+          entry.valid	  = true;
+          entry.is_cnt    = is_tlb;
+          entry.lock	  = false;
+          entry.dirty	  = dirty;
+          entry.tag	    = r_xram_rsp_trt_buf.nline / m_sets;
+          if(cached_read && !is_tlb) {
+            if(inst_read) {
+              entry.i_copies = 0x1 << r_xram_rsp_trt_buf.srcid;
+              entry.d_copies = 0x0;
+              entry.count    = 1;
+            } else {
+              entry.i_copies = 0x0;
+              entry.d_copies = 0x1 << r_xram_rsp_trt_buf.srcid;
+              entry.count    = 1;
+            }
+          } else if (is_tlb && !r_xram_rsp_trt_buf.pktid) {
+              entry.count     = 1;
+              entry.d_copies  = 0;
+              entry.i_copies  = 0;
+          } else {
+            entry.d_copies = 0;
+            entry.i_copies = 0;
+            entry.count    = 0;
+          }
+          m_cache_directory.write(set, way, entry);
+#ifdef DDEBUG
+	   std::cout << "printing the entry : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_DIR_UPDT transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          if(r_xram_rsp_victim_inval.read()){
+            bool    brdcast = r_xram_rsp_victim_is_cnt.read();
+            size_t index;
+            size_t count_copies = r_xram_rsp_victim_count.read();
+
+            bool	 wok = m_update_tab.set(false,	// it's an inval transaction
+                brdcast,                          // set brdcast bit
+                false,  // it does not need a response
+                0,
+                0,
+                0,
+                r_xram_rsp_victim_nline.read(),
+                count_copies,
+                index);
+
+#ifdef IDEBUG
+            std::cout << "xram_rsp : record invalidation, time = " << std::dec << m_cpt_cycles << std::endl;
+            m_update_tab.print();
+#endif
+            r_xram_rsp_upt_index = index;
+            if(!wok) {
+              assert(false && "mem_cache error : xram_rsp_dir_upt, an update_tab entry was free but write unsuccessful");
+            }
+          }
+          // If the victim is not dirty, we erase the entry in the TRT
+          if      (!r_xram_rsp_victim_dirty.read()){
+	  m_transaction_tab.erase(r_xram_rsp_trt_index.read());
+
+	  }
+          // Next state
+          if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
+          else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+          else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+          else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          break;
+        }
+        ////////////////////////
+      case XRAM_RSP_TRT_DIRTY:		// set the TRT entry (write line to XRAM) if the victim is dirty
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP ) {
+            m_transaction_tab.set(r_xram_rsp_trt_index.read(),
+                false,				// write to XRAM
+                r_xram_rsp_victim_nline.read(), // line index
+                0,
+                0,
+                0,
+                false,
+                0,
+                0,
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0) );
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_TRT_DIRTY transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+          }
+          break;
+        }
+        //////////////////////
+      case XRAM_RSP_DIR_RSP:     // send a request to TGT_RSP FSM in case of read
+        {
+          if ( !r_xram_rsp_to_tgt_rsp_req ) {
+            r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
+            r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
+            r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
+            for (size_t i=0; i < m_words; i++) {
+              r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
+            } 
+            r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
+            r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
+            r_xram_rsp_to_tgt_rsp_req    = true;
+
+            if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY; 
+            else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#ifdef DDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_RSP state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ////////////////////
+      case XRAM_RSP_INVAL:	// send invalidate request to INIT_CMD FSM
+        {
+          if( !r_xram_rsp_to_init_cmd_req ) {	      
+            r_xram_rsp_to_init_cmd_req      = true; 
+            r_xram_rsp_to_init_cmd_brdcast  = r_xram_rsp_victim_is_cnt.read();
+            r_xram_rsp_to_init_cmd_nline    = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_init_cmd_trdid    = r_xram_rsp_upt_index;
+            r_xram_rsp_to_init_cmd_d_copies = r_xram_rsp_victim_d_copies ;
+            r_xram_rsp_to_init_cmd_i_copies = r_xram_rsp_victim_i_copies ;
+            if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+            else		                    r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef DDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL state" << std::endl;
+#endif
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_WRITE_DIRTY:	// send a write request to IXR_CMD FSM
+        {
+          if ( !r_xram_rsp_to_ixr_cmd_req ) {
+            r_xram_rsp_to_ixr_cmd_req = true;
+            r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
+            for(size_t i=0; i<m_words ; i++) {
+              r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
+            }
+            m_cpt_write_dirty++;
+            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_WRITE_DIRTY state" << std::endl;
+#endif
+          }
+          break;
+        }
+    } // end swich r_xram_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		CLEANUP FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The CLEANUP FSM handles the cleanup request from L1 caches.
+    // It accesses the cache directory to update the list of copies.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+    switch ( r_cleanup_fsm.read() ) {
+
+      ///////////////////
+      case CLEANUP_IDLE:
+        {
+
+          if ( p_vci_tgt_cleanup.cmdval.read() ) {
+            assert( (p_vci_tgt_cleanup.srcid.read() < m_initiators) &&
+                "VCI_MEM_CACHE error in VCI_MEM_CACHE in the CLEANUP network : The received SRCID is larger than 31");
+            bool reached = false;
+            for ( size_t index = 0 ; index < ncseg && !reached ; index++ ){
+              if ( m_cseg[index]->contains((addr_t)(p_vci_tgt_cleanup.address.read())) ){
+                reached = true;
+              }
+            }
+            if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
+                (((addr_t)(p_vci_tgt_cleanup.address.read())) != BROADCAST_ADDR) &&
+                reached) {
+
+              m_cpt_cleanup++;
+
+              r_cleanup_nline      = (addr_t)(m_nline[(vci_addr_t)(p_vci_tgt_cleanup.address.read())]) ;
+              r_cleanup_srcid      = p_vci_tgt_cleanup.srcid.read();
+              r_cleanup_trdid      = p_vci_tgt_cleanup.trdid.read();
+              r_cleanup_pktid      = p_vci_tgt_cleanup.pktid.read();
+
+              r_cleanup_fsm        = CLEANUP_DIR_LOCK;
+            }
+          }
+          break;
+        }
+        //////////////////////
+      case CLEANUP_DIR_LOCK:
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) {
+
+            // Read the directory
+            size_t way = 0;
+	        addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
+            DirectoryEntry entry = m_cache_directory.read(cleanup_address , way);
+#ifdef DDEBUG
+	   std::cout << "In CLEANUP_DIR_LOCK printing the entry of address is : " << std::hex << cleanup_address << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+            r_cleanup_is_cnt    = entry.is_cnt;
+            r_cleanup_dirty	    = entry.dirty;
+            r_cleanup_tag	    = entry.tag;
+            r_cleanup_lock	    = entry.lock;
+            r_cleanup_way	    = way;
+            r_cleanup_d_copies  = entry.d_copies;
+            r_cleanup_i_copies  = entry.i_copies;
+            r_cleanup_count     = entry.count;
+            // In case of hit, the copy must be cleaned in the copies bit-vector
+            if( entry.valid )  {
+              r_cleanup_fsm = CLEANUP_DIR_WRITE;
+            } else {
+              r_cleanup_fsm = CLEANUP_UPT_LOCK;
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case CLEANUP_DIR_WRITE:
+        {
+          size_t way      = r_cleanup_way.read();
+#define L2 soclib::common::uint32_log2
+          size_t set      = m_y[(vci_addr_t)(r_cleanup_nline.read() << (L2(m_words) +2))];
+#undef L2
+          bool cleanup_inst  = r_cleanup_trdid.read() & 0x1; 
+
+          // update the cache directory (for the copies)
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.is_cnt  = r_cleanup_is_cnt.read();
+          entry.dirty	= r_cleanup_dirty.read();
+          entry.tag	= r_cleanup_tag.read();
+          entry.lock	= r_cleanup_lock.read();
+          if(r_cleanup_is_cnt.read()) { // Directory is a counter
+            entry.count  = r_cleanup_count.read() -1;
+            entry.i_copies = 0;
+            entry.d_copies = 0;
+            // response to the cache 
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          else{                         // Directory is a vector
+            if(cleanup_inst){           // Cleanup from a ICACHE
+              if(r_cleanup_i_copies.read() & (0x1 << r_cleanup_srcid.read())){ // hit
+                entry.count  = r_cleanup_count.read() -1;
+                r_cleanup_fsm = CLEANUP_RSP;
+              } else { // miss
+                assert(false && "MemCache ERROR : Cleanup instruction hit but the line is not shared");
+              }
+              entry.i_copies  = r_cleanup_i_copies.read() & ~(0x1 << r_cleanup_srcid.read());
+              entry.d_copies  = r_cleanup_d_copies.read();
+            } else {                    // Cleanup from a DCACHE
+              if(r_cleanup_d_copies.read() & (0x1 << r_cleanup_srcid.read())){ // hit
+                entry.count  = r_cleanup_count.read() -1;
+                r_cleanup_fsm = CLEANUP_RSP; 
+              } else { // miss
+                assert(false && "MemCache ERROR : Cleanup data hit but the line is not shared");
+              }
+              entry.i_copies  = r_cleanup_i_copies.read();
+              entry.d_copies  = r_cleanup_d_copies.read() & ~(0x1 << r_cleanup_srcid.read());
+            }
+          }
+          m_cache_directory.write(set, way, entry);  
+
+          // response to the cache      
+//          r_cleanup_fsm = CLEANUP_RSP;
+
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_LOCK:
+        {
+          if( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
+          {
+            size_t index = 0;
+            bool hit_inval;
+            hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
+            if(!hit_inval) {
+#ifdef DEBUG_VCI_MEM_CACHE
+              std::cout << "MEM_CACHE WARNING: cleanup with no corresponding entry at address : " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::dec << std::endl;
+#endif
+              r_cleanup_fsm = CLEANUP_RSP;
+            } else {
+              r_cleanup_write_srcid = m_update_tab.srcid(index);
+              r_cleanup_write_trdid = m_update_tab.trdid(index);
+              r_cleanup_write_pktid = m_update_tab.pktid(index);
+              r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
+              r_cleanup_fsm = CLEANUP_UPT_WRITE;
+            }
+            r_cleanup_index.write(index) ; 
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_WRITE:
+        {
+          size_t count = 0;
+          m_update_tab.decrement(r_cleanup_index.read(), count); // &count
+          if(count == 0){
+            m_update_tab.clear(r_cleanup_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " CLEANUP_UPT_WRITE update table : " << std::endl;
+	m_update_tab.print();
+#endif
+
+            if(r_cleanup_need_rsp.read()){
+              r_cleanup_fsm = CLEANUP_WRITE_RSP ;
+            } else {
+              r_cleanup_fsm = CLEANUP_RSP;
+            }
+          } else {
+            r_cleanup_fsm = CLEANUP_RSP ;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_WRITE_RSP:
+        {
+          if( !r_cleanup_to_tgt_rsp_req.read()) {
+            r_cleanup_to_tgt_rsp_req     = true;
+            r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
+            r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
+            r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_RSP:
+        {
+          if(p_vci_tgt_cleanup.rspack)
+            r_cleanup_fsm = CLEANUP_IDLE;
+          break;
+        }
+    } // end switch cleanup fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		LLSC FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The LLSC FSM handles the LL & SC atomic access.
+    //
+    // For a LL :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the LL request is registered in the Atomic Table and the
+    // response is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state.
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the LL request is not consumed in the FIFO.
+    //
+    // For a SC :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the Atomic Table is checked and the proper response
+    // (true or false is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state. 
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the SC request is not consumed in the FIFO.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_llsc_fsm.read() ) {
+
+      ///////////////
+      case LLSC_IDLE:		// test LL / SC
+        {
+          if( m_cmd_llsc_addr_fifo.rok() ) {
+            if(m_cmd_llsc_sc_fifo.read()){
+              m_cpt_sc++;
+              r_llsc_fsm = SC_DIR_LOCK;
+            }
+            else{
+              m_cpt_ll++;
+              r_llsc_fsm = LL_DIR_LOCK;
+            }
+          }	
+          break;
+        }
+        /////////////////
+      case LL_DIR_LOCK:		// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+            size_t way = 0;
+            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+            r_llsc_is_cnt     = entry.is_cnt;
+            r_llsc_dirty      = entry.dirty;
+            r_llsc_tag        = entry.tag;
+            r_llsc_way        = way;
+            r_llsc_d_copies   = entry.d_copies;
+            r_llsc_i_copies   = entry.i_copies ;
+            r_llsc_count      = entry.count ;
+
+            // set Atomic Table
+            m_atomic_tab.set(m_cmd_llsc_srcid_fifo.read(), m_cmd_llsc_addr_fifo.read());
+
+            if ( entry.valid )  r_llsc_fsm = LL_DIR_HIT;
+            else                r_llsc_fsm = LLSC_TRT_LOCK;
+          }
+          break;
+        }
+        ////////////////
+      case LL_DIR_HIT:		// read hit : update the memory cache
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+
+          // update directory (lock bit & copies)
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.is_cnt      = r_llsc_is_cnt.read();
+          entry.dirty	    = r_llsc_dirty.read();
+          entry.lock	    = true;
+          entry.tag	        = r_llsc_tag.read();
+          entry.d_copies    = r_llsc_d_copies.read();
+          entry.i_copies    = r_llsc_i_copies.read();
+          entry.count       = r_llsc_count.read();
+          m_cache_directory.write(set, way, entry);
+
+          // read data in cache
+          r_llsc_data	= m_cache_data[way][set][word];
+
+          r_llsc_fsm 	= LL_RSP;
+          break;
+        }
+        ////////////
+      case LL_RSP:		// request the TGT_RSP FSM to return data
+        {
+          if ( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_data	= r_llsc_data.read();
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_fsm = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_DIR_LOCK:
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+            size_t way = 0;
+            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+            bool ok = m_atomic_tab.isatomic(m_cmd_llsc_srcid_fifo.read(),m_cmd_llsc_addr_fifo.read());
+            if( ok ) {
+              r_llsc_is_cnt   = entry.is_cnt;
+              r_llsc_dirty    = entry.dirty;
+              r_llsc_tag      = entry.tag;
+              r_llsc_way      = way;
+              r_llsc_d_copies = entry.d_copies;
+              r_llsc_i_copies = entry.i_copies;
+              r_llsc_count    = entry.count;
+              /* to avoid livelock, force the atomic access to fail (pseudo-)randomly */
+              bool fail = (r_llsc_lfsr % (64) == 0);
+              r_llsc_lfsr = (r_llsc_lfsr >> 1) ^ ((-(r_llsc_lfsr & 1)) & 0xd0000001);
+#ifdef RANDOMIZE_SC
+              if(fail){
+#else
+              if(0){
+#endif
+                r_llsc_fsm = SC_RSP_FALSE;
+              } else {
+                  if ( entry.valid ){
+                      if((entry.is_cnt && entry.count) || entry.i_copies) {
+                          r_llsc_fsm = SC_TRT_LOCK;
+                      } else {
+                          r_llsc_fsm = SC_DIR_HIT;
+                      }
+                  }
+                  else r_llsc_fsm = LLSC_TRT_LOCK;
+              }
+            } else {
+              r_llsc_fsm = SC_RSP_FALSE;
+            }
+          }
+          break;
+        }
+        ////////////////
+      case SC_DIR_HIT:
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+
+          // update directory (lock & dirty bits
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.is_cnt      = r_llsc_is_cnt.read();
+          entry.dirty	    = true;
+          entry.lock	    = true;
+          entry.tag	        = r_llsc_tag.read();
+          entry.d_copies    = r_llsc_d_copies.read();
+          entry.i_copies    = r_llsc_i_copies.read();
+          entry.count       = r_llsc_count.read();
+          m_cache_directory.write(set, way, entry);
+
+          // write data in cache
+          m_cache_data[way][set][word] = m_cmd_llsc_wdata_fifo.read();
+
+          // reset Atomic Table
+          m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+          
+          if(r_llsc_count.read()) {  // Shared line
+            r_llsc_fsm = SC_UPT_LOCK;
+          } else {
+            r_llsc_fsm = SC_RSP_TRUE;
+          }
+          break;
+        }
+        /////////////////////
+      case SC_UPT_LOCK: 	// Try to register the request in Update Table
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
+            bool        wok        = false;
+            size_t      index      = 0;
+            size_t      srcid      = m_cmd_llsc_srcid_fifo.read();
+            size_t      trdid      = m_cmd_llsc_trdid_fifo.read();
+            size_t      pktid      = m_cmd_llsc_pktid_fifo.read();
+            addr_t	    nline      = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t      nb_copies  = r_llsc_count.read();
+
+            wok =m_update_tab.set(true,	// it's an update transaction
+                false,                  // it's not a broadcast
+                true,                   // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " SC_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_llsc_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_llsc_fsm = SC_UPDATE;
+            else       r_llsc_fsm = SC_WAIT_UPT;
+          }
+          break;
+        }
+        ////////////////////
+      case SC_WAIT_UPT: 	// release the lock protecting UPT
+        {
+          r_llsc_fsm = SC_UPT_LOCK;
+          break;
+        }
+        //////////////////
+      case SC_UPDATE:   	// send a multi-update request to INIT_CMD fsm
+        {
+
+          if ( !r_llsc_to_init_cmd_req ) {
+            r_llsc_to_init_cmd_req      = true;
+            r_llsc_to_init_cmd_brdcast  = false;
+            r_llsc_to_init_cmd_trdid    = r_llsc_upt_index.read();
+            r_llsc_to_init_cmd_nline    = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_index    = m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_wdata    = m_cmd_llsc_wdata_fifo.read();
+            r_llsc_to_init_cmd_d_copies = r_llsc_d_copies.read();
+            
+            cmd_llsc_fifo_get         = true;
+
+            r_llsc_fsm = LLSC_IDLE; // Response will be sent after receiving
+            // all update responses
+          }
+          break;
+        }
+
+        //////////////////
+      case SC_TRT_LOCK:
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            if( !r_llsc_to_ixr_cmd_req ) { // we can transfer the data to the buffer
+              size_t way	= r_llsc_way.read();
+              size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+              for(size_t i = 0; i<m_words; i++){
+                if(i==m_x[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]) {
+                  r_llsc_to_ixr_cmd_data[i] = m_cmd_llsc_wdata_fifo.read();
+                } else {
+                  r_llsc_to_ixr_cmd_data[i] = m_cache_data[way][set][i];
+                }
+              }
+              size_t wok_index = 0;
+              bool wok = !m_transaction_tab.full(wok_index);
+              if ( wok ) { // set a new entry in TRT
+                r_llsc_trt_index = wok_index;
+                r_llsc_fsm       = SC_INVAL_LOCK;
+              } else {
+                r_llsc_fsm       = LLSC_IDLE;
+              }
+            } else {
+              r_llsc_fsm = LLSC_IDLE;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case SC_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
+            bool        wok       = false;
+            size_t      index     = 0;
+            size_t      srcid     = m_cmd_llsc_srcid_fifo.read();
+            size_t      trdid     = m_cmd_llsc_trdid_fifo.read();
+            size_t      pktid     = m_cmd_llsc_pktid_fifo.read();
+            addr_t	    nline     = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t      nb_copies = r_llsc_count.read();
+
+            wok =m_update_tab.set(false,	// it's an inval transaction
+                true,                       // it's a broadcast
+                true,                       // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " LLSC_INVAL_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_llsc_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_llsc_fsm = SC_DIR_INVAL;
+            else       r_llsc_fsm = LLSC_IDLE;
+          }
+          break;
+        }
+        //////////////////
+      case SC_DIR_INVAL:
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) &&
+              (r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) )
+          {
+            m_transaction_tab.set(r_llsc_trt_index.read(),
+                false,				// write request to XRAM
+                m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())],
+                0,
+                0,
+                0,
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " SC_DIR_INVAL transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+            // reset Atomic Table
+            m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+
+            // invalidate directory entry
+            DirectoryEntry entry;
+            entry.valid	   = false;
+            entry.dirty	   = false;
+            entry.tag	   = 0;
+            entry.is_cnt   = false;
+            entry.lock	   = false;
+            entry.d_copies = 0;
+            entry.i_copies = 0;
+            entry.count    = 0;
+            size_t set	   = m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t way	   = r_llsc_way.read();
+            m_cache_directory.write(set, way, entry);
+            r_llsc_fsm = SC_INVAL;
+          } else {
+            assert(false && "LOCK ERROR in LLSC_FSM, STATE = LLSC_DIR_INVAL");
+          }
+
+          break;
+
+        }
+        //////////////////
+      case SC_INVAL:
+        {
+          if ( !r_llsc_to_init_cmd_req ) {
+            r_llsc_to_init_cmd_req      = true;
+            r_llsc_to_init_cmd_brdcast  = true;
+            r_llsc_to_init_cmd_trdid    = r_llsc_upt_index.read();
+            r_llsc_to_init_cmd_nline    = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_index    = 0;
+            r_llsc_to_init_cmd_d_copies = 0;
+            r_llsc_to_init_cmd_wdata    = 0;
+
+            r_llsc_fsm = SC_XRAM_SEND;
+            // all update responses
+          }
+
+          break;
+        }
+        //////////////////
+      case SC_XRAM_SEND:
+        {
+          if ( !r_llsc_to_ixr_cmd_req ) {
+            r_llsc_to_ixr_cmd_req     = true;
+            r_llsc_to_ixr_cmd_write   = true;
+            r_llsc_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_ixr_cmd_trdid   = r_llsc_trt_index.read();
+            r_llsc_fsm                = LLSC_IDLE;
+            cmd_llsc_fifo_get         = true;
+          } else {
+            assert( false && "MEM_CACHE, LLSC FSM : SC_XRAM_SEND state : the request should not have been previously set");
+          }
+          break;
+
+        }
+        //////////////////
+      case SC_RSP_FALSE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 1;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_RSP_TRUE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get	    = true;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 0;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_TRT_LOCK:         // read or write miss : check the Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            size_t   index = 0;
+            bool hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]);
+            bool wok = !m_transaction_tab.full(index);
+
+            if ( hit_read || !wok || hit_write ) {  // missing line already requested or no space in TRT
+              r_llsc_fsm = LLSC_IDLE;
+            } else {
+              r_llsc_trt_index = index;
+              r_llsc_fsm       = LLSC_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case LLSC_TRT_SET:	// register the XRAM transaction in Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+            bool proc_read = !m_cmd_llsc_sc_fifo.read();
+            if(proc_read){
+              m_transaction_tab.set(r_llsc_trt_index.read(),
+                  true,
+                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
+                  m_cmd_llsc_srcid_fifo.read(),
+                  m_cmd_llsc_trdid_fifo.read(),
+                  (m_cmd_llsc_pktid_fifo.read()|0x1),
+                  true,
+                  1,
+                  word,
+                  std::vector<be_t>(m_words,0),
+                  std::vector<data_t>(m_words,0));
+            }else{
+              std::vector<be_t> be_vector;
+              std::vector<data_t> data_vector;
+              be_vector.clear();
+              data_vector.clear();
+              // reset Atomic Table
+              m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+              for ( size_t i=0; i<m_words; i++ ) 
+              {   
+                if(i == word){
+                  be_vector.push_back(0xF);
+                  data_vector.push_back(m_cmd_llsc_wdata_fifo.read());
+                } else {
+                  be_vector.push_back(0);
+                  data_vector.push_back(0);
+                }
+              }
+ 
+              m_transaction_tab.set(r_llsc_trt_index.read(),
+                  true,
+                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
+                  m_cmd_llsc_srcid_fifo.read(),
+                  m_cmd_llsc_trdid_fifo.read(),
+                  (m_cmd_llsc_pktid_fifo.read()|0x1),
+                  false,
+                  0,
+                  0,
+                  be_vector,
+                  data_vector);
+            }
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " LLSC_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_llsc_fsm = LLSC_XRAM_REQ;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_XRAM_REQ:	// request the IXR_CMD FSM to fetch the missing line
+        {
+          if ( !r_llsc_to_ixr_cmd_req ) {
+            r_llsc_to_ixr_cmd_req        = true;
+            r_llsc_to_ixr_cmd_write      = false;
+            r_llsc_to_ixr_cmd_trdid      = r_llsc_trt_index.read();
+            r_llsc_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()];
+            if( m_cmd_llsc_sc_fifo.read() ) {
+              r_llsc_fsm                 = SC_RSP_TRUE;
+            } else {
+              cmd_llsc_fifo_get          = true;
+              r_llsc_fsm                 = LLSC_IDLE;
+            }
+          }
+          break;
+        }
+    } // end switch r_llsc_fsm
+
+
+    //////////////////////////////////////////////////////////////////////////////
+    //		INIT_CMD FSM
+    //////////////////////////////////////////////////////////////////////////////
+    // The INIT_CMD fsm controls the VCI CMD initiator port, used to update
+    // or invalidate cache lines in L1 caches.
+    // It implements a round-robin priority between the two following requests:
+    // - r_write_to_init_cmd_req : update request from WRITE FSM 
+    // - r_xram_rsp_to_init_cmd_req : invalidate request from XRAM_RSP FSM 
+    // The inval request is a single cell VCI write command containing the 
+    // index of the line to be invalidated.
+    // The update request is a multi-cells VCI write command : The first cell 
+    // contains the index of the cache line to be updated. The second cell contains 
+    // the index of the first modified word in the line. The following cells
+    // contain the data.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      //////////////////////// 
+      case INIT_CMD_UPDT_IDLE:	// Invalidate requests have highest priority
+        {
+
+          if ( r_xram_rsp_to_init_cmd_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          } else if ( r_write_to_init_cmd_req.read() ) {
+            if(r_write_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+              m_cpt_update++;
+            }
+          } else if (r_llsc_to_init_cmd_req.read() ) {
+            if(r_llsc_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_SC_UPDT_SEL;
+              m_cpt_update++;
+            }
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_INVAL_IDLE:	// Update requests have highest priority
+        {
+          if ( r_write_to_init_cmd_req.read() ) {
+            if(r_write_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+              m_cpt_update++;
+            }
+          } else if (r_llsc_to_init_cmd_req.read() ) {
+            if(r_llsc_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_SC_UPDT_SEL;
+              m_cpt_update++;
+            }
+          } else if ( r_xram_rsp_to_init_cmd_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_IDLE:	// Update requests for SCs have highest priority
+        {
+          if (r_llsc_to_init_cmd_req.read() ) {
+            if(r_llsc_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_SC_UPDT_SEL;
+              m_cpt_update++;
+            }
+          } else if ( r_xram_rsp_to_init_cmd_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          } else if ( r_write_to_init_cmd_req.read() ) {
+            if(r_write_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+              m_cpt_update++;
+            }
+          }
+          break;
+        }
+
+        ////////////////////////
+      case INIT_CMD_INVAL_SEL:	// selects L1 caches
+        {
+          if(r_xram_rsp_to_init_cmd_brdcast.read()){
+            m_cpt_inval_brdcast++;
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            break;
+          }
+          if ((r_xram_rsp_to_init_cmd_d_copies.read() == 0) &&
+              (r_xram_rsp_to_init_cmd_i_copies.read() == 0)) {	// no more copies
+            r_xram_rsp_to_init_cmd_req = false;
+            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+            break;
+          }
+          m_cpt_inval_mult++;
+          copy_t copies;
+          bool inst = false;
+          if(r_xram_rsp_to_init_cmd_i_copies.read()){
+            copies = r_xram_rsp_to_init_cmd_i_copies.read();
+            inst = true;
+          } else {
+            copies = r_xram_rsp_to_init_cmd_d_copies.read();
+          }
+          copy_t mask   = 0x1;
+          for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+            if ( copies & mask ) {
+              r_init_cmd_target = i;
+              break;
+            }
+            mask = mask << 1;
+          } // end for 
+          r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+          r_init_cmd_inst = inst;
+          if(inst){
+            r_xram_rsp_to_init_cmd_i_copies = copies & ~mask;
+          } else {
+            r_xram_rsp_to_init_cmd_d_copies = copies & ~mask;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_INVAL_NLINE:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ) {
+            if ( r_xram_rsp_to_init_cmd_brdcast.read() ) {
+              r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+              r_xram_rsp_to_init_cmd_req = false;
+            }
+            else r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_CMD_UPDT_SEL:	// selects the next L1 cache
+        {
+          if (r_write_to_init_cmd_d_copies.read() == 0) {	// no more copies
+            r_write_to_init_cmd_req = false;
+            r_init_cmd_fsm    = INIT_CMD_UPDT_IDLE;
+          } else {						// select the first target
+            copy_t copies;
+            copies = r_write_to_init_cmd_d_copies.read();
+            copy_t mask   = 0x1;
+            for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+              if ( copies & mask ) {
+                r_init_cmd_target = i;
+                break;
+              }
+              mask = mask << 1;
+            } // end for 
+            r_init_cmd_fsm    = INIT_CMD_UPDT_NLINE;
+            r_write_to_init_cmd_d_copies = copies & ~mask;
+            r_init_cmd_cpt    = 0;
+            m_cpt_update_mult++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_BRDCAST:
+        {
+          if( p_vci_ini.cmdack ) {
+            r_write_to_init_cmd_req = false;
+            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_NLINE:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ){
+            r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_INDEX:	// send the first word index
+        {
+
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) ) {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+            } else {
+              r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_CMD_SC_UPDT_SEL:	// selects the next L1 cache
+        {
+          if (r_llsc_to_init_cmd_d_copies.read() == 0) {	// no more copies
+            r_llsc_to_init_cmd_req = false;
+            r_init_cmd_fsm    = INIT_CMD_SC_UPDT_IDLE;
+          } else {						// select the first target
+            copy_t copies;
+            copies = r_llsc_to_init_cmd_d_copies.read();
+            copy_t mask   = 0x1;
+            for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+              if ( copies & mask ) {
+                r_init_cmd_target = i;
+                break;
+              }
+              mask = mask << 1;
+            } // end for 
+            r_init_cmd_fsm    = INIT_CMD_SC_UPDT_NLINE;
+            r_llsc_to_init_cmd_d_copies = copies & ~mask;
+            r_init_cmd_cpt    = 0;
+            m_cpt_update_mult++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_BRDCAST:
+        {
+          if( p_vci_ini.cmdack ) {
+            r_llsc_to_init_cmd_req = false;
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_NLINE:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ){
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_INDEX;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_INDEX:	// send the first word index
+        {
+
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_SC_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_SEL;
+          }
+          break;
+        }
+
+    } // end switch r_init_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_RSP FSM
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_RSP fsm sends the responses on the VCI target port
+    // with a round robin priority between six requests :
+    // - r_read_to_tgt_rsp_req
+    // - r_write_to_tgt_rsp_req
+    // - r_llsc_to_tgt_rsp_req
+    // - r_cleanup_to_tgt_rsp_req
+    // - r_init_rsp_to_tgt_rsp_req
+    // - r_xram_rsp_to_tgt_rsp_req
+    // The  ordering is :  read > write > llsc > cleanup > xram > init
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      ///////////////////////
+      case TGT_RSP_READ_IDLE:		// write requests have the highest priority
+        {
+          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          break;
+        }
+        ////////////////////////
+      case TGT_RSP_WRITE_IDLE:		// llsc requests have the highest priority
+        {
+          if      ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_LLSC_IDLE:		// cleanup requests have the highest priority
+        {
+          if ( r_xram_rsp_to_tgt_rsp_req )  {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          break;
+        }
+      case TGT_RSP_XRAM_IDLE:		// init requests have the highest priority
+        {
+
+          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req )  {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_INIT_IDLE:		// cleanup requests have the highest priority
+        {
+          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_CLEANUP_IDLE:		// read requests have the highest priority
+        {
+          if      ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ:		// send the response
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) ) {
+              r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
+              r_read_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_WRITE:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
+            r_write_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_CLEANUP:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
+            r_cleanup_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        //////////////////
+      case TGT_RSP_LLSC:		// send one atomic word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_LLSC_IDLE;
+            r_llsc_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+
+        ///////////////////////
+      case TGT_RSP_XRAM:		// send the response
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1)) {
+              r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
+              r_xram_rsp_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_INIT:		// send the pending write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
+            r_init_rsp_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+    } // end switch tgt_rsp_fsm
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		NEW ALLOC_UPT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
+    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP 
+    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
+    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
+    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
+    // - The CLEANUP  FSM decrement an entry in UPT.
+    // The resource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_upt_fsm.read() ) {
+
+      ////////////////////////
+      case ALLOC_UPT_INIT_RSP:
+        if ( (r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK) && 
+             (r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR) ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_UPT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_UPT_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+        }
+        break;
+
+        ////////////////////////
+      case ALLOC_UPT_XRAM_RSP:
+        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK) 
+        { 
+          if       (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)       r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+        }
+        break;
+
+        //////////////////////////
+      case ALLOC_UPT_CLEANUP:
+        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
+        {
+          if      ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+        }
+        break;
+        
+        //////////////////////////
+      case ALLOC_UPT_LLSC:
+        if( (r_llsc_fsm.read() != SC_UPT_LOCK) && 
+            (r_llsc_fsm.read() != SC_INVAL_LOCK))
+        {
+          if      (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+        }
+        break;
+
+    } // end switch r_alloc_upt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_DIR FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_DIR FSM allocates the access to the directory and
+    // the data cache with a round robin priority between 5 user FSMs :
+    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
+    // The ressource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_dir_fsm.read() ) {
+
+      ////////////////////
+      case ALLOC_DIR_READ:
+        if ( ( (r_read_fsm.read() != READ_DIR_LOCK) &&
+              (r_read_fsm.read() != READ_TRT_LOCK)     )
+            ||
+            ( (r_read_fsm.read()      == READ_TRT_LOCK)  &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)    )  ) 
+        {
+          if        (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_DIR_WRITE:
+        if ( ( (r_write_fsm.read() != WRITE_DIR_LOCK)     &&
+              (r_write_fsm.read() != WRITE_TRT_LOCK)     &&
+              (r_write_fsm.read() != WRITE_DIR_HIT_READ) &&
+              (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+              (r_write_fsm.read() != WRITE_INVAL_LOCK) )
+            ||
+            ( (r_write_fsm.read()     == WRITE_TRT_LOCK) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
+        {
+          if        ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+        }
+        break;
+
+        ////////////////////
+      case ALLOC_DIR_LLSC:
+        if ( ( (r_llsc_fsm.read() != LL_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != LL_DIR_HIT )    &&
+              (r_llsc_fsm.read() != SC_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != SC_DIR_HIT )    &&
+              (r_llsc_fsm.read() != LLSC_TRT_LOCK ) &&
+              (r_llsc_fsm.read() != SC_TRT_LOCK)    &&
+              (r_llsc_fsm.read() != SC_INVAL_LOCK))
+            || 
+            ( (r_llsc_fsm.read()      == LLSC_TRT_LOCK ) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC)    ) )
+        {
+          if      (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)  r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+        }
+        break;
+
+        ///////////////////////
+      case ALLOC_DIR_CLEANUP:
+        if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
+            (r_cleanup_fsm.read() != CLEANUP_DIR_WRITE) )
+        {
+          if        (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if   (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_DIR_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)   && 
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
+        {
+          if      (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if ( (r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))         r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+        }
+        break;
+
+    } // end switch alloc_dir_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_TRT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
+    // with a round robin priority between 4 user FSMs :
+    // The cyclic priority is READ > WRITE > LLSC > XRAM_RSP
+    // The ressource is always allocated.
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    switch (r_alloc_trt_fsm) {
+
+      ////////////////////
+      case ALLOC_TRT_READ:
+        if ( r_read_fsm.read() != READ_TRT_LOCK ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ) )    r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+        }
+        break;
+        /////////////////////
+      case ALLOC_TRT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_TRT_LOCK) &&
+             (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+        }
+        break;
+        ////////////////////
+      case ALLOC_TRT_LLSC:
+        if ( (r_llsc_fsm.read() != LLSC_TRT_LOCK) &&
+             (r_llsc_fsm.read() != SC_TRT_LOCK) &&
+             (r_llsc_fsm.read() != SC_INVAL_LOCK))
+        { 
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)     ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT)   &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)) {
+          if      ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)    ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_IXR_RSP:
+        if ( (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
+            (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ) ) {
+          if      (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+        }
+        break;
+
+    } // end switch alloc_trt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to READ FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_read_fifo_put ) {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
+        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+      } else {
+        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
+        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+      }
+    } else {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.simple_get();
+        m_cmd_read_length_fifo.simple_get();
+        m_cmd_read_srcid_fifo.simple_get();
+        m_cmd_read_trdid_fifo.simple_get();
+        m_cmd_read_pktid_fifo.simple_get();
+      }
+    }
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to WRITE FIFO
+    /////////////////////////////////////////////////////////////////////
+
+    if ( cmd_write_fifo_put ) {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
+      } else {
+        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
+      }
+    } else {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.simple_get();
+        m_cmd_write_eop_fifo.simple_get();
+        m_cmd_write_srcid_fifo.simple_get();
+        m_cmd_write_trdid_fifo.simple_get();
+        m_cmd_write_pktid_fifo.simple_get();
+        m_cmd_write_data_fifo.simple_get();
+        m_cmd_write_be_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to LLSC FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_llsc_fifo_put ) {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_sc_fifo.put_and_get(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
+      } else {
+        m_cmd_llsc_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_sc_fifo.simple_put(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
+      }
+    } else {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.simple_get();
+        m_cmd_llsc_sc_fifo.simple_get();
+        m_cmd_llsc_srcid_fifo.simple_get();
+        m_cmd_llsc_trdid_fifo.simple_get();
+        m_cmd_llsc_pktid_fifo.simple_get();
+        m_cmd_llsc_wdata_fifo.simple_get();
+      }
+    }
+
+  //////////////////////////////////////////////////////////////
+    m_cpt_cycles++;
+
+  } // end transition()
+
+  /////////////////////////////
+  tmpl(void)::genMoore()
+    /////////////////////////////
+  {
+    ////////////////////////////////////////////////////////////
+    // Command signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////////////
+
+
+    p_vci_ixr.be      = 0xF;
+    p_vci_ixr.pktid   = 0;
+    p_vci_ixr.srcid   = m_srcid_ixr;
+    p_vci_ixr.cons    = false;
+    p_vci_ixr.wrap    = false;
+    p_vci_ixr.contig  = true;
+    p_vci_ixr.clen    = 0;
+    p_vci_ixr.cfixed  = false;
+
+    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_LLSC_NLINE ) {
+      if(r_llsc_to_ixr_cmd_write.read()){
+        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)((r_llsc_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = r_llsc_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+      } else {
+        p_vci_ixr.cmd     = vci_param::CMD_READ;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)(r_llsc_to_ixr_cmd_nline.read()*m_words*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = 0x00000000;
+        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = true;
+      }
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
+      if(r_write_to_ixr_cmd_write.read()){
+        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+      } else {
+        p_vci_ixr.cmd     = vci_param::CMD_READ;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = 0x00000000;
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = true;
+      }
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
+      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+    } else {
+      p_vci_ixr.cmdval  = false;
+      p_vci_ixr.address = 0;
+      p_vci_ixr.plen    = 0;
+      p_vci_ixr.wdata   = 0;
+      p_vci_ixr.trdid   = 0;
+      p_vci_ixr.eop	= false;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////
+
+    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
+          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) || 
+        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
+    else                                        p_vci_ixr.rspack = false;
+
+    ////////////////////////////////////////////////////
+    // Command signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+
+    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
+      case TGT_CMD_IDLE:
+        p_vci_tgt.cmdack  = false;
+        break;
+      case TGT_CMD_READ:
+        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
+        break;
+      case TGT_CMD_READ_EOP:
+        p_vci_tgt.cmdack  = true;
+        break;
+      case TGT_CMD_WRITE:
+        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
+        break;
+      case TGT_CMD_ATOMIC:
+        p_vci_tgt.cmdack  = m_cmd_llsc_addr_fifo.wok();
+        break;
+      default:
+        p_vci_tgt.cmdack = false;
+        break;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      case TGT_RSP_READ_IDLE:
+      case TGT_RSP_WRITE_IDLE:
+      case TGT_RSP_LLSC_IDLE:
+      case TGT_RSP_XRAM_IDLE:
+      case TGT_RSP_INIT_IDLE:
+      case TGT_RSP_CLEANUP_IDLE:
+        p_vci_tgt.rspval  = false;
+        p_vci_tgt.rsrcid  = 0;
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rpktid  = 0;
+        p_vci_tgt.rtrdid  = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = false;	
+        break;
+      case TGT_RSP_READ:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
+        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
+        break;
+      case TGT_RSP_WRITE:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_CLEANUP:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_LLSC:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = r_llsc_to_tgt_rsp_data.read();
+        p_vci_tgt.rsrcid   = r_llsc_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_llsc_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_llsc_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_XRAM:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
+        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1));
+        break;
+      case TGT_RSP_INIT:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        p_vci_tgt.rsrcid   = r_init_rsp_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_init_rsp_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_init_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;	
+        break;
+    } // end switch r_tgt_rsp_fsm
+
+    ///////////////////////////////////////////////////
+    // Command signals on the p_vci_ini port
+    ///////////////////////////////////////////////////
+
+    p_vci_ini.cmd     = vci_param::CMD_WRITE;
+    p_vci_ini.srcid   = m_srcid_ini;
+    p_vci_ini.pktid   = 0;
+    p_vci_ini.cons    = true;
+    p_vci_ini.wrap    = false;
+    p_vci_ini.contig  = false;
+    p_vci_ini.clen    = 0;
+    p_vci_ini.cfixed  = false;
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      case INIT_CMD_UPDT_IDLE:
+      case INIT_CMD_INVAL_IDLE:
+      case INIT_CMD_SC_UPDT_IDLE:
+      case INIT_CMD_UPDT_SEL:
+      case INIT_CMD_INVAL_SEL:
+      case INIT_CMD_SC_UPDT_SEL:
+        p_vci_ini.cmdval  = false;
+        p_vci_ini.address = 0;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0;
+        p_vci_ini.plen    = 0;
+        p_vci_ini.trdid   = 0;
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_INVAL_NLINE:
+        p_vci_ini.cmdval  = true;
+        if(r_xram_rsp_to_init_cmd_brdcast.read())
+          p_vci_ini.address = BROADCAST_ADDR;
+        else {
+          if(r_init_cmd_inst.read()) {
+            p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()]+8);
+          } else {
+            p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()]);
+          }
+        }
+        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4;
+        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+      case INIT_CMD_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4 ;
+        p_vci_ini.eop     = true;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_NLINE:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.eop     = false;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
+          r_write_to_init_cmd_index.read()].read();
+        if(r_write_to_init_cmd_we[r_init_cmd_cpt.read() +
+            r_write_to_init_cmd_index.read()].read())  
+          p_vci_ini.be      = 0xF;
+        else			p_vci_ini.be      = 0x0;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
+        break;
+
+      case INIT_CMD_SC_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (addr_t)r_llsc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4 ;
+        p_vci_ini.eop     = true;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_SC_UPDT_NLINE:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = (uint32_t)r_llsc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        p_vci_ini.plen    = 4 * 3;
+        p_vci_ini.eop     = false;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_SC_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = r_llsc_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * 3;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_SC_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = r_llsc_to_init_cmd_wdata.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * 3;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+
+    } // end switch r_init_cmd_fsm
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_ini port
+    //////////////////////////////////////////////////////
+
+    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
+    else                                          p_vci_ini.rspack  = false;
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt_cleanup port
+    //////////////////////////////////////////////////////
+    p_vci_tgt_cleanup.rspval = false;
+    p_vci_tgt_cleanup.rsrcid = 0;
+    p_vci_tgt_cleanup.rdata  = 0;
+    p_vci_tgt_cleanup.rpktid = 0;
+    p_vci_tgt_cleanup.rtrdid = 0;
+    p_vci_tgt_cleanup.rerror = 0;
+    p_vci_tgt_cleanup.reop   = false;
+    p_vci_tgt_cleanup.cmdack = false ;
+
+    switch(r_cleanup_fsm.read()){
+      case CLEANUP_IDLE:
+        {
+          p_vci_tgt_cleanup.cmdack = true ;
+          break;
+        }
+      case CLEANUP_RSP:
+        {
+          p_vci_tgt_cleanup.rspval = true;
+          p_vci_tgt_cleanup.rdata  = 0;
+          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
+          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
+          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
+          p_vci_tgt_cleanup.rerror = 0;
+          p_vci_tgt_cleanup.reop   = 1;
+          break;
+        }
+
+    }
+
+  } // end genMoore()
+
+}} // end name space
+
+// 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
+
