Index: trunk/modules/vci_mem_cache_v4/caba/source/include/update_tab_v4.h
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/include/update_tab_v4.h	(revision 183)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/update_tab_v4.h	(revision 184)
@@ -47,13 +47,13 @@
       size_t i_count) 
   {
-    valid		= i_valid;
-    update	    = i_update;
+    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;
+    srcid	= i_srcid;
+    trdid	= i_trdid;
+    pktid	= i_pktid;
+    nline	= i_nline;
+    count	= i_count;
   }
 
@@ -156,5 +156,5 @@
 
   ////////////////////////////////////////////////////////////////////
-  // The size() function returns the size of the tab  
+  // The print() function diplays the tab content 
   ////////////////////////////////////////////////////////////////////
   void print(){
@@ -262,4 +262,17 @@
 
   /////////////////////////////////////////////////////////////////////
+  // The is_not_empty() function returns true if the table is not empty
+  /////////////////////////////////////////////////////////////////////
+  bool is_not_empty()
+  {
+    for(size_t i = 0 ; i < size_tab ; i++){
+      if(tab[i].valid){
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
   // The need_rsp() function returns the need of a response
   // Arguments :
Index: trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h	(revision 183)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h	(revision 184)
@@ -80,5 +80,4 @@
         TGT_CMD_IDLE,
         TGT_CMD_READ,
-        TGT_CMD_READ_EOP,
         TGT_CMD_WRITE,
         TGT_CMD_ATOMIC,
@@ -89,5 +88,5 @@
         TGT_RSP_READ_IDLE,
         TGT_RSP_WRITE_IDLE,
-        TGT_RSP_LLSC_IDLE,
+        TGT_RSP_SC_IDLE,
         TGT_RSP_XRAM_IDLE,
         TGT_RSP_INIT_IDLE,
@@ -95,5 +94,5 @@
         TGT_RSP_READ,
         TGT_RSP_WRITE,
-        TGT_RSP_LLSC,
+        TGT_RSP_SC,
         TGT_RSP_XRAM,
         TGT_RSP_INIT,
@@ -139,5 +138,5 @@
         READ_TRT_LOCK,
         READ_TRT_SET,
-        READ_XRAM_REQ,
+        READ_TRT_REQ,
       };
 
@@ -197,15 +196,15 @@
         IXR_CMD_READ_IDLE,
         IXR_CMD_WRITE_IDLE,
-        IXR_CMD_LLSC_IDLE,
+        IXR_CMD_SC_IDLE,
         IXR_CMD_XRAM_IDLE,
         IXR_CMD_READ_NLINE,
         IXR_CMD_WRITE_NLINE,
-        IXR_CMD_LLSC_NLINE,
+        IXR_CMD_SC_NLINE,
         IXR_CMD_XRAM_DATA,
       };
 
-      /* States of the LLSC fsm */
-      enum llsc_fsm_state_e{
-        LLSC_IDLE,
+      /* States of the SC fsm */
+      enum sc_fsm_state_e{
+        SC_IDLE,
         SC_DIR_LOCK,
         SC_DIR_HIT_READ,
@@ -215,15 +214,15 @@
         SC_HEAP_LOCK,
         SC_UPT_REQ,
-        SC_UPDATE,
-        SC_TRT_LOCK,
+        SC_UPT_NEXT,
+        SC_TRT_PUT_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,
+        SC_TRT_PUT_REQ,
+        SC_RSP_FAIL,
+        SC_RSP_SUCCESS,
+        SC_TRT_GET_LOCK,
+        SC_TRT_GET_SET,
+        SC_TRT_GET_REQ,
       };
 
@@ -247,5 +246,5 @@
         ALLOC_DIR_READ,
         ALLOC_DIR_WRITE,
-        ALLOC_DIR_LLSC,
+        ALLOC_DIR_SC,
         ALLOC_DIR_CLEANUP,
         ALLOC_DIR_XRAM_RSP,
@@ -256,5 +255,5 @@
         ALLOC_TRT_READ,
         ALLOC_TRT_WRITE,
-        ALLOC_TRT_LLSC,
+        ALLOC_TRT_SC,
         ALLOC_TRT_XRAM_RSP,
         ALLOC_TRT_IXR_RSP,
@@ -267,5 +266,5 @@
         ALLOC_UPT_INIT_RSP,
         ALLOC_UPT_CLEANUP,
-        ALLOC_UPT_LLSC,
+        ALLOC_UPT_SC,
       };
 
@@ -274,9 +273,28 @@
         ALLOC_HEAP_READ,
         ALLOC_HEAP_WRITE,
-        ALLOC_HEAP_LLSC,
+        ALLOC_HEAP_SC,
         ALLOC_HEAP_CLEANUP,
         ALLOC_HEAP_XRAM_RSP,
       };
 
+      // debug variables (for each FSM)
+      size_t       m_debug_start_cycle;
+      bool         m_debug_ok;
+      bool         m_debug_global;
+      bool         m_debug_tgt_cmd_fsm;
+      bool         m_debug_tgt_rsp_fsm;
+      bool         m_debug_init_cmd_fsm;
+      bool         m_debug_init_rsp_fsm;
+      bool         m_debug_read_fsm;
+      bool         m_debug_write_fsm;
+      bool         m_debug_sc_fsm;
+      bool         m_debug_cleanup_fsm;
+      bool         m_debug_ixr_cmd_fsm;
+      bool         m_debug_ixr_rsp_fsm;
+      bool         m_debug_xram_rsp_fsm;
+      bool         m_debug_previous_hit;
+      size_t       m_debug_previous_count;
+
+      // instrumentation counters
       uint32_t	   m_cpt_cycles;            // Counter of cycles 
       uint32_t	   m_cpt_read;              // Number of READ transactions
@@ -297,4 +315,6 @@
       uint32_t	   m_cpt_sc;                // Number of SC transactions
 
+      size_t       m_prev_count;
+
       protected:
 
@@ -310,29 +330,28 @@
 
       VciMemCacheV4(
-          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
-          size_t heap_size=1024,                            // Size of the heap
-          size_t transaction_tab_lines=TRANSACTION_TAB_LINES,// Size of the TRT
-          size_t update_tab_lines=UPDATE_TAB_LINES          // Size of the UPT
-          );
+          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
+          size_t heap_size=1024,                              // Size of the heap
+          size_t transaction_tab_lines=TRANSACTION_TAB_LINES, // Size of the TRT
+          size_t update_tab_lines=UPDATE_TAB_LINES,           // Size of the UPT
+          size_t debug_start_cycle=0,
+          bool   debug_ok=false);
 
       ~VciMemCacheV4();
 
       void transition();
-
       void genMoore();
-
       void print_stats();
-
       void print_trace();
+      void cache_monitor(vci_addr_t addr);
 
       private:
@@ -343,18 +362,18 @@
       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
+      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)
       uint32_t                    		m_transaction_tab_lines;
-      TransactionTab      		    	m_transaction_tab;	// xram transaction table
+      TransactionTab      		    	m_transaction_tab;	    // xram transaction table
       uint32_t                    		m_update_tab_lines;
-      UpdateTab                 		m_update_tab;		// pending update & invalidate 
-      CacheDirectory			        m_cache_directory;	// data cache directory
-      HeapDirectory             		m_heap_directory;       // heap directory
-
-      data_t	        	       		***m_cache_data;	// data array[set][way][word]
+      UpdateTab                 		m_update_tab;		    // pending update & invalidate 
+      CacheDirectory			        m_cache_directory;	    // data cache directory
+      HeapDirectory             		m_heap;                 // heap for copies
+
+      data_t	        	       		***m_cache_data;	    // data array[set][way][word]
 
       // adress masks
@@ -371,4 +390,5 @@
       //////////////////////////////////////////////////
       sc_signal<size_t>   r_copies_limit; // Limit of the number of copies for one line
+      sc_signal<size_t>   xxx_count;
 
       //////////////////////////////////////////////////
@@ -392,11 +412,11 @@
       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_eop_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;
+      // Fifo between TGT_CMD fsm and SC fsm
+      GenericFifo<uint64_t>  m_cmd_sc_addr_fifo;
+      GenericFifo<bool>      m_cmd_sc_eop_fifo;
+      GenericFifo<size_t>    m_cmd_sc_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_sc_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_sc_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_sc_wdata_fifo;
 
       sc_signal<int>         r_tgt_cmd_fsm;
@@ -555,57 +575,57 @@
 
       ///////////////////////////////////////////////////////
-      // Registers controlled by LLSC fsm
+      // Registers controlled by SC fsm
       ///////////////////////////////////////////////////////
 
-      sc_signal<int>       r_llsc_fsm;          // FSM state
-      sc_signal<data_t>	   r_llsc_wdata;		// write data word
-      sc_signal<data_t>	   *r_llsc_rdata;		// read data word
-      sc_signal<uint32_t>  r_llsc_lfsr;         // lfsr for random introducing
-      sc_signal<size_t>    r_llsc_cpt;  	    // size of command
-      sc_signal<copy_t>    r_llsc_copy; 	    // Srcid of the first copy
-      sc_signal<copy_t>    r_llsc_copy_cache;   // Srcid of the first copy
-      sc_signal<bool>      r_llsc_copy_inst;	// Type of the first copy
-      sc_signal<size_t>    r_llsc_count;	    // number of copies
-      sc_signal<size_t>    r_llsc_ptr;  	    // pointer to the heap
-      sc_signal<size_t>    r_llsc_next_ptr;  	// next pointer to the heap
-      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_multi_req;    // valid request
-      sc_signal<bool>	   r_llsc_to_init_cmd_brdcast_req;  // 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<data_t>    r_llsc_to_init_cmd_wdata;        // data (one word)
-      sc_signal<bool>      r_llsc_to_init_cmd_is_long;      // it is a 64 bits SC
-      sc_signal<data_t>    r_llsc_to_init_cmd_wdata_high;   // data high (one word)
-      sc_signal<size_t>	   r_llsc_to_init_cmd_index;	    // index of the word in line
-      GenericFifo<bool>    m_llsc_to_init_cmd_inst_fifo;    // fifo for the L1 type
-      GenericFifo<size_t>  m_llsc_to_init_cmd_srcid_fifo;   // fifo for srcids
-      GenericFifo<size_t>  m_llsc_to_init_cmd_cache_id_fifo;// fifo for srcids
-
-      // Buffer between LLSC fsm and INIT_RSP fsm (Decrement UPT entry)
-      sc_signal<bool>      r_llsc_to_init_rsp_req;          // valid request
-      sc_signal<size_t>    r_llsc_to_init_rsp_upt_index;    // index in update table
+      sc_signal<int>       r_sc_fsm;                        // FSM state
+      sc_signal<data_t>	   r_sc_wdata;	                    // write data word
+      sc_signal<data_t>	   *r_sc_rdata;	                    // read data word
+      sc_signal<uint32_t>  r_sc_lfsr;                       // lfsr for random introducing
+      sc_signal<size_t>    r_sc_cpt;  	                    // size of command
+      sc_signal<copy_t>    r_sc_copy; 	                    // Srcid of the first copy
+      sc_signal<copy_t>    r_sc_copy_cache;                 // Srcid of the first copy
+      sc_signal<bool>      r_sc_copy_inst;	                // Type of the first copy
+      sc_signal<size_t>    r_sc_count;	                    // number of copies
+      sc_signal<size_t>    r_sc_ptr;  	                    // pointer to the heap
+      sc_signal<size_t>    r_sc_next_ptr;  	                // next pointer to the heap
+      sc_signal<bool>      r_sc_is_cnt;	                    // is_cnt bit (in directory)
+      sc_signal<bool>      r_sc_dirty;	                    // dirty bit (in directory)
+      sc_signal<size_t>    r_sc_way;		                // way in directory
+      sc_signal<size_t>    r_sc_set;		                // set in directory
+      sc_signal<data_t>    r_sc_tag;		                // cache line tag (in directory)
+      sc_signal<size_t>    r_sc_trt_index;                  // Transaction Table index
+      sc_signal<size_t>    r_sc_upt_index;                  // Update Table index
+
+      // Buffer between SC fsm and INIT_CMD fsm (XRAM read)	
+      sc_signal<bool>	   r_sc_to_ixr_cmd_req;             // valid request
+      sc_signal<addr_t>	   r_sc_to_ixr_cmd_nline;           // cache line index
+      sc_signal<size_t>	   r_sc_to_ixr_cmd_trdid;           // index in Transaction Table
+      sc_signal<bool>	   r_sc_to_ixr_cmd_write;           // write request
+      sc_signal<data_t>	  *r_sc_to_ixr_cmd_data;            // cache line data
+
+
+      // Buffer between SC fsm and TGT_RSP fsm
+      sc_signal<bool>	   r_sc_to_tgt_rsp_req;             // valid request
+      sc_signal<data_t>    r_sc_to_tgt_rsp_data;            // read data word
+      sc_signal<size_t>	   r_sc_to_tgt_rsp_srcid;           // Transaction srcid
+      sc_signal<size_t>	   r_sc_to_tgt_rsp_trdid;           // Transaction trdid
+      sc_signal<size_t>	   r_sc_to_tgt_rsp_pktid;           // Transaction pktid
+
+      // Buffer between SC fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>	   r_sc_to_init_cmd_multi_req;      // valid request
+      sc_signal<bool>	   r_sc_to_init_cmd_brdcast_req;    // brdcast request
+      sc_signal<addr_t>	   r_sc_to_init_cmd_nline;	        // cache line index
+      sc_signal<size_t>	   r_sc_to_init_cmd_trdid;	        // index in Update Table
+      sc_signal<data_t>    r_sc_to_init_cmd_wdata;          // data (one word)
+      sc_signal<bool>      r_sc_to_init_cmd_is_long;        // it is a 64 bits SC
+      sc_signal<data_t>    r_sc_to_init_cmd_wdata_high;     // data high (one word)
+      sc_signal<size_t>	   r_sc_to_init_cmd_index;	        // index of the word in line
+      GenericFifo<bool>    m_sc_to_init_cmd_inst_fifo;      // fifo for the L1 type
+      GenericFifo<size_t>  m_sc_to_init_cmd_srcid_fifo;     // fifo for srcids
+      GenericFifo<size_t>  m_sc_to_init_cmd_cache_id_fifo;  // fifo for srcids
+
+      // Buffer between SC fsm and INIT_RSP fsm (Decrement UPT entry)
+      sc_signal<bool>      r_sc_to_init_rsp_req;            // valid request
+      sc_signal<size_t>    r_sc_to_init_rsp_upt_index;      // index in update table
 
       ////////////////////////////////////////////////////
Index: trunk/modules/vci_mem_cache_v4/caba/source/include/xram_transaction_v4.h
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/include/xram_transaction_v4.h	(revision 183)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/xram_transaction_v4.h	(revision 184)
@@ -14,22 +14,22 @@
 
 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;
+  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
-  bool            rerror;           // error returned by xram
+  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
+  bool                  rerror;         // error returned by xram
 
   /////////////////////////////////////////////////////////////////////
@@ -39,4 +39,5 @@
   {
     valid		= false;
+    rerror      = false;
   }
 
@@ -50,6 +51,7 @@
     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);
+    for(size_t i=0; i<n_words; i++)
+    {
+      wdata_be.push_back(0);
       wdata.push_back(0);
     }
@@ -352,5 +354,6 @@
     tab[index].read_length	    = read_length;
     tab[index].word_index	    = word_index;
-    for(size_t i=0; i<tab[index].wdata.size(); i++) {
+    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];
@@ -361,9 +364,10 @@
   // 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.
+  // The BE field in TRT is taken into account.
   // 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
+  // - error : invalid data
   /////////////////////////////////////////////////////////////////////
   void write_rsp(const size_t index,
@@ -396,4 +400,5 @@
 	    && "The selected entry is out of range in erase() Transaction Tab");
     tab[index].valid	= false;
+    tab[index].rerror   = false;
   }
 }; // end class TransactionTab
Index: trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp	(revision 183)
+++ trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp	(revision 184)
@@ -1,3 +1,3 @@
-/* -*- c++ -*-
+ /* -*- c++ -*-
  * File 	: vci_mem_cache_v4.cpp
  * Date 	: 30/10/2008
@@ -27,201 +27,200 @@
  * Maintainers: alain eric.guthmuller@polytechnique.edu
  */
+
 #include "../include/vci_mem_cache_v4.h"
 
-#define DEBUG_VCI_MEM_CACHE 0
-#define DEBUG_START_CYCLE   1013300
-#define RANDOMIZE_SC
-
-#define ASSERT_VERBOSE
-#define ASSERT_NCYCLES m_cpt_cycles
-
-#if DEBUG_VCI_MEM_CACHE
-#define TDEBUG // Transaction tab debug
-#define IDEBUG // Update tab debug
-#define DDEBUG // Directory debug
-#define LOCK_DEBUG // Lock debug
-#endif
-
-
-#include "debug.h"
-
-#if DEBUG_VCI_MEM_CACHE
-# define PRINTF(msg...) PRINTF_COND(m_cpt_cycles > DEBUG_START_CYCLE,msg)
-#else
-# define PRINTF(msg...)
-#endif
+//////   debug services   ///////////////////////////////////////////////////////
+// All debug messages are conditionned by two variables:
+// - compile time : DEBUG_MEMC_*** : defined below
+// - execution time : m_debug_***  : defined by constructor arguments
+//    m_debug_* = (m_debug_ok) and (m_cpt_cycle > m_debug_start_cycle)
+/////////////////////////////////////////////////////////////////////////////////
+
+#define DEBUG_MEMC_GLOBAL	0	// synthetic trace of all FSMs
+#define DEBUG_MEMC_READ 	1	// detailed trace of READ FSM
+#define DEBUG_MEMC_WRITE	1	// detailed trace of WRITE FSM	
+#define DEBUG_MEMC_SC 		0	// detailed trace of SC FSM	
+#define DEBUG_MEMC_IXR_CMD	1	// detailed trace of IXR_RSP FSM
+#define DEBUG_MEMC_IXR_RSP	1	// detailed trace of IXR_RSP FSM
+#define DEBUG_MEMC_XRAM_RSP	1	// detailed trace of XRAM_RSP FSM	
+#define DEBUG_MEMC_INIT_CMD	0	// detailed trace of INIT_CMD FSM	
+#define DEBUG_MEMC_INIT_RSP	0	// detailed trace of INIT_RSP FSM	
+#define DEBUG_MEMC_TGT_CMD	0	// detailed trace of TGT_CMD FSM	
+#define DEBUG_MEMC_TGT_RSP	0	// detailed trace of TGT_RSP FSM	
+#define DEBUG_MEMC_CLEANUP	0	// detailed trace of CLEANUP FSM	
+
+#define RANDOMIZE_SC		1
 
 namespace soclib { namespace caba {
 
   const char *tgt_cmd_fsm_str[] = {
-    "TGT_CMD_IDLE    ",
-    "TGT_CMD_READ    ",
-    "TGT_CMD_READ_EOP",
-    "TGT_CMD_WRITE   ",
-    "TGT_CMD_ATOMIC  ",
+    "TGT_CMD_IDLE",
+    "TGT_CMD_READ",
+    "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_READ_IDLE",
+    "TGT_RSP_WRITE_IDLE",
+    "TGT_RSP_SC_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     ",
+    "TGT_RSP_READ",
+    "TGT_RSP_WRITE",
+    "TGT_RSP_SC",
+    "TGT_RSP_XRAM",
+    "TGT_RSP_INIT",
+    "TGT_RSP_CLEANUP",
   };
   const char *init_cmd_fsm_str[] = {
-    "INIT_CMD_INVAL_IDLE       ",
-    "INIT_CMD_INVAL_NLINE      ",
-    "INIT_CMD_XRAM_BRDCAST     ",
-    "INIT_CMD_UPDT_IDLE        ",
-    "INIT_CMD_WRITE_BRDCAST    ",
-    "INIT_CMD_UPDT_NLINE       ",
-    "INIT_CMD_UPDT_INDEX       ",
-    "INIT_CMD_UPDT_DATA        ",
-    "INIT_CMD_SC_UPDT_IDLE     ",
-    "INIT_CMD_SC_BRDCAST       ",
-    "INIT_CMD_SC_UPDT_NLINE    ",
-    "INIT_CMD_SC_UPDT_INDEX    ",
-    "INIT_CMD_SC_UPDT_DATA     ",
+    "INIT_CMD_INVAL_IDLE",
+    "INIT_CMD_INVAL_NLINE",
+    "INIT_CMD_XRAM_BRDCAST",
+    "INIT_CMD_UPDT_IDLE",
+    "INIT_CMD_WRITE_BRDCAST",
+    "INIT_CMD_UPDT_NLINE",
+    "INIT_CMD_UPDT_INDEX",
+    "INIT_CMD_UPDT_DATA",
+    "INIT_CMD_SC_UPDT_IDLE",
+    "INIT_CMD_SC_BRDCAST",
+    "INIT_CMD_SC_UPDT_NLINE",
+    "INIT_CMD_SC_UPDT_INDEX",
+    "INIT_CMD_SC_UPDT_DATA",
     "INIT_CMD_SC_UPDT_DATA_HIGH",
   };
   const char *init_rsp_fsm_str[] = {
-    "INIT_RSP_IDLE     ",
-    "INIT_RSP_UPT_LOCK ",
+    "INIT_RSP_IDLE",
+    "INIT_RSP_UPT_LOCK",
     "INIT_RSP_UPT_CLEAR",
-    "INIT_RSP_END      ",
+    "INIT_RSP_END",
   };
   const char *read_fsm_str[] = {
-    "READ_IDLE      ",
-    "READ_DIR_LOCK  ",
-    "READ_DIR_HIT   ",
-    "READ_HEAP_LOCK ",
+    "READ_IDLE",
+    "READ_DIR_LOCK",
+    "READ_DIR_HIT",
+    "READ_HEAP_LOCK",
     "READ_HEAP_WRITE",
     "READ_HEAP_ERASE",
-    "READ_HEAP_LAST ",
-    "READ_RSP       ",
-    "READ_TRT_LOCK  ",
-    "READ_TRT_SET   ",
-    "READ_XRAM_REQ  ",
+    "READ_HEAP_LAST",
+    "READ_RSP",
+    "READ_TRT_LOCK",
+    "READ_TRT_SET",
+    "READ_TRT_REQ",
   };
   const char *write_fsm_str[] = {
-    "WRITE_IDLE          ",
-    "WRITE_NEXT          ",
-    "WRITE_DIR_LOCK      ",
-    "WRITE_DIR_HIT_READ  ",
-    "WRITE_DIR_HIT       ",
-    "WRITE_UPT_LOCK      ",
-    "WRITE_HEAP_LOCK     ",
-    "WRITE_UPT_REQ       ",
-    "WRITE_UPDATE        ",
-    "WRITE_UPT_DEC       ",
-    "WRITE_RSP           ",
-    "WRITE_TRT_LOCK      ",
-    "WRITE_TRT_DATA      ",
-    "WRITE_TRT_SET       ",
-    "WRITE_WAIT          ",
-    "WRITE_XRAM_REQ      ",
+    "WRITE_IDLE",
+    "WRITE_NEXT",
+    "WRITE_DIR_LOCK",
+    "WRITE_DIR_HIT_READ",
+    "WRITE_DIR_HIT",
+    "WRITE_UPT_LOCK",
+    "WRITE_HEAP_LOCK",
+    "WRITE_UPT_REQ",
+    "WRITE_UPDATE",
+    "WRITE_UPT_DEC",
+    "WRITE_RSP",
+    "WRITE_TRT_LOCK",
+    "WRITE_TRT_DATA",
+    "WRITE_TRT_SET",
+    "WRITE_WAIT",
+    "WRITE_XRAM_REQ",
     "WRITE_TRT_WRITE_LOCK",
-    "WRITE_INVAL_LOCK    ",
-    "WRITE_DIR_INVAL     ",
-    "WRITE_INVAL         ",
-    "WRITE_XRAM_SEND     ",
+    "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_IDLE",
+    "IXR_RSP_ACK",
     "IXR_RSP_TRT_ERASE",
-    "IXR_RSP_TRT_READ ",
+    "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_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",
-    "XRAM_RSP_HEAP_ERASE ",
-    "XRAM_RSP_HEAP_LAST  ",
+    "XRAM_RSP_HEAP_ERASE",
+    "XRAM_RSP_HEAP_LAST",
     "XRAM_RSP_ERROR_ERASE",
-    "XRAM_RSP_ERROR_RSP  ",
+    "XRAM_RSP_ERROR_RSP",
   };
   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   ",
+    "IXR_CMD_READ_IDLE",
+    "IXR_CMD_WRITE_IDLE",
+    "IXR_CMD_SC_IDLE",
+    "IXR_CMD_XRAM_IDLE",
+    "IXR_CMD_READ_NLINE",
+    "IXR_CMD_WRITE_NLINE",
+    "IXR_CMD_SC_NLINE",
+    "IXR_CMD_XRAM_DATA",
   };
-  const char *llsc_fsm_str[] = {
-    "LLSC_IDLE       ",
-    "SC_DIR_LOCK     ",
-    "SC_DIR_HIT_READ ",
+  const char *sc_fsm_str[] = {
+    "SC_IDLE",
+    "SC_DIR_LOCK",
+    "SC_DIR_HIT_READ",
     "SC_DIR_HIT_WRITE",
-    "SC_UPT_LOCK     ",
-    "SC_WAIT         ",
-    "SC_HEAP_LOCK    ",
-    "SC_UPT_REQ      ",
-    "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   ",
+    "SC_UPT_LOCK",
+    "SC_WAIT",
+    "SC_HEAP_LOCK",
+    "SC_UPT_REQ",
+    "SC_UPT_NEXT",
+    "SC_TRT_PUT_LOCK",
+    "SC_INVAL_LOCK",
+    "SC_DIR_INVAL",
+    "SC_INVAL",
+    "SC_TRT_PUT_REQ",
+    "SC_RSP_FAIL",
+    "SC_RSP_SUCCESS",
+    "SC_TRT_GET_LOCK",
+    "SC_TRT_GET_SET",
+    "SC_TRT_GET_REQ",
   };
   const char *cleanup_fsm_str[] = {
-    "CLEANUP_IDLE       ",
-    "CLEANUP_DIR_LOCK   ",
-    "CLEANUP_DIR_WRITE  ",
-    "CLEANUP_HEAP_LOCK  ",
+    "CLEANUP_IDLE",
+    "CLEANUP_DIR_LOCK",
+    "CLEANUP_DIR_WRITE",
+    "CLEANUP_HEAP_LOCK",
     "CLEANUP_HEAP_SEARCH",
-    "CLEANUP_HEAP_CLEAN ",
-    "CLEANUP_HEAP_FREE  ",
-    "CLEANUP_UPT_LOCK   ",
-    "CLEANUP_UPT_WRITE  ",
-    "CLEANUP_WRITE_RSP  ",
-    "CLEANUP_RSP        ",
+    "CLEANUP_HEAP_CLEAN",
+    "CLEANUP_HEAP_FREE",
+    "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_READ",
+    "ALLOC_DIR_WRITE",
+    "ALLOC_DIR_SC",
+    "ALLOC_DIR_CLEANUP",
     "ALLOC_DIR_XRAM_RSP",
   };
   const char *alloc_trt_fsm_str[] = {
-    "ALLOC_TRT_READ    ",
-    "ALLOC_TRT_WRITE   ",
-    "ALLOC_TRT_LLSC    ",
+    "ALLOC_TRT_READ",
+    "ALLOC_TRT_WRITE",
+    "ALLOC_TRT_SC",
     "ALLOC_TRT_XRAM_RSP",
-    "ALLOC_TRT_IXR_RSP ",
+    "ALLOC_TRT_IXR_RSP",
   };
   const char *alloc_upt_fsm_str[] = {
-    "ALLOC_UPT_WRITE   ",
+    "ALLOC_UPT_WRITE",
     "ALLOC_UPT_XRAM_RSP",
     "ALLOC_UPT_INIT_RSP",
-    "ALLOC_UPT_CLEANUP ",
+    "ALLOC_UPT_CLEANUP",
   };
   const char *alloc_heap_fsm_str[] = {
-    "ALLOC_HEAP_READ    ",
-    "ALLOC_HEAP_WRITE   ",
-    "ALLOC_HEAP_LLSC    ",
-    "ALLOC_HEAP_CLEANUP ",
+    "ALLOC_HEAP_READ",
+    "ALLOC_HEAP_WRITE",
+    "ALLOC_HEAP_SC",
+    "ALLOC_HEAP_CLEANUP",
     "ALLOC_HEAP_XRAM_RSP",
   };
@@ -244,12 +243,17 @@
       const soclib::common::IntTab &vci_tgt_index,
       const soclib::common::IntTab &vci_tgt_index_cleanup,
-      size_t nways,
-      size_t nsets,
-      size_t nwords,
-      size_t heap_size,
-      size_t transaction_tab_lines,
-      size_t update_tab_lines)
+      size_t nways,                                         // number of ways per set
+      size_t nsets,                                         // number of cache sets
+      size_t nwords,                                        // number of words in cache line
+      size_t heap_size,                                     // number of heap entries
+      size_t transaction_tab_lines,                         // number of TRT entries
+      size_t update_tab_lines,                              // number of UPT entries
+      size_t debug_start_cycle,
+      bool   debug_ok)
 
     : soclib::caba::BaseModule(name),
+
+    m_debug_start_cycle( debug_start_cycle),
+    m_debug_ok ( debug_ok ),
 
     p_clk("clk"),
@@ -275,5 +279,6 @@
     m_update_tab( update_tab_lines ),
     m_cache_directory( nways, nsets, nwords, vci_param::N ),
-    m_heap_directory( m_heap_size ),
+    m_heap( m_heap_size ),
+
 #define L2 soclib::common::uint32_log2
     m_x( L2(m_words), 2),
@@ -298,10 +303,10 @@
     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_eop_fifo("m_cmd_llsc_eop_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),
+    m_cmd_sc_addr_fifo("m_cmd_sc_addr_fifo",4),
+    m_cmd_sc_eop_fifo("m_cmd_sc_eop_fifo",4),
+    m_cmd_sc_srcid_fifo("m_cmd_sc_srcid_fifo",4),
+    m_cmd_sc_trdid_fifo("m_cmd_sc_trdid_fifo",4),
+    m_cmd_sc_pktid_fifo("m_cmd_sc_pktid_fifo",4),
+    m_cmd_sc_wdata_fifo("m_cmd_sc_wdata_fifo",4),
 
     r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
@@ -319,9 +324,9 @@
     r_init_rsp_fsm("r_init_rsp_fsm"),
     r_cleanup_fsm("r_cleanup_fsm"),
-    r_llsc_fsm("r_llsc_fsm"),
-    m_llsc_to_init_cmd_inst_fifo("m_llsc_to_init_cmd_inst_fifo",8),
-    m_llsc_to_init_cmd_srcid_fifo("m_llsc_to_init_cmd_srcid_fifo",8),
+    r_sc_fsm("r_sc_fsm"),
+    m_sc_to_init_cmd_inst_fifo("m_sc_to_init_cmd_inst_fifo",8),
+    m_sc_to_init_cmd_srcid_fifo("m_sc_to_init_cmd_srcid_fifo",8),
 #if L1_MULTI_CACHE
-    m_llsc_to_init_cmd_cache_id_fifo("m_llsc_to_init_cmd_cache_id_fifo",8),
+    m_sc_to_init_cmd_cache_id_fifo("m_sc_to_init_cmd_cache_id_fifo",8),
 #endif
     r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
@@ -346,4 +351,8 @@
       assert(nways);
 
+      // check Transaction table size
+      assert( (uint32_log2(transaction_tab_lines) <= vci_param::T) and
+             "Need more bits for VCI TRDID field");
+
       // Set the broadcast address with Xmin,Xmax,Ymin,Ymax set to maximum
       m_broadcast_address = 0x3 | (0x7C1F << (vci_param::N-20));
@@ -405,7 +414,7 @@
       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];
-      r_llsc_rdata                  = new sc_signal<data_t>[2];
+      // Allocation for SC FSM
+      r_sc_to_ixr_cmd_data	        = new sc_signal<data_t>[nwords];
+      r_sc_rdata                    = new sc_signal<data_t>[2];
 
 
@@ -422,25 +431,45 @@
     } // end constructor
 
-  //////////////////////////////////////////////////
-  // This function prints a trace of internal states
-  //////////////////////////////////////////////////
-
-  tmpl(void)::print_trace()
-  {
-    std::cout << "MEM_CACHE " << name() << std::endl;
-    std::cout << " / " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] 
-              << " / " << read_fsm_str[r_read_fsm]
-              << " / " << write_fsm_str[r_write_fsm]
-              << " / " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] 
-              << " / " << init_cmd_fsm_str[r_init_cmd_fsm]
-              << " / " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl;
-  }
-
-  /////////////////////////////////////////
-  // This function prints the statistics 
-  /////////////////////////////////////////
-
-  tmpl(void)::print_stats()
-  {
+/////////////////////////////////////////////////////
+tmpl(void)::cache_monitor( vci_addr_t addr )
+/////////////////////////////////////////////////////
+{
+    size_t way = 0;
+    DirectoryEntry entry = m_cache_directory.read(addr, way);
+    if ( (entry.count != m_debug_previous_count) or 
+         (entry.valid != m_debug_previous_hit) )
+    {
+    std::cout << " MEMC " << name()
+              << " cache change at cycle " << std::dec << m_cpt_cycles
+              << " for address " << std::hex << addr
+              << " / HIT = " << entry.valid
+              << " / COUNT = " << std::dec << entry.count << std::endl;
+    }
+    m_debug_previous_count = entry.count;
+    m_debug_previous_hit = entry.valid;
+}
+
+//////////////////////////////////////////////////
+tmpl(void)::print_trace()
+//////////////////////////////////////////////////
+{
+    std::cout << "MEMC " << name() << std::endl;
+    std::cout << "  "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm] 
+              << " | " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] 
+              << " | " << read_fsm_str[r_read_fsm]
+              << " | " << write_fsm_str[r_write_fsm] 
+              << " | " << sc_fsm_str[r_sc_fsm] 
+              << " | " << cleanup_fsm_str[r_cleanup_fsm] << std::endl;
+    std::cout << "  "  << init_cmd_fsm_str[r_init_cmd_fsm]
+              << " | " << init_rsp_fsm_str[r_init_rsp_fsm] 
+              << " | " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] 
+              << " | " << ixr_rsp_fsm_str[r_ixr_rsp_fsm]
+              << " | " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl;
+}
+
+/////////////////////////////////////////
+tmpl(void)::print_stats()
+/////////////////////////////////////////
+{
     std::cout << "----------------------------------" << std::dec << std::endl;
     std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
@@ -464,5 +493,5 @@
               << "- LL RATE              = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
               << "- SC RATE              = " << (double)m_cpt_sc/m_cpt_cycles << std::endl;
-  }
+}
 
   /////////////////////////////////
@@ -495,9 +524,10 @@
   }
 
-  //////////////////////////////////
-  tmpl(void)::transition()
-    //////////////////////////////////
-  {
+//////////////////////////////////
+tmpl(void)::transition()
+//////////////////////////////////
+{
     using soclib::common::uint32_log2;
+
     //  RESET          
     if ( ! p_resetn.read() ) {
@@ -508,7 +538,7 @@
       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_read_fsm 	    = READ_IDLE;
+      r_write_fsm 	    = WRITE_IDLE;
+      r_sc_fsm 	        = SC_IDLE;
       r_cleanup_fsm 	= CLEANUP_IDLE;
       r_alloc_dir_fsm   = ALLOC_DIR_READ;
@@ -519,8 +549,23 @@
       r_ixr_cmd_fsm 	= IXR_CMD_READ_IDLE;
 
+      m_debug_global         = false;
+      m_debug_tgt_cmd_fsm    = false;
+      m_debug_tgt_rsp_fsm    = false;
+      m_debug_init_cmd_fsm   = false;
+      m_debug_init_rsp_fsm   = false;
+      m_debug_read_fsm       = false;
+      m_debug_write_fsm      = false;
+      m_debug_sc_fsm         = false;
+      m_debug_cleanup_fsm    = false;
+      m_debug_ixr_cmd_fsm    = false;
+      m_debug_ixr_rsp_fsm    = false;
+      m_debug_xram_rsp_fsm   = false;
+      m_debug_previous_hit   = false;
+      m_debug_previous_count = 0;
+
       //  Initializing Tables
       m_cache_directory.init();
       m_transaction_tab.init();
-      m_heap_directory.init();
+      m_heap.init();
 
       // initializing FIFOs and communication Buffers
@@ -539,13 +584,13 @@
       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_eop_fifo.init();
-
-      r_read_to_tgt_rsp_req	    = false;
-      r_read_to_ixr_cmd_req	    = false;
+      m_cmd_sc_addr_fifo.init();
+      m_cmd_sc_srcid_fifo.init();
+      m_cmd_sc_trdid_fifo.init();
+      m_cmd_sc_pktid_fifo.init();
+      m_cmd_sc_wdata_fifo.init();
+      m_cmd_sc_eop_fifo.init();
+
+      r_read_to_tgt_rsp_req	            = false;
+      r_read_to_ixr_cmd_req	            = false;
 
       r_write_to_tgt_rsp_req	        = false;
@@ -560,18 +605,18 @@
 #endif
 
-      r_cleanup_to_tgt_rsp_req	= false;
-
-      r_init_rsp_to_tgt_rsp_req	= false;
-
-      r_llsc_to_tgt_rsp_req	            = false;
-      r_llsc_cpt                        = 0;
-      r_llsc_lfsr                       = -1;
-      r_llsc_to_ixr_cmd_req	            = false;
-      r_llsc_to_init_cmd_multi_req	    = false;
-      r_llsc_to_init_cmd_brdcast_req	= false;
-      m_llsc_to_init_cmd_inst_fifo.init();
-      m_llsc_to_init_cmd_srcid_fifo.init();
+      r_cleanup_to_tgt_rsp_req	        = false;
+
+      r_init_rsp_to_tgt_rsp_req	        = false;
+
+      r_sc_to_tgt_rsp_req	            = false;
+      r_sc_cpt                          = 0;
+      r_sc_lfsr                         = -1;
+      r_sc_to_ixr_cmd_req	            = false;
+      r_sc_to_init_cmd_multi_req	    = false;
+      r_sc_to_init_cmd_brdcast_req	    = false;
+      m_sc_to_init_cmd_inst_fifo.init();
+      m_sc_to_init_cmd_srcid_fifo.init();
 #if L1_MULTI_CACHE
-      m_llsc_to_init_cmd_cache_id_fifo.init();
+      m_sc_to_init_cmd_cache_id_fifo.init();
 #endif
 
@@ -611,6 +656,6 @@
       m_cpt_ll     		    = 0;
       m_cpt_sc     		    = 0;
-      m_cpt_trt_full      = 0;
-      m_cpt_trt_rb        = 0;
+      m_cpt_trt_full        = 0;
+      m_cpt_trt_rb          = 0;
 
       return;
@@ -623,6 +668,6 @@
     bool    cmd_write_fifo_get = false;
 
-    bool    cmd_llsc_fifo_put = false;
-    bool    cmd_llsc_fifo_get = false;
+    bool    cmd_sc_fifo_put = false;
+    bool    cmd_sc_fifo_get = false;
 
     bool    write_to_init_cmd_fifo_put      = false;
@@ -630,4 +675,5 @@
     bool    write_to_init_cmd_fifo_inst     = false;
     size_t  write_to_init_cmd_fifo_srcid    = 0;
+
 #if L1_MULTI_CACHE
     size_t  write_to_init_cmd_fifo_cache_id = 0;
@@ -638,18 +684,35 @@
     bool    xram_rsp_to_init_cmd_fifo_inst     = false;
     size_t  xram_rsp_to_init_cmd_fifo_srcid    = 0;
+
 #if L1_MULTI_CACHE
     size_t  xram_rsp_to_init_cmd_fifo_cache_id = 0;
 #endif
 
-    bool    llsc_to_init_cmd_fifo_put      = false;
-    bool    llsc_to_init_cmd_fifo_get      = false;
-    bool    llsc_to_init_cmd_fifo_inst     = false;
-    size_t  llsc_to_init_cmd_fifo_srcid    = 0;
+    bool    sc_to_init_cmd_fifo_put      = false;
+    bool    sc_to_init_cmd_fifo_get      = false;
+    bool    sc_to_init_cmd_fifo_inst     = false;
+    size_t  sc_to_init_cmd_fifo_srcid    = 0;
+
 #if L1_MULTI_CACHE
-    size_t  llsc_to_init_cmd_fifo_cache_id = 0;
-#endif
-
-#if DEBUG_VCI_MEM_CACHE 
-if(m_cpt_cycles > DEBUG_START_CYCLE){
+    size_t  sc_to_init_cmd_fifo_cache_id = 0;
+#endif
+
+m_debug_global       = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_tgt_cmd_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_tgt_rsp_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_init_cmd_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_init_rsp_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_read_fsm     = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_write_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_sc_fsm       = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_cleanup_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_ixr_cmd_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_ixr_rsp_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+m_debug_xram_rsp_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+
+
+#if DEBUG_MEMC_GLOBAL   
+if( m_debug_global ) 
+{
     std::cout << "---------------------------------------------" << std::dec << std::endl;
     std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
@@ -660,5 +723,5 @@
       << " - 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
+      << " - SC FSM         = " << sc_fsm_str[r_sc_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
@@ -672,11 +735,4 @@
 #endif
 
-#ifdef IDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_LOCK update table : " << std::endl;
-	m_update_tab.print();
-}
-#endif
-
     ////////////////////////////////////////////////////////////////////////////////////
     //		TGT_CMD FSM
@@ -684,87 +740,136 @@
     // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
     //
-    // There is 4 types of packets for the m_mem_segment :
+    // There is 3 types of accepted commands :
     // - 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.
-    //
+    // - SC      : The SC request has a length of 2 cells or 4 cells. 
     ////////////////////////////////////////////////////////////////////////////////////
 
-    switch ( r_tgt_cmd_fsm.read() ) {
-
-      //////////////////
-      case TGT_CMD_IDLE:
-        {
-          if ( p_vci_tgt.cmdval ) {
-
-              PRINTF("  * <MEM_CACHE.TGT> Request from %d.%d (%d) at address %llx\n",(uint32_t)p_vci_tgt.srcid.read(),(uint32_t)p_vci_tgt.pktid.read(),(uint32_t)p_vci_tgt.trdid.read(),(uint64_t)p_vci_tgt.address.read());
-
-            if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) 
-            {
-              r_tgt_cmd_fsm = TGT_CMD_READ;
+    switch ( r_tgt_cmd_fsm.read() ) 
+    {
+        //////////////////
+        case TGT_CMD_IDLE:
+        {
+            if ( p_vci_tgt.cmdval ) 
+            {
+
+#if DEBUG_MEMC_TGT_CMD
+if( m_debug_tgt_cmd_fsm ) 
+{
+    std::cout << "  <MEMC.TGT_CMD_IDLE> Receive command from srcid " << p_vci_tgt.srcid.read()
+              << " / for address " << p_vci_tgt.address.read() << std::endl;
+}
+#endif
+                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_STORE_COND ) 
+                {
+                    r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
+                } 
+                else 
+                {
+                    std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                              << " TGT_CMD_IDLE state" << std::endl;
+                    std::cout << " illegal VCI command type" << std::endl;
+                    exit(0);
+                }
+            }
+            break;
+        }
+        //////////////////
+        case TGT_CMD_READ:
+        {
+            if ((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2)) > 16)
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" << std::endl;
+                std::cout << " illegal address/plen combination for VCI read command" << std::endl;
+                exit(0);
+            }
+            if ( !p_vci_tgt.eop.read() )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" << std::endl;
+                std::cout << " read command packets must contain one single flit" << std::endl;
+                exit(0);
+            }
+
+            if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) 
+            {
+           
+#if DEBUG_MEMC_TGT_CMD
+if( m_debug_tgt_cmd_fsm ) 
+{
+    std::cout << "  <MEMC.TGT_CMD_READ> Push into read_fifo:" 
+              << " address = " << std::hex << p_vci_tgt.address.read()
+              << " srcid = " << p_vci_tgt.srcid.read()
+              << " trdid = " << p_vci_tgt.trdid.read()
+              << " plen = " << p_vci_tgt.plen.read() << std::endl;
+}
+#endif
+                cmd_read_fifo_put = true;
+                m_cpt_read++;
+                r_tgt_cmd_fsm = TGT_CMD_IDLE;
             } 
-            // else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ) && ( p_vci_tgt.trdid.read() == 0x0 ))
-            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_STORE_COND ) 
-            {
-              r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
-            } else {
-                std::cout << "MemCache error : wrong command " << std::endl;
+            break;
+        }
+        ///////////////////
+        case TGT_CMD_WRITE:
+        {
+            if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() ) 
+            {
+           
+#if DEBUG_MEMC_TGT_CMD
+if( m_debug_tgt_cmd_fsm ) 
+{
+    std::cout << "  <MEMC.TGT_CMD_WRITE> Push into write_fifo:" 
+              << " address = " << std::hex << p_vci_tgt.address.read()
+              << " srcid = " << p_vci_tgt.srcid.read()
+              << " trdid = " << p_vci_tgt.trdid.read()
+              << " wdata = " << p_vci_tgt.wdata.read()
+              << " be = " << p_vci_tgt.be.read()
+              << " plen = " << p_vci_tgt.plen.read() << std::endl;
+}
+#endif
+                cmd_write_fifo_put = true;
+                if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+            }
+            break;
+        }
+        ////////////////////
+        case TGT_CMD_ATOMIC:
+        {
+            if ( (p_vci_tgt.plen.read() != 8) && (p_vci_tgt.plen.read() != 16) )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_ATOMIC state" << std::endl;
+                std::cout << "illegal format for sc command " << std::endl;
                 exit(0);
             }
-          }
-          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 ) {
-                    m_cpt_read++;
-                    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 ){
-            m_cpt_read++;
-            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:
-        {
-          if ( p_vci_tgt.cmdval && m_cmd_llsc_addr_fifo.wok() ) {
-            cmd_llsc_fifo_put = true;
-            if( p_vci_tgt.eop ) r_tgt_cmd_fsm = TGT_CMD_IDLE;
-          }
-          break;
+
+            if ( p_vci_tgt.cmdval && m_cmd_sc_addr_fifo.wok() ) 
+            {
+           
+#if DEBUG_MEMC_TGT_CMD
+if( m_debug_tgt_cmd_fsm ) 
+{
+    std::cout << "  <MEMC.TGT_CMD_ATOMIC> Pushing command into cmd_sc_fifo:"
+              << " address = " << std::hex << p_vci_tgt.address.read()
+              << " srcid = " << p_vci_tgt.srcid.read()
+              << " trdid = " << p_vci_tgt.trdid.read()
+              << " wdata = " << p_vci_tgt.wdata.read()
+              << " be = " << p_vci_tgt.be.read()
+              << " plen = " << p_vci_tgt.plen.read() << std::endl;
+}
+#endif
+                cmd_sc_fifo_put = true;
+                if( p_vci_tgt.eop ) r_tgt_cmd_fsm = TGT_CMD_IDLE;
+            }
+            break;
         }
     } // end switch tgt_cmd_fsm
@@ -773,99 +878,137 @@
     //		INIT_RSP FSM
     /////////////////////////////////////////////////////////////////////////
-    // This FSM controls the response to the update or invalidate requests
-    // sent by the memory cache to the L1 caches :
+    // This FSM controls the response to the update or inval coherence
+    // 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.
+    // It can be update or inval requests initiated by the WRITE FSM,
+    // or inval requests initiated by the XRAM_RSP FSM.  
+    // The FSM decrements the proper entry in UPT.
+    // 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.  
     //
     // 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.
+    // the transaction type is defined in the UPT entry.
     /////////////////////////////////////////////////////////////////////
 
-    switch ( r_init_rsp_fsm.read() ) {
-
-      ///////////////////
-      case INIT_RSP_IDLE:
-        {
-
-          if ( p_vci_ini.rspval ) {
-            PRINTF("  * <MEM_CACHE.INIT_RSP> rsp val - trdid %d\n",(uint32_t)p_vci_ini.rtrdid.read());
-
-            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;
-          } else if( r_write_to_init_rsp_req.read() ){
-            r_init_rsp_upt_index = r_write_to_init_rsp_upt_index.read();
-            r_write_to_init_rsp_req = false;
-            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
-          }
-          break;
+    switch ( r_init_rsp_fsm.read() ) 
+    {
+        ///////////////////
+        case INIT_RSP_IDLE:   // wait a response for a coherence transaction
+        {
+            if ( p_vci_ini.rspval ) 
+            {
+
+#if DEBUG_MEMC_INIT_RSP
+if( m_debug_init_rsp_fsm ) 
+{
+    std::cout <<  "  <MEMC.INIT_RSP_IDLE> Response for UPT entry " 
+              << p_vci_ini.rtrdid.read() << std::endl;
+}
+#endif
+                if ( p_vci_ini.rtrdid.read() >= m_update_tab.size() )
+                {
+                    std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                              << " INIT_RSP_IDLE state" << std::endl;
+                    std::cout << "index too large for UPT: " 
+                              << " / rtrdid = " << p_vci_ini.rtrdid.read()
+                              << " / UPT size = " << m_update_tab.size() << std::endl;
+                    exit(0);
+                }
+                if ( !p_vci_ini.reop.read() )
+                {
+                    std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                              << " INIT_RSP_IDLE state" << std::endl;
+                    std::cout << "all coherence response packets must be one flit" << std::endl;
+                    exit(0);
+                }
+
+                r_init_rsp_upt_index = p_vci_ini.rtrdid.read(); 
+                r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
+            } 
+            else if( r_write_to_init_rsp_req.read() )
+            {
+                r_init_rsp_upt_index = r_write_to_init_rsp_upt_index.read();
+                r_write_to_init_rsp_req = false;
+                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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_LOCK update table : " << std::endl;
-	m_update_tab.print();
-}
-#endif
-            while(!valid);
-            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_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);
+
+#if DEBUG_MEMC_INIT_RSP
+if( m_debug_init_rsp_fsm ) 
+{
+    std::cout << "  <MEMC.INIT_RSP_UPT_LOCK> Decrement the responses counter for UPT:"
+              << " entry = " << r_init_rsp_upt_index.read() 
+              << " / rsp_count = " << std::dec << count << std::endl;
+}
+#endif
+                if ( not valid )
+                {
+                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " INIT_RSP_UPT_LOCK state" << std::endl;
+                    std::cout << "unsuccessful access to decrement the UPT" << std::endl;
+                    exit(0);
+                }
+
+                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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_CLEAR update table : " << std::endl;
-	m_update_tab.print();
-}
-#endif
-          }
-          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());
+
+#if DEBUG_MEMC_INIT_RSP
+if ( m_debug_init_rsp_fsm )
+{
+    std::cout <<  "  <MEMC.INIT_RSP_UPT_CLEAR> Clear UPT entry "
+              << r_init_rsp_upt_index.read() <<  std::endl;
+}
+#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;
+        case INIT_RSP_END:	// Post a request to TGT_RSP FSM
+        {
+            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;
+
+#if DEBUG_MEMC_INIT_RSP
+if ( m_debug_init_rsp_fsm )
+{
+    std::cout <<  "  <MEMC.INIT_RSP_END> Request TGT_RSP FSM to send a response to srcid "
+              << r_init_rsp_srcid.read() <<  std::endl;
+}
+#endif
+            }
+            break;
         }
     } // end switch r_init_rsp_fsm
@@ -874,355 +1017,476 @@
     //		READ FSM
     ////////////////////////////////////////////////////////////////////////////////////
-    // The READ FSM controls the read requests sent by processors.
+    // The READ FSM controls the VCI read requests.
     // 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 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 the number of copy is larger than 1, the new copy is registered
+    //   in the HEAP.
+    //   If the number of copy is larger than the threshold, the HEAP is cleared,
+    //   and the corresponding line switches to the counter mode.
+    // - 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.
+    //   If a TRT entry is free, the READ request is registered in TRT,
+    //   it is consumed in the request FIFO, and transmited to the IXR_CMD FSM.
+    //   The READ FSM returns in the IDLE state as the read transaction will be 
+    //   completed when the missing line will be received.
     ////////////////////////////////////////////////////////////////////////////////////
 
-    PRINTF("  * <MEM_CACHE.TOP> Request from %d.%d at address %llx\n",(uint32_t)m_cmd_read_srcid_fifo.read(),(uint32_t)m_cmd_read_pktid_fifo.read(),(uint64_t)m_cmd_read_addr_fifo.read());
-
-    switch ( r_read_fsm.read() ) {
-
-      ///////////////
-      case READ_IDLE:
-        {
-          if (m_cmd_read_addr_fifo.rok()) {
-            PRINTF("  * <MEM_CACHE.READ> Request from %d.%d at address %llx\n",(uint32_t)m_cmd_read_srcid_fifo.read(),(uint32_t)m_cmd_read_pktid_fifo.read(),(uint64_t)m_cmd_read_addr_fifo.read());
-
-            r_read_fsm = READ_DIR_LOCK;
-          }
-          break;
+    switch ( r_read_fsm.read() ) 
+    {
+        ///////////////
+        case READ_IDLE:		// waiting a read request
+        {
+            if (m_cmd_read_addr_fifo.rok()) 
+            {
+
+#if DEBUG_MEMC_READ
+if( m_debug_read_fsm ) 
+{
+    std::cout << "  <MEMC.READ_IDLE> Read request:"
+              << " srcid = " << std::hex << m_cmd_read_srcid_fifo.read()
+              << " / address = " << m_cmd_read_addr_fifo.read()
+              << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
+}
+#endif
+                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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	   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_lock	      = entry.lock;
-            r_read_tag	      = entry.tag;
-            r_read_way	      = way;
-            r_read_count      = entry.count;
-            r_read_copy       = entry.owner.srcid; 
+        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);
+
+                r_read_is_cnt     = entry.is_cnt;
+            	r_read_dirty      = entry.dirty;
+            	r_read_lock	      = entry.lock;
+            	r_read_tag	      = entry.tag;
+            	r_read_way	      = way;
+            	r_read_count      = entry.count;
+            	r_read_copy       = entry.owner.srcid; 
+
 #if L1_MULTI_CACHE
-            r_read_copy_cache = entry.owner.cache_id; 
-#endif
-            r_read_copy_inst  = entry.owner.inst;
-            r_read_ptr        = entry.ptr;
-
-            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
-            // In case of hit, the read acces must be registered in the copies bit-vector
-            if(  entry.valid ) {
-              if(entry.is_cnt || (entry.count == 0) || !cached_read)  { // No new entry in the heap
-                r_read_fsm = READ_DIR_HIT;
-              } else {
-                r_read_fsm = READ_HEAP_LOCK;
-              }
-            } else {
-              r_read_fsm = READ_TRT_LOCK;
-            }
-          }
-          break;
+                r_read_copy_cache = entry.owner.cache_id; 
+#endif
+                r_read_copy_inst  = entry.owner.inst;
+                r_read_ptr        = entry.ptr;              // pointer to the heap
+
+                bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
+                if(  entry.valid ) 	// hit
+                {
+                    // test if we need to register a new copy in the heap
+                    if ( entry.is_cnt || (entry.count == 0) || !cached_read ) 
+                        r_read_fsm = READ_DIR_HIT; 
+                    else
+                        r_read_fsm = READ_HEAP_LOCK;
+                }
+                else 			// miss
+                {
+                    r_read_fsm = READ_TRT_LOCK;
+                }
+
+#if DEBUG_MEMC_READ
+if( m_debug_read_fsm ) 
+{
+    std::cout << "  <MEMC.READ_DIR_LOCK> Accessing directory: "
+              << " address = " << std::hex << m_cmd_read_addr_fifo.read() 
+              << " / hit = " << entry.valid 
+              << " / count = " <<std::dec << entry.count
+              << " / is_cnt = " << entry.is_cnt << std::endl;
+}
+#endif
+            }
+            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_is_cnt.read();
-
-            // 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; 
-            entry.dirty	  = r_read_dirty.read();
-            entry.tag	  = r_read_tag.read();
-            entry.lock	  = r_read_lock.read();
-            entry.ptr     = r_read_ptr.read();
-            if(cached_read){  // Cached read, we update the copy
-              if(!is_cnt){ // Not counter mode
-                entry.owner.srcid   = m_cmd_read_srcid_fifo.read();
+        case READ_DIR_HIT:	    //  read data in cache & update the directory 
+                                //  we enter this state in 3 cases:
+                                //  - the read request is uncachable
+                                //  - the cache line is in counter mode
+                                //  - the cache line is valid but not replcated
+        {
+            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_is_cnt.read();
+
+                // 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 
+                DirectoryEntry entry;
+                entry.valid	  = true;
+                entry.is_cnt  = is_cnt; 
+                entry.dirty	  = r_read_dirty.read();
+                entry.tag	  = r_read_tag.read();
+                entry.lock	  = r_read_lock.read();
+                entry.ptr     = r_read_ptr.read();
+                if (cached_read)  // Cached read => we must update the copies
+                {
+                    if (!is_cnt) // Not counter mode
+                    {
+                        entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
 #if L1_MULTI_CACHE
-                entry.owner.cache_id= m_cmd_read_pktid_fifo.read();
-#endif
-
-                entry.owner.inst    = inst_read;
-                entry.count         = r_read_count.read() + 1;
-              } else { // Counter mode
-                entry.owner.srcid   = 0;
+                        entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
+#endif
+                        entry.owner.inst     = inst_read;
+                        entry.count          = r_read_count.read() + 1;
+                    } 
+                    else  // Counter mode
+                    {
+                        entry.owner.srcid    = 0;
 #if L1_MULTI_CACHE
-                entry.owner.cache_id= 0;
-#endif
-                entry.owner.inst    = false;
-                entry.count         = r_read_count.read() + 1;
-              } 
-            } else { // Uncached read
-              entry.owner.srcid     = r_read_copy.read();
+                        entry.owner.cache_id = 0;
+#endif
+                        entry.owner.inst     = false;
+                        entry.count          = r_read_count.read() + 1;
+                    } 
+                } 
+                else  // Uncached read
+                {
+                    entry.owner.srcid     = r_read_copy.read();
 #if L1_MULTI_CACHE
-              entry.owner.cache_id  = r_read_copy_cache.read();
-#endif
-
-              entry.owner.inst      = r_read_copy_inst.read();
-              entry.count           = r_read_count.read();
-            }
-#ifdef DDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	   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;
+                    entry.owner.cache_id  = r_read_copy_cache.read();
+#endif
+                    entry.owner.inst      = r_read_copy_inst.read();
+                    entry.count           = r_read_count.read();
+                }
+
+#if DEBUG_MEMC_READ
+if( m_debug_read_fsm )
+{
+    std::cout << "  <MEMC.READ_DIR_HIT> Update directory entry:"
+              << " set = " << std::dec << set 
+              << " / way = " << way 
+              << " / owner_id = " << entry.owner.srcid 
+              << " / owner_ins = " << entry.owner.inst
+              << " / count = " << entry.count 
+              << " / is_cnt = " << entry.is_cnt << std::endl;
+}
+#endif
+
+                m_cache_directory.write(set, way, entry);
+                r_read_fsm    = READ_RSP;
+            }
+            break;
+        }
+        ////////////////////
+        case READ_HEAP_LOCK:	// read data in cache, update the directory
+                                // and prepare the HEAP update        
+        {
+            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ ) 
+            {
+                // enter counter mode when we reach the limit of copies or the heap is full
+                bool go_cnt = (r_read_count.read() >= r_copies_limit.read()) || m_heap.is_full();
+
+                // 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
+                DirectoryEntry entry;
+                entry.valid	  = true;
+                entry.is_cnt  = go_cnt; 
+                entry.dirty	  = r_read_dirty.read();
+                entry.tag	  = r_read_tag.read();
+                entry.lock	  = r_read_lock.read();
+                entry.count   = r_read_count.read() + 1;
+
+                if (not go_cnt)        // Not entering counter mode
+                {
+                    entry.owner.srcid   = r_read_copy.read();
+#if L1_MULTI_CACHE
+                    entry.owner.cache_id= r_read_copy_cache.read();
+#endif
+                    entry.owner.inst    = r_read_copy_inst.read();
+                    entry.ptr           = m_heap.next_free_ptr();   // set pointer on the heap
+                } 
+                else                // Entering Counter mode
+                {
+                    entry.owner.srcid   = 0;
+#if L1_MULTI_CACHE
+                    entry.owner.cache_id= 0;
+#endif
+                    entry.owner.inst    = false;
+                    entry.ptr           = 0;
+                }
+
+                m_cache_directory.write(set, way, entry);
+
+                // prepare the heap update (add an entry, or clear the linked list)
+                if (not go_cnt)	    // not switching to counter mode
+                {
+                    // We test if the next free entry in the heap is the last
+                    HeapEntry heap_entry = m_heap.next_free_entry();
+                    r_read_next_ptr      = heap_entry.next;
+                    r_read_last_free     = ( heap_entry.next == m_heap.next_free_ptr() );
+
+                    r_read_fsm           = READ_HEAP_WRITE; // add an entry in the HEAP
+                } 
+                else 		        // switching to counter mode
+                {
+                    if ( r_read_count.read()>1 )            // heap must be cleared
+                    {
+                        HeapEntry next_entry = m_heap.read(r_read_ptr.read());
+                        r_read_next_ptr      = m_heap.next_free_ptr();
+                        m_heap.write_free_ptr(r_read_ptr.read());
+
+                        if( next_entry.next == r_read_ptr.read() )  // last entry 
+                        {
+                            r_read_fsm = READ_HEAP_LAST;    // erase the entry
+                        } 
+                        else                                        // not the last entry
+                        {
+                            r_read_ptr = next_entry.next;
+                            r_read_fsm = READ_HEAP_ERASE;   // erase the list 
+                        }
+                    } 
+                    else 	// the heap is not used / nothing to do
+                    {
+                        r_read_fsm = READ_RSP;
+                    }
+                }
+
+#if DEBUG_MEMC_READ
+if( m_debug_read_fsm )
+{
+    std::cout << "  <MEMC.READ_HEAP_LOCK> Update directory:"
+              << " tag = " << std::hex << entry.tag
+              << " set = " << std::dec << set 
+              << " way = " << way
+              << " count = " << entry.count
+              << " is_cnt = " << entry.is_cnt << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////////////
+        case READ_HEAP_WRITE:       // add a entry in the heap
+        {
+            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
+            {
+                HeapEntry heap_entry;
+                heap_entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
+#if L1_MULTI_CACHE
+                heap_entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
+#endif
+                heap_entry.owner.inst     = (m_cmd_read_trdid_fifo.read() & 0x2);
+
+                if(r_read_count.read() == 1)    // creation of a new linked list
+                {
+                    heap_entry.next         = m_heap.next_free_ptr(); 
+                } 
+                else                            // head insertion in existing list 
+                {
+                    heap_entry.next         = r_read_ptr.read();
+                }
+                m_heap.write_free_entry(heap_entry);
+                m_heap.write_free_ptr(r_read_next_ptr.read());
+                if(r_read_last_free.read())  m_heap.set_full(); 
+
+                r_read_fsm = READ_RSP;
+
+#if DEBUG_MEMC_READ
+if( m_debug_read_fsm )
+{
+    std::cout << "  <MEMC.READ_HEAP_WRITE> Add an entry in the heap:"
+              << " owner_id = " << heap_entry.owner.srcid
+              << " owner_ins = " << heap_entry.owner.inst << std::endl;
+}
+#endif
+            }
+            else 
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                          << " READ_HEAP_WRITE state" << std::endl;
+                std::cout << "Bad HEAP allocation" << std::endl;
+                exit(0);
+            }
+            break;
+        }
+        /////////////////////
+        case READ_HEAP_ERASE:
+        {
+            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
+            {
+                HeapEntry next_entry = m_heap.read(r_read_ptr.read());
+                if( next_entry.next == r_read_ptr.read() )
+                {
+                    r_read_fsm = READ_HEAP_LAST;
+                } 
+                else 
+                {
+                    r_read_ptr = next_entry.next;
+                    r_read_fsm = READ_HEAP_ERASE;
+                }
+            } 
+            else 
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                          << " READ_HEAP_ERASE state" << std::endl;
+                std::cout << "Bad HEAP allocation" << std::endl;
+                exit(0);
+            }
+            break;
+        }
+        ////////////////////
+        case READ_HEAP_LAST:
+        {
+            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
+            {
+                HeapEntry last_entry;
+                last_entry.owner.srcid    = 0;
+#if L1_MULTI_CACHE
+                last_entry.owner.cache_id = 0;
+#endif
+                last_entry.owner.inst     = false;
+
+                if(m_heap.is_full())
+                {
+                    last_entry.next       = r_read_ptr.read();
+                    m_heap.unset_full();
+                } 
+                else 
+                {
+                    last_entry.next       = r_read_next_ptr.read();
+                }
+                m_heap.write(r_read_ptr.read(),last_entry);
+                r_read_fsm = READ_RSP;
+            } 
+            else 
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                          << " READ_HEAP_LAST state" << std::endl;
+                std::cout << "Bad HEAP allocation" << std::endl;
+                exit(0);
+            }
+            break;
         }
         //////////////
-      case READ_HEAP_LOCK:
-        {
-          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ ) {
-            bool is_cnt = (r_read_count.read() >= r_copies_limit.read()) || m_heap_directory.is_full();
-            // 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 or the heap is full
-            entry.dirty	  = r_read_dirty.read();
-            entry.tag	  = r_read_tag.read();
-            entry.lock	  = r_read_lock.read();
-            if(!is_cnt){ // Not counter mode
-                entry.owner.srcid   = r_read_copy.read();
-#if L1_MULTI_CACHE
-                entry.owner.cache_id= r_read_copy_cache.read();
-#endif
-                entry.owner.inst    = r_read_copy_inst.read();
-                entry.count         = r_read_count.read() + 1;
-                entry.ptr           = m_heap_directory.next_free_ptr();
-            } else { // Counter mode
-                entry.owner.srcid   = 0;
-#if L1_MULTI_CACHE
-                entry.owner.cache_id= 0;
-#endif
-                entry.owner.inst    = false;
-                entry.count         = r_read_count.read() + 1;
-                entry.ptr           = 0;
-            }
-#ifdef DDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	   std::cout << "In READ_HEAP_LOCK printing the entry of address is : " << std::endl;
-	   entry.print();
-	   std::cout << "done" << std::endl;
-}
-#endif
-
-            m_cache_directory.write(set, way, entry);
-
-            if(!is_cnt){
-              HeapEntry free_heap_entry = m_heap_directory.next_free_entry();
-              r_read_next_ptr = free_heap_entry.next;
-              if( free_heap_entry.next == m_heap_directory.next_free_ptr() ) { // Last free heap entry
-                r_read_last_free = true;
-              } else {
-                r_read_last_free = false;
-              }
-              r_read_fsm = READ_HEAP_WRITE; // we add an entry in the list of copies
-            } else {
-              if(r_read_count.read()>1) { // else there is no list of copies...
-                HeapEntry next_entry = m_heap_directory.read(r_read_ptr.read());
-                r_read_next_ptr = m_heap_directory.next_free_ptr();
-                m_heap_directory.write_free_ptr(r_read_ptr.read());
-                if( next_entry.next == r_read_ptr.read() ) { // The last list member
-                  r_read_fsm = READ_HEAP_LAST; // we erase the list of copies (counter mode)
-                } else { // Not the end of the list
-                  r_read_ptr = next_entry.next;
-                  r_read_fsm = READ_HEAP_ERASE; // we erase the list of copies (counter mode)
-                }
-              } else {
-                r_read_fsm = READ_RSP;
-              }
-            }
-          }
-          break;
-        }
-        //////////////
-      case READ_HEAP_WRITE:
-        {
-          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
-            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
-            HeapEntry new_heap_entry;
-            new_heap_entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
-#if L1_MULTI_CACHE
-            new_heap_entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
-#endif
-            new_heap_entry.owner.inst     = inst_read;
-            if(r_read_count.read() == 1){ // creation of a new list
-              new_heap_entry.next         = m_heap_directory.next_free_ptr(); 
-            } else {                      // it is an insertion
-              new_heap_entry.next         = r_read_ptr.read();
-            }
-            m_heap_directory.write_free_entry(new_heap_entry);
-            m_heap_directory.write_free_ptr(r_read_next_ptr.read());
-            if(r_read_last_free.read()) {
-              m_heap_directory.set_full();
-            }
-
-            r_read_fsm = READ_RSP;
-          } else {
-              ASSERT(false,"MEMCACHE Error : Bad HEAP allocation");
-          }
-          break;
-        }
-        //////////////
-      case READ_HEAP_ERASE:
-        {
-          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
-            HeapEntry next_entry = m_heap_directory.read(r_read_ptr.read());
-            if( next_entry.next == r_read_ptr.read() ){
-              r_read_fsm = READ_HEAP_LAST;
-            } else {
-              r_read_ptr = next_entry.next;
-              r_read_fsm = READ_HEAP_ERASE;
-            }
-          } else {
-              ASSERT(false,"MEMCACHE Error : Bad HEAP allocation");
-          }
-          break;
-        }
-        //////////////
-      case READ_HEAP_LAST:
-        {
-          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
-            HeapEntry last_entry;
-            last_entry.owner.srcid    = 0;
-#if L1_MULTI_CACHE
-            last_entry.owner.cache_id = 0;
-#endif
-            last_entry.owner.inst     = false;
-            if(m_heap_directory.is_full()){
-              last_entry.next      = r_read_ptr.read();
-              m_heap_directory.unset_full();
-            } else {
-              last_entry.next      = r_read_next_ptr.read();
-            }
-            m_heap_directory.write(r_read_ptr.read(),last_entry);
-            r_read_fsm = READ_RSP;
-          } else {
-              ASSERT(false,"MEMCACHE Error : Bad HEAP allocation");
-          }
-          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_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();
+                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();
+                cmd_read_fifo_get 	 = true;
+                r_read_to_tgt_rsp_req	 = true;
+                r_read_fsm 		 = READ_IDLE;  
+
+#if DEBUG_MEMC_READ
+if( m_debug_read_fsm )
+{
+    std::cout << "  <MEMC.READ_RSP> Request the TGT_RSP FSM to return data:"
+              << " rsrcid = " << std::hex << m_cmd_read_srcid_fifo.read()
+              << " / address = " << m_cmd_read_addr_fifo.read()
+              << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
+}
+#endif
+            }
+            break;
         }
         ///////////////////
-      case READ_TRT_LOCK:	// read miss : check the Transaction Table
-        {
-          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
-#ifdef TDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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
-              if(!wok)
-                m_cpt_trt_full++;
-              if(hit_read || hit_write)
-                m_cpt_trt_rb++;
-              r_read_fsm = READ_IDLE;
-            } else {			   // missing line is requested to the XRAM
-              m_cpt_read_miss++;
-              r_read_trt_index = index;
-              r_read_fsm       = READ_TRT_SET;
-            }
-          }
-          break;
+        case READ_TRT_LOCK:	// read miss : check the Transaction Table
+        {
+            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) 
+            {
+                size_t      index     = 0;
+                vci_addr_t  addr      = (vci_addr_t)m_cmd_read_addr_fifo.read();
+                bool        hit_read  = m_transaction_tab.hit_read(m_nline[addr], index);
+                bool        hit_write = m_transaction_tab.hit_write(m_nline[addr]);
+                bool        wok       = !m_transaction_tab.full(index);
+
+                if( hit_read || !wok || hit_write )  // missing line already requested or no space
+                {
+                    if(!wok) 			m_cpt_trt_full++;
+                    if(hit_read || hit_write) 	m_cpt_trt_rb++;
+                    r_read_fsm = READ_IDLE;
+                } 
+                else 			            // missing line is requested to the XRAM
+                {
+                    m_cpt_read_miss++;
+                    r_read_trt_index = index;
+                    r_read_fsm       = READ_TRT_SET;
+                }
+
+#if DEBUG_MEMC_READ
+if( m_debug_read_fsm )
+{
+    std::cout << "  <MEMC.READ_TRT_LOCK> Check TRT:"
+              << " hit_read = " << hit_read 
+              << " / hit_write = " << hit_write 
+              << " / full = " << !wok << std::endl;
+}
+#endif
+            }
+            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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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;
+        case READ_TRT_SET:      // register get transaction in TRT
+        {
+            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));
+#if DEBUG_MEMC_READ
+if( m_debug_read_fsm )
+{
+    std::cout << "  <MEMC.READ_TRT_SET> Write in Transaction Table: " << std::hex
+              << " address = " << m_cmd_read_addr_fifo.read() 
+              << " / srcid = " << m_cmd_read_srcid_fifo.read() << std::endl;
+}
+#endif
+                r_read_fsm = READ_TRT_REQ;
+            }
+            break;
+        }
+        //////////////////
+        case READ_TRT_REQ:		// consume the read request in the FIFO,
+                				// and send it to the ixr_cmd_fsm
+        {	
+            if( not 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;
+
+#if DEBUG_MEMC_READ
+if( m_debug_read_fsm )
+{
+    std::cout << "  <MEMC.READ_TRT_REQ> Request GET transaction for address " 
+              << m_cmd_read_addr_fifo.read() << std::endl;
+}
+#endif
+            }
+            break;
         }
     } // end switch read_fsm
@@ -1240,7 +1504,10 @@
     //   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 
+    //   If the data is cached by other processors, a coherence transaction must
+    //   be launched:
+    //   It is a multicast update if the line is not in counter mode, and the processor
+    //   takes the lock protecting the Update Table (UPT) to register this transaction.
+    //   It is a broadcast invalidate if the line is in counter mode.
+    //   If the UPT is full, it releases the lock(s) and retry. 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 
@@ -1256,140 +1523,210 @@
     /////////////////////////////////////////////////////////////////////////////////////
 
-    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()) {
-              PRINTF("  * <MEM_CACHE.WRITE> KANE Request from %d.%d (%d) at address %llx\n",(uint32_t)m_cmd_write_srcid_fifo.read(),(uint32_t)m_cmd_write_pktid_fifo.read(),(uint32_t) m_cmd_write_trdid_fifo.read(), (uint64_t)m_cmd_write_addr_fifo.read());
-
-            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;
-        }
+    switch ( r_write_fsm.read() ) 
+    {
         ////////////////
-      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_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();
+
+                // initialize the be field 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;
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_IDLE> Write request " 
+              << " srcid = " << std::hex << m_cmd_write_srcid_fifo.read()
+              << " / address = " << m_cmd_write_addr_fifo.read() 
+              << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        ////////////////
+        case WRITE_NEXT:	// copy next word of a write burst in local buffer
+        {
+            if ( m_cmd_write_addr_fifo.rok() ) 
+            {
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_NEXT> Write another word in local buffer" << std::endl;
+}
+#endif
+                m_cpt_write_cells++;
+
+                // check that the next word is in the same cache line
+                if ( (m_nline[(vci_addr_t)(r_write_address.read())] != 
+                      m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())]) )
+                {
+                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_NEXT state" << std::endl;
+                    std::cout << "all words in a write burst must be in same cache line" << std::endl;
+                    exit(0);
+                }
+
+                // 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_copy      = entry.owner.srcid;
+        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));
+
+                if ( entry.valid ) // hit 
+                {	
+                    // copy directory entry in local buffer in case of hit
+                    r_write_is_cnt     = entry.is_cnt;
+                    r_write_lock       = entry.lock;
+                    r_write_tag        = entry.tag;
+                    r_write_copy       = entry.owner.srcid;
 #if L1_MULTI_CACHE
-              r_write_copy_cache= entry.owner.cache_id;
-#endif
-              r_write_copy_inst = entry.owner.inst;
-              r_write_count     = entry.count;
-              r_write_ptr       = entry.ptr;
-              r_write_way  	    = way;
-              if( entry.is_cnt && entry.count ) {
-                r_write_fsm      = WRITE_DIR_HIT_READ;
-              } else {
-                if(r_write_byte.read())
-                  r_write_fsm      = WRITE_DIR_HIT_READ;
-                else  r_write_fsm  = WRITE_DIR_HIT;
-              }
-            } else {
-              r_write_fsm = WRITE_TRT_LOCK;
-            }
-          }
-          break;
+                    r_write_copy_cache = entry.owner.cache_id;
+#endif
+                    r_write_copy_inst  = entry.owner.inst;
+                    r_write_count      = entry.count;
+                    r_write_ptr        = entry.ptr;
+                    r_write_way        = way;
+
+                    if( entry.is_cnt && entry.count ) 
+                    {
+                        r_write_fsm      = WRITE_DIR_HIT_READ;
+                    } 
+                    else 
+                    {
+                        if (r_write_byte.read()) 	r_write_fsm = WRITE_DIR_HIT_READ;
+                        else  				        r_write_fsm = WRITE_DIR_HIT;
+                    }
+                } 
+                else 	// miss
+                {
+                    r_write_fsm = WRITE_TRT_LOCK;
+                }
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_DIR_LOCK> Check the directory: "
+              << " address = " << r_write_address.read()
+              << " hit = " << entry.valid 
+              << " count = " << std::dec << entry.count 
+              << " is_cnt = " << entry.is_cnt << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        ////////////////////////
+        case WRITE_DIR_HIT_READ:	// read the cache and complete the buffer 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;
+
+                // complete only if mask is not null (for energy consumption)
+                if ( r_write_be[i].read() || r_write_is_cnt.read() ) 
+                { 
+                    r_write_data[i]  = (r_write_data[i].read() & mask) | 
+                                           (m_cache_data[way][set][i] & ~mask);
+                }
+            } // end for
+
+            // test if a coherence broadcast is required
+            if( r_write_is_cnt.read() && r_write_count.read() ) r_write_fsm = WRITE_TRT_WRITE_LOCK;
+            else  						r_write_fsm = WRITE_DIR_HIT;
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    if( r_write_is_cnt.read() && r_write_count.read() )
+    {
+        std::cout << "  <MEMC.WRITE_DIR_HIT_READ> Read the cache to complete local buffer /" 
+                  << " coherence broadcast required" << std::endl;
+    }
+    else
+    {
+        std::cout << "  <MEMC.WRITE_DIR_HIT_READ> Read the cache to complete local buffer" 
+                  << std::endl;
+    } 
+}
+#endif
+            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()) { // 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_fsm            = WRITE_TRT_WRITE_LOCK;
-          } 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.owner.srcid   = r_write_copy.read();
+        case WRITE_DIR_HIT:	   // update the cache (data & directory)
+        {
+            // 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.owner.srcid    = r_write_copy.read();
 #if L1_MULTI_CACHE
-          entry.owner.cache_id= r_write_copy_cache.read();
-#endif
-          entry.owner.inst    = r_write_copy_inst.read();
-          entry.count         = r_write_count.read();
-          entry.ptr           = r_write_ptr.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);
-
-          bool owner = (((r_write_copy.read()==r_write_srcid.read())
+            entry.owner.cache_id = r_write_copy_cache.read();
+#endif
+            entry.owner.inst     = r_write_copy_inst.read();
+            entry.count          = r_write_count.read();
+            entry.ptr            = r_write_ptr.read();
+            size_t set	         = m_y[(vci_addr_t)(r_write_address.read())];
+            size_t way	         = r_write_way.read();
+
+            // update directory
+            m_cache_directory.write(set, way, entry);
+
+            // owner is true when the writer is the owner
+            bool owner = (((r_write_copy.read() == r_write_srcid.read())
 #if L1_MULTI_CACHE
                          and (r_write_copy_cache.read()==r_write_pktid.read())
@@ -1397,391 +1734,487 @@
                          ) and not r_write_copy_inst.read());
 
-          bool no_update = (r_write_count.read()==0) || ( owner && (r_write_count.read()==1));
-
-          if( no_update ) // no update
-          {
-            // 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
-          }
-
-          size_t count_signal   = r_write_count.read();
-          if(owner){
-            count_signal        = count_signal - 1;
-          }
-          r_write_count         = count_signal;
-          r_write_to_dec        = false;
-
-          if ( no_update )      r_write_fsm = WRITE_RSP;
-          else                  
+            // no_update is true when there is no need for coherence transaction 
+            bool no_update = (r_write_count.read()==0) || ( owner && (r_write_count.read()==1));
+
+            // write data in the cache if no transaction on the coherence network
+            if( no_update ) 
+            {
+                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();
+                } 
+            }
+
+            if ( owner )   r_write_count = r_write_count.read() - 1;
+            r_write_to_dec = false;
+
+            if ( no_update )      // Write transaction completed
+            {
+                r_write_fsm = WRITE_RSP;
+            }
+            else          // coherence update required        
+            {
+                if( !r_write_to_init_cmd_multi_req.read() && 
+                   !r_write_to_init_cmd_brdcast_req.read()  ) 	r_write_fsm = WRITE_UPT_LOCK;
+                else 						r_write_fsm = WRITE_WAIT;
+            }
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    if ( no_update )
+    {
+        std::cout << "  <MEMC.WRITE_DIR_HIT> Write into cache / No coherence transaction" 
+                  << std::endl;
+    }
+    else
+    {
+        std::cout << "  <MEMC.WRITE_DIR_HIT> Coherence update required:"
+                  << " is_cnt = " << r_write_is_cnt.read() 
+                  << " count = " << std::dec << r_write_count.read() 
+                  << std::endl;
+    }
+}
+#endif
+            break;
+        }
+        /////////////////////
+        case WRITE_UPT_LOCK: 	// Try to register the update request in UPT
+        {
+            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();
+                size_t      set	       = m_y[(vci_addr_t)(r_write_address.read())];
+                size_t 	    way	       = r_write_way.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);
+                if ( wok )    // 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();
+                    } 
+                }
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    if ( wok )
+    {
+        std::cout << "  <MEMC.WRITE_UPT_LOCK> Register the multicast update in UPT / " 
+                  << " nb_copies = " << r_write_count.read() << std::endl;
+	//m_update_tab.print();
+    }
+}
+#endif
+                r_write_upt_index = index;
+                //  releases the lock protecting the Update Table and the Directory if no entry...
+                if ( wok ) r_write_fsm = WRITE_HEAP_LOCK;
+                else       r_write_fsm = WRITE_WAIT;
+            }
+            break;
+        }
+        /////////////////////
+        case WRITE_HEAP_LOCK:
+        {
+            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE )
+            {
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_HEAP_LOCK> Get acces to the HEAP" << std::endl;
+}
+#endif
+                r_write_fsm = WRITE_UPT_REQ;
+            }
+            break;
+        }
+        //////////////////
+        case WRITE_UPT_REQ:
+        {
+            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_WRITE )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_UPT_REQ state" << std::endl;
+                std::cout << "bad HEAP allocation" << std::endl;
+                exit(0);
+            }
+
             if( !r_write_to_init_cmd_multi_req.read() && 
-              !r_write_to_init_cmd_brdcast_req.read()  )
-                r_write_fsm = WRITE_UPT_LOCK;
-            else
-                r_write_fsm = WRITE_WAIT;
-          break;
+                !r_write_to_init_cmd_brdcast_req.read()  )
+            {
+                r_write_to_init_cmd_brdcast_req  = 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();
+
+                for(size_t i=0; i<m_words ; i++)
+                {
+                    r_write_to_init_cmd_be[i]=r_write_be[i].read();
+                }
+
+                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];
+            
+                if( (r_write_copy.read() != r_write_srcid.read()) or
+#if L1_MULTI_CACHE
+                    (r_write_copy_cache.read() != r_write_pktid.read()) or
+#endif
+                    r_write_copy_inst.read() ) 
+                {
+                    // We put the first copy in the fifo
+                    write_to_init_cmd_fifo_put     = true;
+                    write_to_init_cmd_fifo_inst    = r_write_copy_inst.read();
+                    write_to_init_cmd_fifo_srcid   = r_write_copy.read();
+#if L1_MULTI_CACHE
+                    write_to_init_cmd_fifo_cache_id= r_write_copy_cache.read();
+#endif
+                    if(r_write_count.read() == 1)
+                    {
+                        r_write_fsm = WRITE_IDLE;
+                        r_write_to_init_cmd_multi_req = true;
+                    } 
+                    else 
+                    {
+                        r_write_fsm = WRITE_UPDATE;
+                    }
+                } 
+                else 
+                {
+                    r_write_fsm = WRITE_UPDATE;
+                }
+            }
+            break;
+        }
+        //////////////////
+        case WRITE_UPDATE:	// send a multi-update request to INIT_CMD fsm
+        {
+            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_WRITE )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_UPDATE state" << std::endl;
+                std::cout << "bad HEAP allocation" << std::endl;
+                exit(0);
+            }
+
+            HeapEntry entry = m_heap.read(r_write_ptr.read());
+            write_to_init_cmd_fifo_inst     = entry.owner.inst;
+            write_to_init_cmd_fifo_srcid    = entry.owner.srcid;
+#if L1_MULTI_CACHE
+            write_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
+#endif
+          
+            bool dec_upt_counter = r_write_to_dec.read();
+            if( (entry.owner.srcid != r_write_srcid.read()) or
+#if L1_MULTI_CACHE
+                (entry.owner.cache_id != r_write_pktid.read()) or
+#endif
+                entry.owner.inst)
+            {
+                write_to_init_cmd_fifo_put = true;
+            } 
+            else 
+            {
+                dec_upt_counter = true;
+            }
+            r_write_to_dec = dec_upt_counter;
+
+            if( m_write_to_init_cmd_inst_fifo.wok() )
+            {
+                r_write_ptr = entry.next;
+                if( entry.next == r_write_ptr.read() )  // last copy
+                {
+                    r_write_to_init_cmd_multi_req = true;
+                    if(dec_upt_counter) r_write_fsm = WRITE_UPT_DEC;
+                    else  		r_write_fsm = WRITE_IDLE;
+                } 
+                else 
+                {
+                    r_write_fsm = WRITE_UPDATE;
+                }
+            } 
+            else 
+            {
+                r_write_fsm = WRITE_UPDATE;
+            }
+            break;
+        }
+        //////////////////
+        case WRITE_UPT_DEC: 	// Post another coherence update request
+        {
+            if ( !r_write_to_init_rsp_req.read() )
+            {
+                r_write_to_init_rsp_req = true;
+                r_write_to_init_rsp_upt_index = r_write_upt_index.read();
+                r_write_fsm = WRITE_IDLE;
+            }
+            break;
+        }
+        ///////////////
+        case WRITE_RSP:		// Post a request to TGT_RSP FSM to acknowledge the write
+        {
+            if ( !r_write_to_tgt_rsp_req.read() ) 
+            {
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_RSP> Post a request to TGT_RSP FSM: rsrcid = "
+              << std::hex << r_write_srcid.read() << std:: endl;
+}
+#endif
+                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 ) 
+            {
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_TRT_LOCK> Check the TRT" << std::endl;
+}
+#endif
+                size_t 		hit_index = 0;
+                size_t 		wok_index = 0;
+                vci_addr_t	addr      = (vci_addr_t)r_write_address.read();
+                bool 		hit_read  = m_transaction_tab.hit_read(m_nline[addr], hit_index);
+                bool 		hit_write = m_transaction_tab.hit_write(m_nline[addr]);
+                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;
+                    m_cpt_write_miss++;
+                } 
+                else if ( wok && !hit_write ) 	// set a new entry in TRT
+                {
+                    r_write_trt_index = wok_index;
+                    r_write_fsm       = WRITE_TRT_SET;
+                    m_cpt_write_miss++;
+                } 
+                else 		// wait an empty entry in TRT
+                {
+                    r_write_fsm       = WRITE_WAIT;
+                    m_cpt_trt_full++;
+                }
+            }
+            break;
+        }
+        ////////////////
+        case WRITE_WAIT:	// release the locks protecting the shared ressources
+        { 
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_WAIT> Releases the locks before retry" << std::endl;
+}
+#endif
+            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);
+                r_write_fsm = WRITE_XRAM_REQ;
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_TRT_SET> Set a new entry in TRT" << std::endl;
+}
+#endif
+            }
+            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;
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_TRT_DATA> Modify an existing entry in TRT" << std::endl;
+    m_transaction_tab.print( r_write_trt_index.read() );
+}
+#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;
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_XRAM_REQ> Post a request to the IXR_CMD FSM" << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        //////////////////////////
+        case WRITE_TRT_WRITE_LOCK:	// Check TRT not full
+        {
+            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;
+                }
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_TRT_WRITE_LOCK> Check TRT : wok = "
+              << wok << " index = " << wok_index << std::endl;
+}
+#endif
+            }
+            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);
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    if ( wok )
+    { 
+        std::cout << "  <MEMC.WRITE_INVAL_LOCK> Register the broadcast inval in UPT / " 
+                  << " nb_copies = " << r_write_count.read() << std::endl;
+	//m_update_tab.print();
+    }
+}
+#endif
+                r_write_upt_index = index;
+
+                if ( wok ) r_write_fsm = WRITE_DIR_INVAL;
+                else       r_write_fsm = WRITE_WAIT;
+            }
+            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();
-            size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
-            size_t way	    = r_write_way.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);
-            if(wok){
-              // 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
-            }
-#ifdef IDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-            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 the Update Table and the Directory if no entry...
-            if ( wok ) r_write_fsm = WRITE_HEAP_LOCK;
-            else       r_write_fsm = WRITE_WAIT;
-          }
-          break;
-        }
-        //////////////////
-      case WRITE_HEAP_LOCK:
-        {
-          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE ){
-            r_write_fsm = WRITE_UPT_REQ;
-          }
-          break;
-        }
-        //////////////////
-      case WRITE_UPT_REQ:
-        {
-          ASSERT( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE)
-                  ,"MemCache ERROR : bad HEAP allocation");
-          if( !r_write_to_init_cmd_multi_req.read() && 
-              !r_write_to_init_cmd_brdcast_req.read()  ){
-            r_write_to_init_cmd_brdcast_req  = 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();
-
-            for(size_t i=0; i<m_words ; i++){
-              r_write_to_init_cmd_be[i]=r_write_be[i].read();
-            }
-
-            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];
-            }
-            
-            if((r_write_copy.read() != r_write_srcid.read()) or
-#if L1_MULTI_CACHE
-               (r_write_copy_cache.read() != r_write_pktid.read()) or
-#endif
-               r_write_copy_inst.read() ) {
-              // We put the first copy in the fifo
-              write_to_init_cmd_fifo_put     = true;
-              write_to_init_cmd_fifo_inst    = r_write_copy_inst.read();
-              write_to_init_cmd_fifo_srcid   = r_write_copy.read();
-#if L1_MULTI_CACHE
-              write_to_init_cmd_fifo_cache_id= r_write_copy_cache.read();
-#endif
-              if(r_write_count.read() == 1){
-                r_write_fsm = WRITE_IDLE;
-                r_write_to_init_cmd_multi_req = true;
-              } else {
-                r_write_fsm = WRITE_UPDATE;
-              }
-            } else {
-              r_write_fsm = WRITE_UPDATE;
-            }
-          }
-          break;
-        }
-        //////////////////
-      case WRITE_UPDATE:	// send a multi-update request to INIT_CMD fsm
-        {
-          ASSERT( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE)
-                  ,"MemCache ERROR : bad HEAP allocation");
-          HeapEntry entry = m_heap_directory.read(r_write_ptr.read());
-          write_to_init_cmd_fifo_inst     = entry.owner.inst;
-          write_to_init_cmd_fifo_srcid    = entry.owner.srcid;
-#if L1_MULTI_CACHE
-          write_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
-#endif
-          
-          bool dec_upt_counter = r_write_to_dec.read();
-          if( (entry.owner.srcid != r_write_srcid.read()) or
-#if L1_MULTI_CACHE
-              (entry.owner.cache_id != r_write_pktid.read()) or
-#endif
-              entry.owner.inst){
-            write_to_init_cmd_fifo_put = true;
-          } else {
-            dec_upt_counter = true;
-          }
-          r_write_to_dec = dec_upt_counter;
-
-          if( m_write_to_init_cmd_inst_fifo.wok() ){
-            r_write_ptr = entry.next;
-            if( entry.next == r_write_ptr.read() ) { // last copy
-              r_write_to_init_cmd_multi_req = true;
-              if(dec_upt_counter){
-                r_write_fsm = WRITE_UPT_DEC;
-              } else {
-                r_write_fsm = WRITE_IDLE;
-              }
-            } else {
-              r_write_fsm = WRITE_UPDATE;
-            }
-          } else {
-            r_write_fsm = WRITE_UPDATE;
-          }
-          break;
-        }
-        //////////////////
-      case WRITE_UPT_DEC:
-        {
-          if(!r_write_to_init_rsp_req.read()){
-            r_write_to_init_rsp_req = true;
-            r_write_to_init_rsp_upt_index = r_write_upt_index.read();
-            r_write_fsm = WRITE_IDLE;
-          }
-          break;
-        }
-        ///////////////
-      case WRITE_RSP:		// send a request to TGT_RSP FSM to acknowledge the write
-        {
-          if ( !r_write_to_tgt_rsp_req.read() ) {
-
-            PRINTF("  * <MEM_CACHE.WRITE> Request from %d.%d (%d)\n",(uint32_t)r_write_srcid.read(), (uint32_t)r_write_trdid.read(), (uint32_t)r_write_pktid.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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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;
-              m_cpt_write_miss++;
-            } else if ( wok && !hit_write ) {	// set a new entry in TRT
-              r_write_trt_index = wok_index;
-              r_write_fsm       = WRITE_TRT_SET;
-              m_cpt_write_miss++;
-            } else {		// wait an empty entry in TRT
-              r_write_fsm       = WRITE_WAIT;
-              m_cpt_trt_full++;
-            }
-          }
-          break;
-        }
-        ////////////////////
-      case WRITE_WAIT:	// 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]);
-            }
+        case WRITE_DIR_INVAL:	// Register a put transaction to XRAM in TRT
+				// and invalidate the line in directory
+        {
+            if ( (r_alloc_trt_fsm.read() != ALLOC_TRT_WRITE ) ||
+                 (r_alloc_upt_fsm.read() != ALLOC_UPT_WRITE ) ||
+                 (r_alloc_dir_fsm.read() != ALLOC_DIR_WRITE ) )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_DIR_INVAL state" << std::endl;
+                std::cout << "bad TRT, DIR, or UPT allocation" << std::endl;
+                exit(0);
+            }
+
+            // register a write request to XRAM in TRT
             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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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;
-            }
-          }
-
-          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(m_cpt_cycles > DEBUG_START_CYCLE){
-            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;
-          }
-
-          break;
-        }
-        ////////////////////
-      case WRITE_DIR_INVAL:
-        {
-            ASSERT(((r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) &&
-                    (r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) &&
-                    (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ))
-                   ,"MemCache ERROR : bad TRT,DIR or UPT allocation error");
-            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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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
-
+                                  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));
             // invalidate directory entry
             DirectoryEntry entry;
@@ -1800,45 +2233,67 @@
             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);
 
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_DIR_INVAL> Invalidate the directory entry: @ = "
+              << r_write_address.read() << " / register the put transaction in TRT:" << std::endl;
+}
+#endif
             r_write_fsm = WRITE_INVAL;
             break;
         }
-        ////////////////////
-      case WRITE_INVAL:
-        {
-          if (  !r_write_to_init_cmd_multi_req.read() &&
-                !r_write_to_init_cmd_brdcast_req.read() ) {
-            r_write_to_init_cmd_multi_req   = false;
-            r_write_to_init_cmd_brdcast_req = 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;
-
-            for(size_t i=0; i<m_words ; i++){
-              r_write_to_init_cmd_be[i]=0;
-              r_write_to_init_cmd_data[i] = 0;
-            }
-            r_write_fsm = WRITE_XRAM_SEND;
-            // all inval 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;
+        /////////////////
+        case WRITE_INVAL:    // Post a coherence broadcast request to INIT_CMD FSM
+        {
+            if ( !r_write_to_init_cmd_multi_req.read() && !r_write_to_init_cmd_brdcast_req.read() ) 
+            {
+                r_write_to_init_cmd_multi_req   = false;
+                r_write_to_init_cmd_brdcast_req = 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;
+
+                for(size_t i=0; i<m_words ; i++)
+                {
+                    r_write_to_init_cmd_be[i]=0;
+                    r_write_to_init_cmd_data[i] = 0;
+                }
+                r_write_fsm = WRITE_XRAM_SEND;
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_INVAL> Post a broadcast request to INIT_CMD FSM" << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////////////
+        case WRITE_XRAM_SEND:   // Post a put 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   = 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;
+
+#if DEBUG_MEMC_WRITE
+if( m_debug_write_fsm )
+{
+    std::cout << "  <MEMC.WRITE_XRAM_SEND> Post a put request to IXR_CMD FSM" << std::endl;
+}
+#endif
+            }
+            break;
         }
     } // end switch r_write_fsm
@@ -1848,27 +2303,28 @@
     ///////////////////////////////////////////////////////////////////////
     // 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 
+    // - It sends a single cell VCI get request to the XRAM in case of MISS
+    // posted by the READ, WRITE or SC 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. 
+    // - It sends a multi-cell VCI write when the XRAM_RSP FSM, WRITE FSM
+    // or SC 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 
+    // This FSM handles requests from the READ, WRITE, SC & XRAM_RSP FSMs 
     // with a round-robin priority.
     ////////////////////////////////////////////////////////////////////////
 
-    switch ( r_ixr_cmd_fsm.read() ) {
-      //////////////////////// 
-      case IXR_CMD_READ_IDLE:
+    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_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_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;
+        case IXR_CMD_WRITE_IDLE:
+        if      ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_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;
@@ -1876,68 +2332,129 @@
         break;
         //////////////////////// 
-      case IXR_CMD_LLSC_IDLE:
+        case IXR_CMD_SC_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;
+        else if ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_NLINE;
         break;
         //////////////////////// 
-      case IXR_CMD_XRAM_IDLE:
+        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_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_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;
+        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;
+
+#if DEBUG_MEMC_IXR_CMD
+if( m_debug_ixr_cmd_fsm )
+{
+    std::cout << "  <MEMC.IXR_CMD_READ_NLINE> Send a get request to xram" ;
+}
+#endif
         }
         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;
-          }
+        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;
+                }
+
+#if DEBUG_MEMC_IXR_CMD
+if( m_debug_ixr_cmd_fsm )
+{
+    std::cout << "  <MEMC.IXR_CMD_WRITE_NLINE> Send a put request to xram" ;
+}
+#endif
+            } 
+            else 
+            {
+                r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;		
+                r_write_to_ixr_cmd_req = false;
+
+#if DEBUG_MEMC_IXR_CMD
+if( m_debug_ixr_cmd_fsm )
+{
+    std::cout << "  <MEMC.IXR_CMD_WRITE_NLINE> Send a get request to xram" ;
+}
+#endif
+            }
         }
         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;
-          }
+        //////////////////////
+        case IXR_CMD_SC_NLINE:
+        if ( p_vci_ixr.cmdack ) 
+        {
+            if( r_sc_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_SC_IDLE;
+                    r_sc_to_ixr_cmd_req = false;
+                } 
+                else 
+                {
+                    r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+                }
+
+#if DEBUG_MEMC_IXR_CMD
+if( m_debug_ixr_cmd_fsm )
+{
+    std::cout << "  <MEMC.IXR_CMD_SC_NLINE> Send a put request to xram" ;
+}
+#endif
+            } 
+            else 
+            {
+                r_ixr_cmd_fsm = IXR_CMD_SC_IDLE;		
+                r_sc_to_ixr_cmd_req = false;
+
+#if DEBUG_MEMC_IXR_CMD
+if( m_debug_ixr_cmd_fsm )
+{
+    std::cout << "  <MEMC.IXR_CMD_SC_NLINE> Send a get request to xram" ;
+}
+#endif
+            }
         }
         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;
-          }
+        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;
+            }
+
+#if DEBUG_MEMC_IXR_CMD
+if( m_debug_ixr_cmd_fsm )
+{
+    std::cout << "  <MEMC.IXR_CMD_XRAM_DATA> Send a put request to xram" ;
+}
+#endif
         }
         break;
@@ -1949,12 +2466,12 @@
     ////////////////////////////////////////////////////////////////////////////
     // The IXR_RSP FSM receives the response packets from the XRAM,
-    // for both write transaction, and read transaction.
+    // for both put transaction, and get transaction.
     //
-    // - A response to a write request is a single-cell VCI packet.
+    // - A response to a put 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.
+    // - A response to a get 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.
@@ -1964,72 +2481,104 @@
     ///////////////////////////////////////////////////////////////////////////////
 
-    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.read() ) {
-            r_ixr_rsp_cpt   = 0;
-            r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
-            if ( p_vci_ixr.reop.read() && !(p_vci_ixr.rerror.read()&0x1))  
-                r_ixr_rsp_fsm = IXR_RSP_ACK;
-            else                   
-                r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
-          }
-          break;  
+    switch ( r_ixr_rsp_fsm.read() ) 
+    {
+        ///////////////////
+        case IXR_RSP_IDLE:	// test if it's a get or a put transaction
+        {
+            if ( p_vci_ixr.rspval.read() ) 
+            {
+                r_ixr_rsp_cpt   = 0;
+                r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
+                if ( p_vci_ixr.reop.read() && !(p_vci_ixr.rerror.read()&0x1))  // put transaction
+                {
+                    r_ixr_rsp_fsm = IXR_RSP_ACK;
+
+#if DEBUG_MEMC_IXR_RSP
+if( m_debug_ixr_rsp_fsm ) 
+{
+    std::cout << "  <MEMC.IXR_RSP_IDLE> Response from XRAM to a put transaction" << std::endl; 
+}
+#endif
+                }
+                else 							       // get transaction
+                {
+  		    r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
+
+#if DEBUG_MEMC_IXR_RSP
+if( m_debug_ixr_rsp_fsm ) 
+{
+    std::cout << "  <MEMC.IXR_RSP_IDLE> Response from XRAM to a get transaction" << std::endl; 
+}
+#endif
+                }
+            }
+            break;  
         }
         ////////////////////////
-      case IXR_RSP_ACK:        // Acknowledge the vci response
-        {
-            if(p_vci_ixr.rspval.read())
-                r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
+        case IXR_RSP_ACK:        // Aknowledge the VCI response
+        {
+            if(p_vci_ixr.rspval.read()) r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
+
+#if DEBUG_MEMC_IXR_RSP
+if( m_debug_ixr_rsp_fsm ) 
+{
+    std::cout << "  <MEMC.IXR_RSP_ACK>" << std::endl; 
+}
+#endif
             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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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_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;
+
+#if DEBUG_MEMC_IXR_RSP
+if( m_debug_ixr_rsp_fsm )
+{
+    std::cout << "  <MEMC.IXR_RSP_TRT_ERASE> Erase TRT entry " 
+              << r_ixr_rsp_trt_index.read() << std::endl; 
+}
+#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))) ||
-                    p_vci_ixr.rerror.read())
-                   ,"Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
-            m_transaction_tab.write_rsp(index, r_ixr_rsp_cpt.read(), data, p_vci_ixr.rerror.read()&0x1);
-            r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
-            if ( eop ) {
-#ifdef TDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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;
+        case IXR_RSP_TRT_READ:		// write data in the TRT
+        {
+            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval ) 
+            {
+                size_t index    = r_ixr_rsp_trt_index.read();
+                bool   eop  	= p_vci_ixr.reop.read();
+                data_t data 	= p_vci_ixr.rdata.read();
+                bool   error    = (p_vci_ixr.rerror.read()&0x1 == 0);
+                assert(((eop == (r_ixr_rsp_cpt.read() == (m_words-1))) || p_vci_ixr.rerror.read()) 
+                    and "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
+                m_transaction_tab.write_rsp(index, 
+                                            r_ixr_rsp_cpt.read(), 
+                                            data, 
+                                            error);
+                r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
+                if ( eop ) 
+                {
+                    r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
+                    r_ixr_rsp_fsm = IXR_RSP_IDLE;
+                }
+
+#if DEBUG_MEMC_IXR_RSP
+if( m_debug_ixr_rsp_fsm )
+{
+    std::cout << "  <MEMC.IXR_RSP_TRT_READ> Writing a word in TRT : "
+              << " index = " << std::dec << index
+              << " / word = " << r_ixr_rsp_cpt.read()
+              << " / data = " << std::hex << data << std::endl;
+}
+#endif
+            }
+            break;
         }
     } // end swich r_ixr_rsp_fsm
-
 
     ////////////////////////////////////////////////////////////////////////////
@@ -2037,10 +2586,13 @@
     ////////////////////////////////////////////////////////////////////////////
     // 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.
+    // The cache line has been written in the TRT by the IXR_CMD_FSM.
+    // As the IXR_RSP FSM and the XRAM_RSP FSM are running in parallel,
+    // there is as many flip-flops r_ixr_rsp_to_xram_rsp_rok[i]
+    // as the number of entries in the TRT, that are handled with
+    // a round-robin priority...
     //
     // 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.
+    // must be copied in a local buffer to be written in the cache. 
+    // The FSM takes the lock protecting the TRT, and the lock protecting the DIR.
     // 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
@@ -2053,35 +2605,337 @@
     ///////////////////////////////////////////////////////////////////////////////
 
-    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 = m_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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << "XRAM_RSP FSM in XRAM_RSP_IDLE state" << std::endl;
-}
-#endif
-            }
-          }
-          break;  
+    switch ( r_xram_rsp_fsm.read() ) 
+    {
+        ///////////////////
+        case XRAM_RSP_IDLE:	// scan the XRAM responses to get the TRT index (round robin)
+        {
+            size_t ptr   = r_xram_rsp_trt_index.read();
+            size_t lines = m_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;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{	
+    std::cout << "  <MEMC.XRAM_RSP_IDLE> Available cache line in TRT:"
+              << " index = " << std::dec << index << std::endl;
+}
+#endif
+                    break;
+                }
+            }
+            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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_LOCK state" << std::endl;
+        case XRAM_RSP_DIR_LOCK: 	// Takes the lock on the directory
+        {
+            if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) 
+            {
+                r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{	
+    std::cout << "  <MEMC.XRAM_RSP_DIR_LOCK> Get access to directory" << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        ///////////////////////
+        case XRAM_RSP_TRT_COPY:		// Takes the lock on TRT
+                                    // Copy the TRT entry in a local buffer 
+                                    // and select a victim cache line
+        {
+            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) ) 
+            {
+                // copy the TRT entry in the r_xram_rsp_trt_buf local buffer
+                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));
+
+                bool inval = (victim.count && victim.valid) ;
+
+                // copy the victim line in a local buffer
+                for (size_t i=0 ; i<m_words ; i++) 
+                    r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
+                r_xram_rsp_victim_copy      = victim.owner.srcid;
+#if L1_MULTI_CACHE
+                r_xram_rsp_victim_copy_cache= victim.owner.cache_id;
+#endif
+                r_xram_rsp_victim_copy_inst = victim.owner.inst;
+                r_xram_rsp_victim_count     = victim.count;
+                r_xram_rsp_victim_ptr       = victim.ptr;
+                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;
+
+                if(!trt_entry.rerror) 	r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
+                else 			        r_xram_rsp_fsm = XRAM_RSP_ERROR_ERASE;      
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_TRT_COPY> Select a slot: "
+              << " way = " << std::dec << way 
+              << " / set = " << set 
+              << " / inval_required = " << inval << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////////////////
+        case XRAM_RSP_INVAL_LOCK:	// check a possible pending inval
+        {
+            if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP ) 
+            {
+                size_t index;
+                if (m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index))
+                {
+                    r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
+              << " but an invalidation is already registered at this address" << std::endl;
+    m_update_tab.print();
+}
+#endif
+
+                }
+	        else if (m_update_tab.is_full() && r_xram_rsp_victim_inval.read())
+                {
+	            r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
+              << " but the table is full" << std::endl;
+    m_update_tab.print();
+}
+#endif
+	        }
+                else 
+                {
+                    r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_INVAL_LOCK> Get acces to UPT" << std::endl;
+}
+#endif
+                }
+            }
+            break;
+        }
+        /////////////////////////
+        case XRAM_RSP_INVAL_WAIT:	// returns to DIR_LOCK to retry
+        {
+            r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
+            break;
+        }
+        ///////////////////////
+        case XRAM_RSP_DIR_UPDT:		// updates the cache (both data & directory)
+                                        // and possibly set an inval request in UPT 
+        {
+            // signals generation
+            bool inst_read = (r_xram_rsp_trt_buf.trdid & 0x2) && r_xram_rsp_trt_buf.proc_read; 
+            bool cached_read = (r_xram_rsp_trt_buf.trdid & 0x1) && 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  = false;
+            entry.lock	  = false;
+            entry.dirty	  = dirty;
+            entry.tag	  = r_xram_rsp_trt_buf.nline / m_sets;
+            entry.ptr     = 0;
+            if(cached_read) 
+            {
+                entry.owner.srcid   = r_xram_rsp_trt_buf.srcid;
+#if L1_MULTI_CACHE
+                entry.owner.cache_id= r_xram_rsp_trt_buf.pktid;
+#endif
+                entry.owner.inst    = inst_read;
+                entry.count         = 1;
+            } 
+            else 
+            {
+                entry.owner.srcid    = 0;
+#if L1_MULTI_CACHE
+                entry.owner.cache_id = 0;
+#endif
+                entry.owner.inst     = 0;
+                entry.count          = 0;
+            }
+            m_cache_directory.write(set, way, entry);
+
+            if (r_xram_rsp_victim_inval.read())
+            {
+                bool   brdcast 		= r_xram_rsp_victim_is_cnt.read();
+                size_t index 		= 0;
+                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,		// srcid
+                				0,		// trdid
+                				0,		// pktid
+                				r_xram_rsp_victim_nline.read(),
+                				count_copies,
+                				index);
+                r_xram_rsp_upt_index = index;
+
+                if (!wok) 
+                {
+                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST state" << std::endl;
+                    std::cout << "an update_tab entry was free but write is unsuccessful" << std::endl;
+                    exit(0);
+                }
+            }
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_DIR_UPDT> Directory update: "
+              << " way = " << std::dec << way 
+              << " / set = " << set 
+              << " / count = " << entry.count
+              << " / is_cnt = " << entry.is_cnt << std::endl;
+    if (r_xram_rsp_victim_inval.read())
+    std::cout << "                           Invalidation request for victim line "
+              << std::hex << r_xram_rsp_victim_nline.read()
+              << " / broadcast = " << r_xram_rsp_victim_is_cnt.read() << std::endl;
+}
+#endif
+
+            // If the victim is not dirty, we don't need another XRAM  put transaction,
+            // and we canwe erase the TRT entry 
+            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 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) );
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_TRT_DIRTY> Set TRT entry for the put transaction:"
+	      << " dirty victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
+}
+#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:     // Request a response to TGT_RSP FSM
+        {
+            if ( !r_xram_rsp_to_tgt_rsp_req.read() ) 
+            {
+                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_rerror = false;
+                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;
+
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_DIR_RSP> Request the TGT_RSP FSM to return data:" 
+              << " rsrcid = " << std::hex << r_xram_rsp_trt_buf.srcid
+              << " / address = " << r_xram_rsp_trt_buf.nline*m_words*4
+              << " / nwords = " << std::dec << r_xram_rsp_trt_buf.read_length << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        ////////////////////
+        case XRAM_RSP_INVAL:	// send invalidate request to INIT_CMD FSM
+        {
+            if(   !r_xram_rsp_to_init_cmd_multi_req.read() && 
+                  !r_xram_rsp_to_init_cmd_brdcast_req.read() ) 
+            {	      
+                bool multi_req = !r_xram_rsp_victim_is_cnt.read();
+                bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
+                bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
+
+                r_xram_rsp_to_init_cmd_multi_req    = last_multi_req; 
+                r_xram_rsp_to_init_cmd_brdcast_req  = 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;
+                xram_rsp_to_init_cmd_fifo_srcid     = r_xram_rsp_victim_copy.read();
+                xram_rsp_to_init_cmd_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
+#if L1_MULTI_CACHE
+                xram_rsp_to_init_cmd_fifo_cache_id  = r_xram_rsp_victim_copy_cache.read();
+#endif
+                xram_rsp_to_init_cmd_fifo_put       = multi_req;
+                r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
+
+                if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+                else if (not_last_multi_req)    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+                else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_INVAL> Send an inval request to INIT_CMD FSM:" 
+              << " victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
 }
 #endif
@@ -2089,409 +2943,154 @@
           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_copy      = victim.owner.srcid;
+        //////////////////////////
+        case XRAM_RSP_WRITE_DIRTY:	// send a write request to IXR_CMD FSM
+        {
+            if ( !r_xram_rsp_to_ixr_cmd_req.read() ) 
+            {
+                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++;
+
+                bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
+                bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
+                if ( not_last_multi_req )   r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+                else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_WRITE_DIRTY> Send the put request to IXR_CMD FSM:" 
+              << " victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////////////////
+        case XRAM_RSP_HEAP_ERASE:	// erase the list of copies and sent invalidations
+        {
+            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP ) 
+            {
+                HeapEntry entry = m_heap.read(r_xram_rsp_next_ptr.read());
+
+                xram_rsp_to_init_cmd_fifo_srcid    = entry.owner.srcid;
 #if L1_MULTI_CACHE
-            r_xram_rsp_victim_copy_cache= victim.owner.cache_id;
-#endif
-            r_xram_rsp_victim_copy_inst = victim.owner.inst;
-            r_xram_rsp_victim_count     = victim.count;
-            r_xram_rsp_victim_ptr       = victim.ptr;
-            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;
-
-            if(!trt_entry.rerror)
-              r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
-            else
-              r_xram_rsp_fsm = XRAM_RSP_ERROR_ERASE;      
-#ifdef TDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << "XRAM_RSP FSM in XRAM_RSP_TRT_COPY state" << std::endl;
-	std::cout << "Victim way : " << std::hex << way << " set " << set << std::dec << std::endl;
-	victim.print();
-}
-#endif
-          }
-          break;
-        }
-        ///////////////////////
-      case XRAM_RSP_INVAL_LOCK:
-        {
-          if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP ) {
-#ifdef IDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
-    std::cout << "A invalidation is already registered at this address" << std::endl;
-	m_update_tab.print();
-}
-#endif
-
-            }
-	    else if(m_update_tab.is_full() && r_xram_rsp_victim_inval.read()){
-	      r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
-#ifdef IDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
-    std::cout << "The inval tab is full" << std::endl;
-	m_update_tab.print();
-}
-#endif
-	    }
-            else {
-              r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
-#ifdef IDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_DIR_UPDT state" << std::endl;
-	m_update_tab.print();
-}
-#endif
-            }
-          }
-          break;
-        }
-        ///////////////////////
-      case XRAM_RSP_INVAL_WAIT:
-        {
-          r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
-          break;
-#ifdef IDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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 ;
-          // 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    = false;
-          entry.lock	  = false;
-          entry.dirty	  = dirty;
-          entry.tag	      = r_xram_rsp_trt_buf.nline / m_sets;
-          entry.ptr       = 0;
-          if(cached_read) {
-              entry.owner.srcid   = r_xram_rsp_trt_buf.srcid;
+                xram_rsp_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
+#endif
+                xram_rsp_to_init_cmd_fifo_inst  = entry.owner.inst;
+                xram_rsp_to_init_cmd_fifo_put   = true;
+                if( m_xram_rsp_to_init_cmd_inst_fifo.wok() )
+                {
+                    r_xram_rsp_next_ptr = entry.next;
+                    if( entry.next == r_xram_rsp_next_ptr.read() ) // last copy
+                    {
+                        r_xram_rsp_to_init_cmd_multi_req = true;
+                        r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
+                    } 
+                    else 
+                    {
+                        r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+                    }
+                } 
+                else 
+                {
+                    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+                }
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_HEAP_ERASE> Erase the list of copies:" 
+              << " srcid = " << entry.owner.srcid
+              << " / inst = " << entry.owner.inst << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////////////////
+        case XRAM_RSP_HEAP_LAST:	// last member of the list
+        {
+            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_XRAM_RSP )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST state" << std::endl;
+                std::cout << "bad HEAP allocation" << std::endl;
+                exit(0);
+            }
+            size_t free_pointer = m_heap.next_free_ptr();
+
+            HeapEntry last_entry;
+            last_entry.owner.srcid    = 0;
 #if L1_MULTI_CACHE
-              entry.owner.cache_id= r_xram_rsp_trt_buf.pktid;
-#endif
-              entry.owner.inst    = inst_read;
-              entry.count         = 1;
-          } else {
-            entry.owner.srcid    = 0;
-#if L1_MULTI_CACHE
-            entry.owner.cache_id = 0;
-#endif
-            entry.owner.inst     = 0;
-            entry.count          = 0;
-          }
-          m_cache_directory.write(set, way, entry);
-#ifdef DDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	   std::cout << "printing the entry : " << std::endl;
-	   entry.print();
-	   std::cout << "done" << std::endl;
-}
-#endif
-
-#ifdef TDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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 = 0;
-            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,//srcid
-                0,//trdid
-                0,//pktid
-                r_xram_rsp_victim_nline.read(),
-                count_copies,
-                index);
-
-#ifdef IDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-            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;
+            last_entry.owner.cache_id = 0;
+#endif
+            last_entry.owner.inst     = false;
+            if(m_heap.is_full())
+            {
+                last_entry.next     = r_xram_rsp_next_ptr.read();
+                m_heap.unset_full();
+            } 
+            else 
+            {
+                last_entry.next     = free_pointer;
+            }
+
+            m_heap.write_free_ptr(r_xram_rsp_victim_ptr.read());
+            m_heap.write(r_xram_rsp_next_ptr.read(),last_entry);
+
+            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_HEAP_LAST> Heap housekeeping" << std::endl;
+}
+#endif
+            break;
+        }
+        // ///////////////////////
+        case XRAM_RSP_ERROR_ERASE:	// erase TRT entry in case of error
+        {
+            m_transaction_tab.erase(r_xram_rsp_trt_index.read());
+
+            // Next state
+            if ( r_xram_rsp_trt_buf.proc_read  ) r_xram_rsp_fsm = XRAM_RSP_ERROR_RSP;
+            else                                 r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_ERROR_ERASE> Error reported by XRAM / erase the TRT entry" << std::endl;
+}
+#endif
+            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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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.read() ) {
-            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_rerror = false;
-            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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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_multi_req.read() && 
-                !r_xram_rsp_to_init_cmd_brdcast_req.read() ) {	      
-            
-            bool multi_req = !r_xram_rsp_victim_is_cnt.read();
-            bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
-            bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
-
-            r_xram_rsp_to_init_cmd_multi_req    = last_multi_req; 
-            r_xram_rsp_to_init_cmd_brdcast_req  = 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;
-            xram_rsp_to_init_cmd_fifo_srcid     = r_xram_rsp_victim_copy.read();
-            xram_rsp_to_init_cmd_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
-#if L1_MULTI_CACHE
-            xram_rsp_to_init_cmd_fifo_cache_id  = r_xram_rsp_victim_copy_cache.read();
-#endif
-            xram_rsp_to_init_cmd_fifo_put       = multi_req;
-            
-            r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
-
-            if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
-            else if (not_last_multi_req)    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
-            else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
-#ifdef IDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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.read() ) {
-            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++;
-            bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
-            bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
-            if ( not_last_multi_req )   r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
-            else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
-#ifdef TDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << "XRAM_RSP FSM in XRAM_RSP_WRITE_DIRTY state" << std::endl;
-}
-#endif
-          }
-          break;
-        }
-        //////////////////////////
-      case XRAM_RSP_HEAP_ERASE:	// erase the list of copies and sent invalidations
-        {
-          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP ) {
-            HeapEntry entry = m_heap_directory.read(r_xram_rsp_next_ptr.read());
-            xram_rsp_to_init_cmd_fifo_srcid    = entry.owner.srcid;
-#if L1_MULTI_CACHE
-            xram_rsp_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
-#endif
-            xram_rsp_to_init_cmd_fifo_inst  = entry.owner.inst;
-            xram_rsp_to_init_cmd_fifo_put   = true;
-            if( m_xram_rsp_to_init_cmd_inst_fifo.wok() ){
-              r_xram_rsp_next_ptr = entry.next;
-              if( entry.next == r_xram_rsp_next_ptr.read() ){ // last copy
-                r_xram_rsp_to_init_cmd_multi_req = true;
-                r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
-              } else {
-                r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
-              }
-            } else {
-              r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
-            }
-          }
-          break;
-        }
-        //////////////////////////
-      case XRAM_RSP_HEAP_LAST:	// last member of the list
-        {
-          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP)
-                 ,"MemCache ERROR : bad HEAP allocation");
-          size_t free_pointer = m_heap_directory.next_free_ptr();
-
-          HeapEntry last_entry;
-          last_entry.owner.srcid    = 0;
-#if L1_MULTI_CACHE
-          last_entry.owner.cache_id = 0;
-#endif
-          last_entry.owner.inst     = false;
-          if(m_heap_directory.is_full()){
-            last_entry.next     = r_xram_rsp_next_ptr.read();
-            m_heap_directory.unset_full();
-          } else {
-            last_entry.next     = free_pointer;
-          }
-
-          m_heap_directory.write_free_ptr(r_xram_rsp_victim_ptr.read());
-          m_heap_directory.write(r_xram_rsp_next_ptr.read(),last_entry);
-
-          r_xram_rsp_fsm = XRAM_RSP_IDLE;
-
-          break;
-        }
-        ///////////////////////
-      case XRAM_RSP_ERROR_ERASE:		// erase xram transaction
-        {
-
-#ifdef TDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_ERROR_ERASE transaction table : " << std::endl;
-	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
-	  m_transaction_tab.print(i);
-}
-#endif
-
-          m_transaction_tab.erase(r_xram_rsp_trt_index.read());
-
-          // Next state
-          if ( r_xram_rsp_trt_buf.proc_read  ) r_xram_rsp_fsm = XRAM_RSP_ERROR_RSP;
-          else                                 r_xram_rsp_fsm = XRAM_RSP_IDLE;
-          break;
-        }
-        //////////////////////
-      case XRAM_RSP_ERROR_RSP:     // send a request to TGT_RSP FSM in case of read
-        {
-          if ( !r_xram_rsp_to_tgt_rsp_req.read() ) {
-            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_rerror = true;
-            r_xram_rsp_to_tgt_rsp_req    = true;
-
-            r_xram_rsp_fsm = XRAM_RSP_IDLE;
-
-#ifdef DDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_RSP state" << std::endl;
-}
-#endif
-          }
-          break;
+        case XRAM_RSP_ERROR_RSP:     // Request an error response to TGT_RSP FSM 
+        {
+            if ( !r_xram_rsp_to_tgt_rsp_req.read() ) 
+            {
+                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_rerror = true;
+                r_xram_rsp_to_tgt_rsp_req    = true;
+
+                r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#if DEBUG_MEMC_XRAM_RSP
+if( m_debug_xram_rsp_fsm )
+{
+    std::cout << "  <MEMC.XRAM_RSP_ERROR_RSP> Request a response error to TGT_RSP FSM:"
+              << " srcid = " << r_xram_rsp_trt_buf.srcid << std::endl;
+}
+#endif
+            }
+            break;
         }
     } // end swich r_xram_rsp_fsm
@@ -2501,922 +3100,1219 @@
     ////////////////////////////////////////////////////////////////////////////////////
     // The CLEANUP FSM handles the cleanup request from L1 caches.
-    // It accesses the cache directory to update the list of copies.
-    //
+    // It accesses the cache directory and the heap 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 a cleanup request : received SRCID is larger than the number of initiators");
-
-            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;
-              }
-            }
-            // only write request to a mapped address that are not broadcast are handled
-            if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
-                 ((p_vci_tgt_cleanup.address.read() & 0x3) == 0) &&
-                 reached) 
-            {
-              PRINTF("  * <MEM_CACHE.CLEANUP> Request from %d.%d at address %llx\n",(uint32_t)p_vci_tgt_cleanup.srcid.read(),(uint32_t)p_vci_tgt_cleanup.pktid.read(),(uint64_t)p_vci_tgt_cleanup.address.read());
-
-              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;
+
+
+    switch ( r_cleanup_fsm.read() ) 
+    {
+        //////////////////
+        case CLEANUP_IDLE:
+        {
+            if ( p_vci_tgt_cleanup.cmdval.read() ) 
+            {
+                if (p_vci_tgt_cleanup.srcid.read() >= m_initiators )
+                {
+                    std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                              << " CLEANUP_IDLE state" << std::endl;
+                    std::cout << "illegal srcid for  cleanup request" << std::endl;
+                    exit(0);
+                }
+
+                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;
+                }
+                // only write request to a mapped address that are not broadcast are handled
+                if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
+                     ((p_vci_tgt_cleanup.address.read() & 0x3) == 0) && reached) 
+                {
+                    addr_t line = (addr_t)(m_nline[(vci_addr_t)(p_vci_tgt_cleanup.address.read())]);
+
+                    r_cleanup_nline = line;
+                    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;
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_IDLE> Cleanup request:" << std::hex
+              << " line = " << line * m_words * 4
+              << " / owner_id = " << p_vci_tgt_cleanup.srcid.read() 
+              << " / owner_ins = " << (p_vci_tgt_cleanup.trdid.read()&0x1)
+              << std::endl;
+}
+#endif
+                    m_cpt_cleanup++;
+                }
+            }
+            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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	   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_copy      = entry.owner.srcid;
+        case CLEANUP_DIR_LOCK:	// test directory status
+        {
+            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);
+                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_copy         = entry.owner.srcid;
 #if L1_MULTI_CACHE
-            r_cleanup_copy_cache= entry.owner.cache_id;
-#endif
-            r_cleanup_copy_inst = entry.owner.inst;
-            r_cleanup_count     = entry.count;
-            r_cleanup_ptr       = entry.ptr;
-
-            // In case of hit, the copy must be cleaned in the copies bit-vector
-            if( entry.valid){
-              if ( (entry.count==1) || (entry.is_cnt) )  { // no access to the heap
-                r_cleanup_fsm = CLEANUP_DIR_WRITE;
-              } else {
-                r_cleanup_fsm = CLEANUP_HEAP_LOCK;
-              }
-            } else {
-              r_cleanup_fsm = CLEANUP_UPT_LOCK;
-            }
-          }
-          break;
+                r_cleanup_copy_cache= entry.owner.cache_id;
+#endif
+                r_cleanup_copy_inst    = entry.owner.inst;
+                r_cleanup_count        = entry.count;
+                r_cleanup_ptr          = entry.ptr;
+
+                if( entry.valid) //  hit : the copy must be cleared  
+                {
+                    if ( (entry.count==1) || (entry.is_cnt) )  // no access to the heap
+                    {
+                        r_cleanup_fsm = CLEANUP_DIR_WRITE;
+                    } 
+                    else 					// access to the heap
+                    {
+                        r_cleanup_fsm = CLEANUP_HEAP_LOCK;
+                    }
+                } 
+                else 		// miss : we must check the update table
+                {
+                    r_cleanup_fsm = CLEANUP_UPT_LOCK;
+                }
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_DIR_LOCK> Test directory status: " << std::hex
+              << " line = " << r_cleanup_nline.read() * m_words * 4
+              << " / hit = " << entry.valid
+              << " / dir_id = " << entry.owner.srcid
+              << " / dir_ins = " << entry.owner.inst
+              << " / search_id = " << r_cleanup_srcid.read() 
+              << " / search_ins = " << (r_cleanup_trdid.read()&0x1)
+              << " / count = " << entry.count
+              << " / is_cnt = " << entry.is_cnt << std::endl;
+}
+#endif
+            }
+            break;
         }
         ///////////////////////
-      case CLEANUP_DIR_WRITE:
-        {
-          ASSERT((r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP)
-                 ,"MemCache ERROR : Bad DIR allocation");
-          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; 
-          bool match_srcid   = ((r_cleanup_copy.read() == r_cleanup_srcid.read())
+        case CLEANUP_DIR_WRITE:  //  update the directory entry without heap access
+        {
+            if ( r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                          << " CLEANUP_DIR_WRITE state" 
+                          << " bad DIR allocation" << std::endl;
+                exit(0);
+            }
+
+            size_t way         = r_cleanup_way.read();
+            size_t set         = m_y[(vci_addr_t)(r_cleanup_nline.read()*m_words*4)];
+            bool cleanup_inst  = r_cleanup_trdid.read() & 0x1; 
+            bool match_srcid   = ((r_cleanup_copy.read() == r_cleanup_srcid.read())
 #if L1_MULTI_CACHE
                                 and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read())
 #endif
                                 );
-          bool match_inst    = (r_cleanup_copy_inst.read()  == cleanup_inst);
-          bool match         = match_srcid && match_inst;
-
-          // 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();
-          entry.ptr     = r_cleanup_ptr.read();
-          if(r_cleanup_is_cnt.read()) { // Directory is a counter
-            entry.count  = r_cleanup_count.read() -1;
-            entry.owner.srcid   = 0;
+            bool match_inst    = (r_cleanup_copy_inst.read()  == cleanup_inst);
+            bool match         = match_srcid && match_inst;
+
+            // 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();
+            entry.ptr     = r_cleanup_ptr.read();
+
+            if ( r_cleanup_is_cnt.read() )      // counter mode
+            { 
+                entry.count  = r_cleanup_count.read() -1;
+                entry.owner.srcid   = 0;
 #if L1_MULTI_CACHE
-            entry.owner.cache_id= 0;
-#endif
-            entry.owner.inst    = 0;
-            // response to the cache 
+                entry.owner.cache_id= 0;
+#endif
+                entry.owner.inst    = 0;
+                // response to the cache 
+                r_cleanup_fsm = CLEANUP_RSP;
+            }
+            else			                    // linked_list mode
+            {                       
+                if ( match )  // hit
+                {
+                    entry.count         = 0; // no more copy
+                    entry.owner.srcid   = 0;
+#if L1_MULTI_CACHE
+                    entry.owner.cache_id=0;
+#endif
+                    entry.owner.inst    = 0;
+                    r_cleanup_fsm       = CLEANUP_RSP; 
+                } 
+                else         // miss
+                { 
+                    entry.count          = r_cleanup_count.read();
+                    entry.owner.srcid    = r_cleanup_copy.read();
+#if L1_MULTI_CACHE
+                    entry.owner.cache_id = r_cleanup_copy_cache.read();
+#endif
+                    entry.owner.inst     = r_cleanup_copy_inst.read();
+                    r_cleanup_fsm        = CLEANUP_UPT_LOCK;
+                }
+            }
+            m_cache_directory.write(set, way, entry);  
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_DIR_WRITE> Update directory:" << std::hex
+              << " line = " << r_cleanup_nline.read() * m_words * 4
+              << " / dir_id = " << entry.owner.srcid
+              << " / dir_ins = " << entry.owner.inst
+              << " / count = " << entry.count
+              << " / is_cnt = " << entry.is_cnt << std::endl;
+}
+#endif
+
+            break;
+        }
+        ///////////////////////
+        case CLEANUP_HEAP_LOCK:	 // two cases are handled in this state:
+                                 // - the matching copy is directly in the directory
+                                 // - the matching copy is the first copy in the heap
+        {
+            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP )
+            {
+                size_t way              = r_cleanup_way.read();
+                size_t set              = m_y[(vci_addr_t)(r_cleanup_nline.read()*m_words*4)];
+                HeapEntry heap_entry    = m_heap.read(r_cleanup_ptr.read());
+                bool last               = (heap_entry.next == r_cleanup_ptr.read());
+                bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
+
+                // match_dir computation
+                bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
+                bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
+                bool match_dir          = match_dir_srcid and match_dir_inst;
+#if L1_MULTI_CACHE
+                match_dir = match_dir and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
+#endif
+
+                // match_heap computation
+                bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+                bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
+                bool match_heap         = match_heap_srcid and match_heap_inst;
+#if L1_MULTI_CACHE
+                match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
+#endif
+
+                r_cleanup_prev_ptr      = r_cleanup_ptr.read();
+                r_cleanup_prev_srcid    = heap_entry.owner.srcid;
+#if L1_MULTI_CACHE
+                r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
+#endif
+                r_cleanup_prev_inst     = heap_entry.owner.inst;
+
+                if (match_dir) // the matching copy is registered in the directory 
+                {       
+                    // the copy registered in the directory must be replaced 
+                    // by the first copy registered in the heap 
+                    // and the corresponding entry must be freed
+                    DirectoryEntry dir_entry;
+                    dir_entry.valid	        = true;
+                    dir_entry.is_cnt        = r_cleanup_is_cnt.read();
+                    dir_entry.dirty	        = r_cleanup_dirty.read();
+                    dir_entry.tag	        = r_cleanup_tag.read();
+                    dir_entry.lock	        = r_cleanup_lock.read();
+                    dir_entry.ptr           = heap_entry.next;
+                    dir_entry.count         = r_cleanup_count.read()-1;
+                    dir_entry.owner.srcid   = heap_entry.owner.srcid;
+#if L1_MULTI_CACHE
+                    dir_entry.owner.cache_id = heap_entry.owner.cache_id;
+#endif
+                    dir_entry.owner.inst    = heap_entry.owner.inst;
+                    m_cache_directory.write(set,way,dir_entry);
+                    r_cleanup_next_ptr      = r_cleanup_ptr.read();
+                    r_cleanup_fsm           = CLEANUP_HEAP_FREE;
+                }
+                else if (match_heap) // the matching copy is the first copy in the heap
+                {
+                    // The first copy in heap must be freed
+                    // and the copy registered in directory must point to the next copy in heap
+                    DirectoryEntry dir_entry;
+                    dir_entry.valid	        = true;
+                    dir_entry.is_cnt        = r_cleanup_is_cnt.read();
+                    dir_entry.dirty	        = r_cleanup_dirty.read();
+                    dir_entry.tag	        = r_cleanup_tag.read();
+                    dir_entry.lock	        = r_cleanup_lock.read();
+                    dir_entry.ptr           = heap_entry.next;
+                    dir_entry.count         = r_cleanup_count.read()-1;
+                    dir_entry.owner.srcid   = r_cleanup_copy.read();
+#if L1_MULTI_CACHE
+                    dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
+#endif
+                    dir_entry.owner.inst    = r_cleanup_copy_inst.read();
+                    m_cache_directory.write(set,way,dir_entry);
+                    r_cleanup_next_ptr      = r_cleanup_ptr.read();
+                    r_cleanup_fsm           = CLEANUP_HEAP_FREE;
+                }
+                else if(!last) // The matching copy is in the heap, but is not the first copy
+                {
+                    // The directory entry must be modified to decrement count
+                    DirectoryEntry  dir_entry;
+                    dir_entry.valid	      = true;
+                    dir_entry.is_cnt      = r_cleanup_is_cnt.read();
+                    dir_entry.dirty	      = r_cleanup_dirty.read();
+                    dir_entry.tag	      = r_cleanup_tag.read();
+                    dir_entry.lock        = r_cleanup_lock.read();
+                    dir_entry.ptr         = r_cleanup_ptr.read();
+                    dir_entry.count       = r_cleanup_count.read()-1;
+                    dir_entry.owner.srcid = r_cleanup_copy.read();
+#if L1_MULTI_CACHE
+                    dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
+#endif
+                    dir_entry.owner.inst     = r_cleanup_copy_inst.read();
+                    m_cache_directory.write(set,way,dir_entry);
+                    r_cleanup_next_ptr       = heap_entry.next;
+                    r_cleanup_fsm            = CLEANUP_HEAP_SEARCH;
+                } 
+                else
+                {
+                    std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                              << " CLEANUP_HEAP_LOCK state"
+                              << " hit but copy not found" << std::endl;
+                    exit(0);
+                }
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_HEAP_LOCK> Checks matching:"
+              << " line = " << r_cleanup_nline.read() * m_words * 4
+              << " / dir_id = " << r_cleanup_copy.read()
+              << " / dir_ins = " << r_cleanup_copy_inst.read()
+              << " / heap_id = " << heap_entry.owner.srcid
+              << " / heap_ins = " << heap_entry.owner.inst 
+              << " / search_id = " << r_cleanup_srcid.read() 
+              << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////////////////
+        case CLEANUP_HEAP_SEARCH:  // This state is handling the case where the copy
+                                   // is in the heap, but is not the first in the linked list
+        {
+            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                          << " CLEANUP_HEAP_SEARCH state" 
+                          << " bad HEAP allocation" << std::endl;
+                exit(0);
+            }
+
+            HeapEntry heap_entry  = m_heap.read(r_cleanup_next_ptr.read());
+            bool last             = (heap_entry.next == r_cleanup_next_ptr.read());
+            bool cleanup_inst     = r_cleanup_trdid.read() & 0x1; 
+            bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+            bool match_heap_inst  = (heap_entry.owner.inst  == cleanup_inst);
+            bool match_heap       = match_heap_srcid && match_heap_inst;
+#if L1_MULTI_CACHE
+            match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
+#endif
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_HEAP_SEARCH> Cheks matching:"
+              << " line = " << r_cleanup_nline.read() * m_words * 4
+              << " / heap_id = " << heap_entry.owner.srcid
+              << " / heap_ins = " << heap_entry.owner.inst
+              << " / search_id = " << r_cleanup_srcid.read()
+              << " / search_ins = " << (r_cleanup_trdid.read()&0x1) 
+              << " / last = " << last << std::endl;
+}
+#endif
+            if(match_heap) // the matching copy must be removed
+            {
+                r_cleanup_ptr = heap_entry.next; // reuse ressources
+                r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
+            }
+            else
+            {
+                if ( last ) 
+                {
+                    std::cout << "VCI_MEM_CACHE_ERROR " << name() 
+                              << " CLEANUP_HEAP_SEARCH state" 
+                              << " cleanup hit but copy not found" << std::endl;
+                    exit(0);
+                } 
+                else // test the next in the linked list
+                {
+                    r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
+                    r_cleanup_prev_srcid    = heap_entry.owner.srcid;
+#if L1_MULTI_CACHE
+                    r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
+#endif
+                    r_cleanup_prev_inst     = heap_entry.owner.inst;
+                    r_cleanup_next_ptr      = heap_entry.next;
+                    r_cleanup_fsm           = CLEANUP_HEAP_SEARCH;
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_HEAP_SEARCH> Matching copy not found, search next:"
+              << " line = " << r_cleanup_nline.read() * m_words * 4
+              << " / heap_id = " << heap_entry.owner.srcid
+              << " / heap_ins = " << heap_entry.owner.inst
+              << " / search_id = " << r_cleanup_srcid.read()
+              << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
+}
+#endif
+                }
+            }
+            break;
+        }
+        ////////////////////////
+        case CLEANUP_HEAP_CLEAN:  // remove a copy in the linked list
+        {
+            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() 
+                          << " CLEANUP_HEAP_CLEAN state"
+                          << "Bad HEAP allocation" << std::endl;
+                exit(0);
+            }
+
+            bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
+            HeapEntry heap_entry; 
+            heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
+#if L1_MULTI_CACHE
+            heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
+#endif
+            heap_entry.owner.inst     = r_cleanup_prev_inst.read();
+            if(last) // this is the last entry of the list of copies
+            {
+                heap_entry.next     = r_cleanup_prev_ptr.read();
+            } 
+            else  // this is not the last entry
+            {
+                heap_entry.next     = r_cleanup_ptr.read();
+            }
+            m_heap.write(r_cleanup_prev_ptr.read(),heap_entry);
+            r_cleanup_fsm = CLEANUP_HEAP_FREE;
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_HEAP_SEARCH> Remove the copy in the linked list" << std::endl;
+}
+#endif
+            break;
+        }
+        ///////////////////////
+        case CLEANUP_HEAP_FREE:  // The heap entry pointed by r_cleanup_next_ptr is freed
+                                 // and becomes the head of the list of free entries
+        {
+            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
+            {
+                std::cout << "VCI_MEM_CACHE ERROR " << name() << " CLEANUP_HEAP_CLEAN state" << std::endl;
+                std::cout << "Bad HEAP allocation" << std::endl;
+                exit(0);
+            }
+
+            HeapEntry heap_entry;
+            heap_entry.owner.srcid    = 0;
+#if L1_MULTI_CACHE
+            heap_entry.owner.cache_id = 0;
+#endif
+            heap_entry.owner.inst     = false;
+
+            if(m_heap.is_full()) heap_entry.next     = r_cleanup_next_ptr.read();
+            else                           heap_entry.next     = m_heap.next_free_ptr();
+            m_heap.write(r_cleanup_next_ptr.read(),heap_entry);
+            m_heap.write_free_ptr(r_cleanup_next_ptr.read());
+            m_heap.unset_full();
             r_cleanup_fsm = CLEANUP_RSP;
-          }
-          else{                         // Directory is a list
-            if(match) { // hit
-              entry.count         = 0; // no more copy
-              entry.owner.srcid   = 0;
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_HEAP_SEARCH> Update the list of free entries" << std::endl;
+}
+#endif
+            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 ) // no pending inval
+                {
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_UPT_LOCK> Unexpected cleanup with no corresponding UPT entry:"
+              << " address = " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::endl;
+}
+#endif
+                    r_cleanup_fsm = CLEANUP_RSP;
+                } 
+                else		// pending inval 
+                {
+                    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:  // decrement response counter
+        {
+            size_t count = 0;
+            m_update_tab.decrement(r_cleanup_index.read(), count);
+            if ( count == 0 )
+            {
+                m_update_tab.clear(r_cleanup_index.read());
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_UPT_WRITE> Decrement response counter in UPT:"
+              << " UPT_index = " << r_cleanup_index.read()
+              << " rsp_count = " << count << std::endl;
+}
+#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:	// Response to a previous write on the direct network
+        {
+            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;
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_WRITE_RSP> Send a response to a cleanup request:"
+              << " rsrcid = " << r_cleanup_write_srcid.read()
+              << " / rtrdid = " << r_cleanup_write_trdid.read() << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////////
+        case CLEANUP_RSP:	// Response to a cleanup on the coherence network
+        {
+            if ( p_vci_tgt_cleanup.rspack.read() ) 
+            {
+                r_cleanup_fsm = CLEANUP_IDLE;
+
+#if DEBUG_MEMC_CLEANUP
+if( m_debug_cleanup_fsm )
+{
+    std::cout << "  <MEMC.CLEANUP_RSP> Send the response to a cleanup request:"
+              << " rsrcid = " << r_cleanup_write_srcid.read()
+              << " / rtrdid = " << r_cleanup_write_trdid.read() << std::endl;
+}
+#endif
+            }
+            break;
+        }
+    } // end switch cleanup fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		SC FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The SC FSM handles the SC (Store Conditionnal) atomic commands, 
+    // that are handled as "compare-and-swap instructions.
+    // 
+    // This command contains two or four flits: 
+    // - In case of 32 bits atomic access, the first flit contains the value read
+    // by a previous LL instruction, the second flit contains the value to be writen.
+    // - In case of 64 bits atomic access, the 2 first flits contains the value read
+    // by a previous LL instruction, the 2 next flits contains the value to be writen.
+    // 
+    // The target address is cachable. If it is replicated in other L1 caches
+    // than the writer, a coherence operation is done.
+    // 
+    // It access the directory to check hit / miss.
+    // - In case of miss, the SC FSM must register a GET transaction in TRT.
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it goes to the WAIT state
+    // to release the locks and try again. When the GET transaction has been
+    // launched, it goes to the WAIT state and try again.
+    // The SC request is not consumed in the FIFO until a HIT is obtained.
+    // - In case of hit...
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_sc_fsm.read() ) 
+    {
+        /////////////
+        case SC_IDLE:	    // fill the local rdata buffers
+        {
+            if( m_cmd_sc_addr_fifo.rok() ) 
+            {
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_IDLE> SC command: " << std::hex
+              << " srcid = " <<  m_cmd_sc_srcid_fifo.read() 
+              << " addr = " <<  m_cmd_sc_addr_fifo.read() 
+              << " wdata = " << m_cmd_sc_wdata_fifo.read()
+              << " eop = " << m_cmd_sc_eop_fifo.read()
+              << " cpt  = " << std::dec << r_sc_cpt.read() << std::endl;
+}
+#endif
+                if( m_cmd_sc_eop_fifo.read() )
+                {
+                    m_cpt_sc++;
+                    r_sc_fsm = SC_DIR_LOCK;
+                } 
+                else  // we keep the last word in the FIFO
+                {
+                    cmd_sc_fifo_get = true;
+                }
+                // We fill the two buffers
+                if ( r_sc_cpt.read() < 2 ) // 32 bits access
+                    r_sc_rdata[r_sc_cpt.read()] = m_cmd_sc_wdata_fifo.read();
+
+                if((r_sc_cpt.read() == 1) && m_cmd_sc_eop_fifo.read())
+                    r_sc_wdata = m_cmd_sc_wdata_fifo.read();
+
+                if( r_sc_cpt.read()>3 ) // more than 4 flits...
+                {
+                    std::cout << "VCI_MEM_CACHE ERROR in SC_IDLE state : illegal SC command" 
+                              << std::endl;
+                    exit(0);
+                }
+
+                if ( r_sc_cpt.read()==2 )
+                    r_sc_wdata = m_cmd_sc_wdata_fifo.read();
+
+                r_sc_cpt = r_sc_cpt.read()+1;
+            }	
+            break;
+        }
+        /////////////////
+        case SC_DIR_LOCK:  // Read the directory
+        {
+            if( r_alloc_dir_fsm.read() == ALLOC_DIR_SC ) 
+            {
+                size_t way = 0;
+                DirectoryEntry entry(m_cache_directory.read(m_cmd_sc_addr_fifo.read(), way));
+
+                r_sc_is_cnt     = entry.is_cnt;
+                r_sc_dirty      = entry.dirty;
+                r_sc_tag        = entry.tag;
+                r_sc_way        = way;
+                r_sc_copy       = entry.owner.srcid;
 #if L1_MULTI_CACHE
-              entry.owner.cache_id=0;
-#endif
-              entry.owner.inst    = 0;
-              r_cleanup_fsm       = CLEANUP_RSP; 
-            } else { // miss
-              entry.count          = r_cleanup_count.read();
-              entry.owner.srcid    = r_cleanup_copy.read();
+                r_sc_copy_cache = entry.owner.cache_id;
+#endif
+                r_sc_copy_inst  = entry.owner.inst;
+                r_sc_ptr        = entry.ptr;
+                r_sc_count      = entry.count;
+
+                if ( entry.valid ) 	r_sc_fsm = SC_DIR_HIT_READ; 
+                else 			r_sc_fsm = SC_TRT_GET_LOCK;
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_DIR_LOCK> Directory acces"
+              << " / address = " << m_cmd_sc_addr_fifo.read()
+              << " / hit = " << entry.valid 
+              << " / count = " << entry.count
+              << " / is_cnt = " << entry.is_cnt << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////////////
+        case SC_DIR_HIT_READ:  // update directory for lock and dirty bit
+                               // and check data change in cache
+        {
+            size_t way	= r_sc_way.read();
+            size_t set	= m_y[(vci_addr_t)(m_cmd_sc_addr_fifo.read())]; 
+            size_t word	= m_x[(vci_addr_t)(m_cmd_sc_addr_fifo.read())]; 
+
+            // update directory (lock & dirty bits)
+            DirectoryEntry entry;
+            entry.valid	         = true;
+            entry.is_cnt         = r_sc_is_cnt.read();
+            entry.dirty	         = true;
+            entry.lock	         = true;
+            entry.tag	         = r_sc_tag.read();
+            entry.owner.srcid    = r_sc_copy.read();
 #if L1_MULTI_CACHE
-              entry.owner.cache_id = r_cleanup_copy_cache.read();
-#endif
-              entry.owner.inst     = r_cleanup_copy_inst.read();
-              r_cleanup_fsm        = CLEANUP_UPT_LOCK;
-            }
-          }
-          m_cache_directory.write(set, way, entry);  
-
-          break;
+            entry.owner.cache_id = r_sc_copy_cache.read();
+#endif
+            entry.owner.inst     = r_sc_copy_inst.read();
+            entry.count          = r_sc_count.read();
+            entry.ptr            = r_sc_ptr.read();
+
+            m_cache_directory.write(set, way, entry);
+
+            // read data in cache & check data change
+            bool ok = ( r_sc_rdata[0].read() == m_cache_data[way][set][word] );
+            if ( r_sc_cpt.read()==4 )  // 64 bits SC
+                ok &= ( r_sc_rdata[1] == m_cache_data[way][set][word+1] );
+
+            // to avoid livelock, force the atomic access to fail pseudo-randomly 
+            bool forced_fail = ( (r_sc_lfsr % (64) == 0) && RANDOMIZE_SC );
+            r_sc_lfsr = (r_sc_lfsr >> 1) ^ ((-(r_sc_lfsr & 1)) & 0xd0000001);
+
+            if( ok and not forced_fail )	// no data change
+            {
+                r_sc_fsm = SC_DIR_HIT_WRITE;
+            }
+            else                            // return failure
+            {
+                r_sc_fsm = SC_RSP_FAIL;
+            } 
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_DIR_HIT_READ> Test if SC success:" 
+              << " / expected value = " << r_sc_rdata[0].read()
+              << " / actual value = " << m_cache_data[way][set][word]
+              << " / forced_fail = " << forced_fail << std::endl;
+}
+#endif
+            break;
+        }
+        ///// ////////////////
+        case SC_DIR_HIT_WRITE: 		// write data in the cache
+                                    // and test if a coherence request is required
+        {
+            size_t way	= r_sc_way.read();
+            size_t set	= m_y[(vci_addr_t)(m_cmd_sc_addr_fifo.read())]; 
+            size_t word	= m_x[(vci_addr_t)(m_cmd_sc_addr_fifo.read())]; 
+
+            // cache update
+            m_cache_data[way][set][word] = r_sc_wdata.read();
+            if(r_sc_cpt.read()==4)
+                m_cache_data[way][set][word+1] = m_cmd_sc_wdata_fifo.read();
+          
+            // test coherence request
+            if(r_sc_count.read())   // replicated line 
+            {
+                if ( r_sc_is_cnt.read() )
+                {
+                    r_sc_fsm = SC_TRT_PUT_LOCK; 		// broadcast invalidate required
+                }
+                else if( !r_sc_to_init_cmd_multi_req.read() && 
+                         !r_sc_to_init_cmd_brdcast_req.read()  )
+                {
+                    r_sc_fsm = SC_UPT_LOCK;			// multi update required
+                }
+                else
+                {
+                    r_sc_fsm = SC_WAIT;
+                }
+            } 
+            else                    // no copies 
+            {
+                r_sc_fsm = SC_RSP_SUCCESS;
+            }
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_DIR_HIT_WRITE> Update cache:" 
+              << " way = " << std::dec << way
+              << " / set = " << set
+              << " / word = " << word
+              << " / value = " << r_sc_wdata.read()
+              << " / count = " << r_sc_count.read() << std::endl;
+}
+#endif
+            break;
         }
         /////////////////
-      case CLEANUP_HEAP_LOCK:
-        {
-          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP){
-            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
-            HeapEntry heap_entry = m_heap_directory.read(r_cleanup_ptr.read());
-            bool last = (heap_entry.next == r_cleanup_ptr.read());
-            bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
-            bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
+        case SC_UPT_LOCK:  //  register the transaction in UPT
+        {
+            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_SC ) 
+            {
+                bool        wok        = false;
+                size_t      index      = 0;
+                size_t      srcid      = m_cmd_sc_srcid_fifo.read();
+                size_t      trdid      = m_cmd_sc_trdid_fifo.read();
+                size_t      pktid      = m_cmd_sc_pktid_fifo.read();
+                addr_t	    nline      = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
+                size_t      nb_copies  = r_sc_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);
+                if (wok)  // coherence transaction registered in UPT
+                {
+                    r_sc_upt_index = index;
+                    r_sc_fsm = SC_HEAP_LOCK;
+                }
+                else       //  releases the locks protecting UPT and DIR if no entry
+                {
+                    r_sc_fsm = SC_WAIT;
+                }
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_UPT_LOCK> Register multi-update transaction in UPT"  
+              << " / wok = " << wok
+              << " / nline  = " << std::hex << nline 
+              << " / count = " << nb_copies << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////
+        case SC_WAIT: 	// release all locks and retry from beginning
+        {
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_WAIT> Release all locks" << std::endl;
+}
+#endif
+            r_sc_fsm = SC_DIR_LOCK;
+            break;
+        }
+        //////////////////
+        case SC_HEAP_LOCK: 	// lock the heap
+        {
+            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_SC ) 
+            {
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_HEAP_LOCK> Get access to the heap" << std::endl;
+}
+#endif
+                r_sc_fsm = SC_UPT_REQ;
+            }
+            break;
+        }
+        ////////////////
+        case SC_UPT_REQ: 	// send a first update request to INIT_CMD FSM
+        {
+            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_SC) and
+                   "VCI_MEM_CACHE ERROR : bad HEAP allocation");
+
+            if( !r_sc_to_init_cmd_multi_req.read() && !r_sc_to_init_cmd_brdcast_req.read() )
+            {
+                r_sc_to_init_cmd_brdcast_req  = false;
+                r_sc_to_init_cmd_trdid        = r_sc_upt_index.read();
+                r_sc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
+                r_sc_to_init_cmd_index        = m_x[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
+                r_sc_to_init_cmd_wdata        = r_sc_wdata.read();
+
+                if(r_sc_cpt.read() == 4)
+                {
+                    r_sc_to_init_cmd_is_long    = true;
+                    r_sc_to_init_cmd_wdata_high = m_cmd_sc_wdata_fifo.read();
+                } 
+                else 
+                {
+                    r_sc_to_init_cmd_is_long    = false;
+                    r_sc_to_init_cmd_wdata_high = 0;
+                }
+
+                // We put the first copy in the fifo
+                sc_to_init_cmd_fifo_put     = true;
+                sc_to_init_cmd_fifo_inst    = r_sc_copy_inst.read();
+                sc_to_init_cmd_fifo_srcid   = r_sc_copy.read();
 #if L1_MULTI_CACHE
-            bool match_dir_cache_id = (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
-#endif
-            bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
-            bool match_dir          = match_dir_srcid and match_dir_cache_id and match_dir_inst;
-            bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+                sc_to_init_cmd_fifo_cache_id= r_sc_copy_cache.read();
+#endif
+                if(r_sc_count.read() == 1) // one single copy
+                {
+                    r_sc_fsm = SC_IDLE;   // Response will be sent after receiving
+                                            // update responses
+                    cmd_sc_fifo_get            = true;
+                    r_sc_to_init_cmd_multi_req = true;
+                    r_sc_cpt = 0;
+                } 
+                else			// several copies
+                {
+                    r_sc_fsm = SC_UPT_NEXT;
+                }
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_UPT_REQ> Send the first update request to INIT_CMD FSM " 
+              << " / address = " << std::hex << m_cmd_sc_addr_fifo.read()
+              << " / wdata = " << std::hex << r_sc_wdata.read()
+              << " / srcid = " << std::hex << r_sc_copy.read() 
+              << " / inst = " << r_sc_copy_inst.read() << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        /////////////////
+        case SC_UPT_NEXT:   	// send a multi-update request to INIT_CMD FSM
+        {
+            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_SC)
+                 and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
+
+            HeapEntry entry = m_heap.read(r_sc_ptr.read());
+            sc_to_init_cmd_fifo_srcid    = entry.owner.srcid;
 #if L1_MULTI_CACHE
-            bool match_heap_cache_id= (heap_entry.owner.cache_id == r_cleanup_pktid.read());
-#endif
-            bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
-            bool match_heap         = match_heap_srcid and match_heap_cache_id and match_heap_inst;
-
-            PRINTF("  * <MEM_CACHE.CLEANUP> %s - srcid %d\n",name().c_str(),r_cleanup_srcid.read());
-            
+            sc_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
+#endif
+            sc_to_init_cmd_fifo_inst     = entry.owner.inst;
+            sc_to_init_cmd_fifo_put = true;
+
+            if( m_sc_to_init_cmd_inst_fifo.wok() ) // request accepted by INIT_CMD FSM
+            {
+                r_sc_ptr = entry.next;
+                if( entry.next == r_sc_ptr.read() )  // last copy
+                {
+                    r_sc_to_init_cmd_multi_req = true;
+                    r_sc_fsm = SC_IDLE;   // Response will be sent after receiving
+                                            // all update responses
+                    cmd_sc_fifo_get = true;
+                    r_sc_cpt        = 0;
+                } 
+            } 
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_UPT_NEXT> Send the next update request to INIT_CMD FSM " 
+              << " / address = " << std::hex << m_cmd_sc_addr_fifo.read()
+              << " / wdata = " << std::hex << r_sc_wdata.read()
+              << " / srcid = " << std::hex << entry.owner.srcid
+              << " / inst = " << entry.owner.inst << std::endl;
+}
+#endif
+            break;
+        }
+        /////////////////////
+        case SC_TRT_PUT_LOCK:  		// check the TRT to register a PUT transaction     
+        {
+            if( r_alloc_trt_fsm.read() == ALLOC_TRT_SC ) 
+            {
+                if( !r_sc_to_ixr_cmd_req )  // we can transfer the request to IXR_CMD FSM
+                {
+                    // fill the data buffer
+                    size_t way	= r_sc_way.read();
+                    size_t set	= m_y[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
+                        size_t word = m_x[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
+                    for(size_t i = 0; i<m_words; i++)
+                    {
+                        if (i == word) 
+                        {
+                            r_sc_to_ixr_cmd_data[i] = r_sc_wdata.read();
+                        } 
+                        else if ( (i == word+1) && (r_sc_cpt.read()==4) ) // 64 bit SC
+                        {
+                            r_sc_to_ixr_cmd_data[i] = m_cmd_sc_wdata_fifo.read();
+                        } 
+                        else 
+                        {
+                            r_sc_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 )  
+                    {
+                        r_sc_trt_index = wok_index;
+                        r_sc_fsm       = SC_INVAL_LOCK; 
+                    } 
+                    else 
+                    {
+                        r_sc_fsm       = SC_WAIT;
+                    }
+                } 
+                else 
+                {
+                    r_sc_fsm = SC_WAIT;
+                }
+            }
+            break;
+        }
+        ///////////////////
+        case SC_INVAL_LOCK:  // Register a broadcast inval transaction in UPT
+        {
+            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_SC ) 
+            {
+                bool        wok       = false;
+                size_t      index     = 0;
+                size_t      srcid     = m_cmd_sc_srcid_fifo.read();
+                size_t      trdid     = m_cmd_sc_trdid_fifo.read();
+                size_t      pktid     = m_cmd_sc_pktid_fifo.read();
+                addr_t	    nline     = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
+                size_t      nb_copies = r_sc_count.read();
+
+                // register a broadcast inval transaction in UPT
+                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);
+                
+                if ( wok )	// UPT not full
+                {
+                    r_sc_upt_index = index;
+                    r_sc_fsm = SC_DIR_INVAL;
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_INVAL_LOCK> Register a broadcast inval transaction in UPT"
+              << " / nline = " << nline 
+              << " / count = " << nb_copies 
+              << " / upt_index = " << index << std::endl; 
+}
+#endif
+                }
+                else      //  releases the lock protecting UPT
+                {
+                     r_sc_fsm = SC_WAIT;
+                }
+            }
+            break;
+        }
+        //////////////////
+        case SC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
+        {
+            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_SC ) &&
+                 (r_alloc_upt_fsm.read() == ALLOC_UPT_SC ) &&
+                 (r_alloc_dir_fsm.read() == ALLOC_DIR_SC ))
+            {
+                // set TRT
+                m_transaction_tab.set(r_sc_trt_index.read(),
+                                      false,		// PUT request to XRAM
+                                      m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())],
+                                      0,
+                                      0,
+                                      0,
+                                      false,		// not a processor read
+                                      0,  		
+                                      0,
+                                      std::vector<be_t>(m_words,0),
+                                      std::vector<data_t>(m_words,0));
+
+                // invalidate directory entry
+                DirectoryEntry entry;
+                entry.valid	        = false;
+                entry.dirty	        = false;
+                entry.tag	        = 0;
+                entry.is_cnt        = false;
+                entry.lock	        = false;
+                entry.count         = 0;
+                entry.owner.srcid   = 0;
 #if L1_MULTI_CACHE
-            PRINTF("  * <MEM_CACHE.CLEANUP> match_dir  %d (match_dir_srcid  %d, match_dir_cache_id  %d, match_dir_inst  %d)\n",
-                   match_dir , match_dir_srcid , match_dir_cache_id , match_dir_inst);
-            PRINTF("  * <MEM_CACHE.CLEANUP> match_heap %d (match_heap_srcid %d, match_heap_cache_id %d, match_heap_inst %d)\n",
-                   match_heap, match_heap_srcid, match_heap_cache_id, match_heap_inst);
-#else
-            PRINTF("  * <MEM_CACHE.CLEANUP> match_dir  %d (match_dir_srcid  %d, match_dir_inst  %d)\n",
-                   match_dir , match_dir_srcid , match_dir_inst);
-            PRINTF("  * <MEM_CACHE.CLEANUP> match_heap %d (match_heap_srcid %d, match_heap_inst %d)\n",
-                   match_heap, match_heap_srcid, match_heap_inst);
-#endif
-            PRINTF("  * <MEM_CACHE.CLEANUP> last %d\n",last);
-
-            r_cleanup_prev_ptr      = r_cleanup_ptr.read();
-            r_cleanup_prev_srcid    = heap_entry.owner.srcid;
-#if L1_MULTI_CACHE
-            r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
-#endif
-
-            r_cleanup_prev_inst     = heap_entry.owner.inst;
-
-            if(match_dir){
-              DirectoryEntry dir_entry;
-              dir_entry.valid	         = true;
-              dir_entry.is_cnt         = r_cleanup_is_cnt.read();
-              dir_entry.dirty	         = r_cleanup_dirty.read();
-              dir_entry.tag	           = r_cleanup_tag.read();
-              dir_entry.lock	         = r_cleanup_lock.read();
-              dir_entry.ptr            = heap_entry.next;
-              dir_entry.count          = r_cleanup_count.read()-1;
-              dir_entry.owner.srcid    = heap_entry.owner.srcid;
-#if L1_MULTI_CACHE
-              dir_entry.owner.cache_id = heap_entry.owner.cache_id;
-#endif
-              dir_entry.owner.inst     = heap_entry.owner.inst;
-              m_cache_directory.write(set,way,dir_entry);
-              r_cleanup_next_ptr       = r_cleanup_ptr.read();
-              r_cleanup_fsm            = CLEANUP_HEAP_FREE;
-            }
-            else if(match_heap){
-              DirectoryEntry dir_entry;
-              dir_entry.valid	       = true;
-              dir_entry.is_cnt         = r_cleanup_is_cnt.read();
-              dir_entry.dirty	       = r_cleanup_dirty.read();
-              dir_entry.tag	           = r_cleanup_tag.read();
-              dir_entry.lock	       = r_cleanup_lock.read();
-              dir_entry.ptr            = heap_entry.next;
-              dir_entry.count          = r_cleanup_count.read()-1;
-              dir_entry.owner.srcid    = r_cleanup_copy.read();
-#if L1_MULTI_CACHE
-              dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
-#endif
-              dir_entry.owner.inst     = r_cleanup_copy_inst.read();
-              m_cache_directory.write(set,way,dir_entry);
-              r_cleanup_next_ptr       = r_cleanup_ptr.read();
-              r_cleanup_fsm            = CLEANUP_HEAP_FREE; 
-            }
-            else{
-              if(!last){
-                DirectoryEntry dir_entry;
-                dir_entry.valid	        = true;
-                dir_entry.is_cnt        = r_cleanup_is_cnt.read();
-                dir_entry.dirty	        = r_cleanup_dirty.read();
-                dir_entry.tag	        = r_cleanup_tag.read();
-                dir_entry.lock	        = r_cleanup_lock.read();
-                dir_entry.ptr           = r_cleanup_ptr.read();
-                dir_entry.count         = r_cleanup_count.read()-1;
-                dir_entry.owner.srcid   = r_cleanup_copy.read();
-#if L1_MULTI_CACHE
-                dir_entry.owner.cache_id= r_cleanup_copy_cache.read();
-#endif
-                dir_entry.owner.inst    = r_cleanup_copy_inst.read();
-                m_cache_directory.write(set,way,dir_entry);
-
-                r_cleanup_next_ptr = heap_entry.next;
-                r_cleanup_fsm      = CLEANUP_HEAP_SEARCH;
-
-              } else{
-                  ASSERT(false,"MemCache ERROR : CLEANUP hit but line not shared");
-              }
-            }
-          }
-          break;
+                entry.owner.cache_id= 0;
+#endif
+                entry.owner.inst    = false;
+                entry.ptr           = 0;
+                size_t set	        = m_y[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
+                size_t way	        = r_sc_way.read();
+                m_cache_directory.write(set, way, entry);
+
+                r_sc_fsm = SC_INVAL;
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
+              << " / nline = " << std::hex << m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())]
+              << " / set = " << std::dec << set << " / way = " << way << std::endl;
+}
+#endif
+            } 
+            else 
+            {
+                assert(false and "LOCK ERROR in SC_FSM, STATE = SC_DIR_INVAL");
+            }
+            break;
+        }
+        //////////////
+        case SC_INVAL:  // Request the broadcast inval to INIT_CMD FSM
+        {
+            if ( !r_sc_to_init_cmd_multi_req.read() &&
+                 !r_sc_to_init_cmd_brdcast_req.read()) 
+            {
+                r_sc_to_init_cmd_multi_req    = false;
+                r_sc_to_init_cmd_brdcast_req  = true;
+                r_sc_to_init_cmd_trdid        = r_sc_upt_index.read();
+                r_sc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
+                r_sc_to_init_cmd_index        = 0;
+                r_sc_to_init_cmd_wdata        = 0;
+
+                r_sc_fsm = SC_TRT_PUT_REQ;
+            }
+            break;
+        }
+        ////////////////////
+        case SC_TRT_PUT_REQ: // request the IXR FSM to start a put transaction
+        {
+            if ( !r_sc_to_ixr_cmd_req ) 
+            {
+                r_sc_to_ixr_cmd_req     = true;
+                r_sc_to_ixr_cmd_write   = true;
+                r_sc_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
+                r_sc_to_ixr_cmd_trdid   = r_sc_trt_index.read();
+                r_sc_fsm                = SC_IDLE;
+                cmd_sc_fifo_get         = true;
+                r_sc_cpt                = 0;
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_TRT_PUT_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
+              << " / nline = " << m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()]
+              << " / trt_index = " << r_sc_trt_index.read() << std::endl;
+}
+#endif
+            } 
+            else 
+            {
+               std::cout << "MEM_CACHE, SC_TRT_PUT_REQ state : request should not have been previously set"
+                         << std::endl;
+            }
+            break;
         }
         /////////////////
-      case CLEANUP_HEAP_SEARCH:
-        {
-          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP)
-                 ,"MemCache ERROR : bad HEAP allocation");
-          HeapEntry heap_entry = m_heap_directory.read(r_cleanup_next_ptr.read());
-          bool last = (heap_entry.next == r_cleanup_next_ptr.read());
-          bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
-          bool match_heap_srcid   = ((heap_entry.owner.srcid == r_cleanup_srcid.read())
-#if L1_MULTI_CACHE
-                                     and (heap_entry.owner.cache_id == r_cleanup_pktid.read())
-#endif
-                                     );
-          bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
-          bool match_heap         = match_heap_srcid && match_heap_inst;
-
-          if(match_heap){
-            r_cleanup_ptr           = heap_entry.next; // reuse ressources
-            r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
-          }
-          else{
-            if(last) {
-                ASSERT(false,"MemCache ERROR : CLEANUP hit but line not shared");
-            } else {
-              r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
-              r_cleanup_prev_srcid    = heap_entry.owner.srcid;
-#if L1_MULTI_CACHE
-              r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
-#endif
-              r_cleanup_prev_inst     = heap_entry.owner.inst;
-              r_cleanup_next_ptr = heap_entry.next;
-              r_cleanup_fsm      = CLEANUP_HEAP_SEARCH;
-            }
-          }
-
-          break;
-        }
-        /////////////////
-      case CLEANUP_HEAP_CLEAN:
-        {
-            ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP)
-                   ,"MemCache ERROR : bad HEAP allocation");
-          bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
-          HeapEntry heap_entry; 
-          heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
-#if L1_MULTI_CACHE
-          heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
-#endif
-          heap_entry.owner.inst     = r_cleanup_prev_inst.read();
-          if(last){ // this is the last entry of the list of copies
-            heap_entry.next     = r_cleanup_prev_ptr.read();
-          } else { // this is not the last entry
-            heap_entry.next     = r_cleanup_ptr.read();
-          }
-          m_heap_directory.write(r_cleanup_prev_ptr.read(),heap_entry);
-          r_cleanup_fsm = CLEANUP_HEAP_FREE;
-          break;
-        }
-        /////////////////
-      case CLEANUP_HEAP_FREE:
-        {
-          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP)
-                 ,"MemCache ERROR : bad HEAP allocation");
-          HeapEntry heap_entry;
-          heap_entry.owner.srcid    = 0;
-#if L1_MULTI_CACHE
-          heap_entry.owner.cache_id = 0;
-#endif
-          heap_entry.owner.inst     = false;
-          if(m_heap_directory.is_full()){
-            heap_entry.next     = r_cleanup_next_ptr.read();
-          } else {
-            heap_entry.next     = m_heap_directory.next_free_ptr();
-          }
-          m_heap_directory.write(r_cleanup_next_ptr.read(),heap_entry);
-          m_heap_directory.write_free_ptr(r_cleanup_next_ptr.read());
-          m_heap_directory.unset_full();
-          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) {
-#if DEBUG_VCI_MEM_CACHE
-if(m_cpt_cycles > DEBUG_START_CYCLE)
-              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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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:	 // fill the buffers
-        {
-          if( m_cmd_llsc_addr_fifo.rok() ) {
-#ifdef LOCK_DEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-            std::cout << "SC data : " << m_cmd_llsc_wdata_fifo.read() << std::endl;
-            std::cout << "SC addr : " << std::hex << m_cmd_llsc_addr_fifo.read() << std::dec << std::endl;
-            std::cout << "SC cpt  : " << r_llsc_cpt.read() << std::endl;
-}
-#endif
-            if(m_cmd_llsc_eop_fifo.read()){
-              m_cpt_sc++;
-              r_llsc_fsm = SC_DIR_LOCK;
-#ifdef LOCK_DEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-              std::cout << "SC eop" << std::endl;
-}
-#endif
-            } else { // we keep the last word
-                cmd_llsc_fifo_get = true;
-            }
-            // We fill the two buffers
-            if(r_llsc_cpt.read() < 2){
-                r_llsc_rdata[r_llsc_cpt.read()] = m_cmd_llsc_wdata_fifo.read();
-            }
-            if((r_llsc_cpt.read() == 1) && m_cmd_llsc_eop_fifo.read())
-                r_llsc_wdata = m_cmd_llsc_wdata_fifo.read();
-            if(r_llsc_cpt.read()>3)
-                ASSERT(false,"MEMCACHE error : SC too long");
-            if(r_llsc_cpt.read()==2){
-                r_llsc_wdata = m_cmd_llsc_wdata_fifo.read();
-            }
-            r_llsc_cpt = r_llsc_cpt.read()+1;
-          }	
-          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));
-            r_llsc_is_cnt     = entry.is_cnt;
-            r_llsc_dirty      = entry.dirty;
-            r_llsc_tag        = entry.tag;
-            r_llsc_way        = way;
-            r_llsc_copy       = entry.owner.srcid;
-#if L1_MULTI_CACHE
-            r_llsc_copy_cache = entry.owner.cache_id;
-#endif
-
-            r_llsc_copy_inst  = entry.owner.inst;
-            r_llsc_ptr        = entry.ptr;
-            r_llsc_count      = entry.count;
-            if ( entry.valid ){
-                r_llsc_fsm = SC_DIR_HIT_READ;
-            }
-            else r_llsc_fsm = LLSC_TRT_LOCK;
-          }
-          break;
-        }
-        ////////////////
-      case SC_DIR_HIT_READ:
-        {
-          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.owner.srcid    = r_llsc_copy.read();
-#if L1_MULTI_CACHE
-          entry.owner.cache_id = r_llsc_copy_cache.read();
-#endif
-          entry.owner.inst     = r_llsc_copy_inst.read();
-          entry.count          = r_llsc_count.read();
-          entry.ptr            = r_llsc_ptr.read();
-          m_cache_directory.write(set, way, entry);
-
-          // read data in cache
-          bool ok;
-          ok = (r_llsc_rdata[0].read() == m_cache_data[way][set][word]);
-          if(r_llsc_cpt.read()==4) // 64 bits SC
-            ok &= (r_llsc_rdata[1] == m_cache_data[way][set][word+1]);
-
-#ifdef LOCK_DEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-          std::cout << "SC_DIR_HIT_READ ok ? " << ok << std::endl;
-          if(!ok){
-              std::cout << "SC_DIR_HIT_READ cache data 0 : " << m_cache_data[way][set][word] << std::endl;
-              if(r_llsc_cpt.read()==4)
-                  std::cout << "SC_DIR_HIT_READ rdata 1      : " << m_cache_data[way][set][word+1] << std::endl;
-              std::cout << "SC_DIR_HIT_READ rdata 0      : " << r_llsc_rdata[0].read() << std::endl;
-              if(r_llsc_cpt.read()==4)
-                  std::cout << "SC_DIR_HIT_READ rdata 1      : " << r_llsc_rdata[1].read() << std::endl;
-              std::cout << "SC_DIR_HIT_READ wdata 0      : " << r_llsc_wdata.read() << std::endl;
-              if(r_llsc_cpt.read()==4)
-                  std::cout << "SC_DIR_HIT_READ wdata 1      : " << m_cmd_llsc_wdata_fifo.read() << std::endl;
-          }
-}
-#endif
-          if(ok){
-            /* 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(r_llsc_count.read()) {  // Shared line
-                    if(entry.is_cnt) {
-                        r_llsc_fsm = SC_TRT_LOCK;
-                    } else {
-                        if( !r_llsc_to_init_cmd_multi_req.read() && 
-                            !r_llsc_to_init_cmd_brdcast_req.read()  )
-                            r_llsc_fsm = SC_UPT_LOCK;
-                        else
-                            r_llsc_fsm = SC_WAIT;
-                    }
-                } else {
-                    r_llsc_fsm = SC_DIR_HIT_WRITE;
-                }
-            }
-          } else {
-            r_llsc_fsm = SC_RSP_FALSE;
-          }
-          break;
-        }
-        ////////////////
-      case SC_DIR_HIT_WRITE:
-        {
-          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())]; 
-
-          m_cache_data[way][set][word] = r_llsc_wdata.read();
-          if(r_llsc_cpt.read()==4)
-              m_cache_data[way][set][word+1] = m_cmd_llsc_wdata_fifo.read();
-          
-          r_llsc_fsm = SC_RSP_TRUE;
-          break;
+        case SC_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
+        {
+            if( !r_sc_to_tgt_rsp_req ) 
+            {
+                cmd_sc_fifo_get	    = true;
+                r_sc_cpt              = 0;
+                r_sc_to_tgt_rsp_req	= true;
+                r_sc_to_tgt_rsp_data	= 1;
+                r_sc_to_tgt_rsp_srcid	= m_cmd_sc_srcid_fifo.read();
+                r_sc_to_tgt_rsp_trdid	= m_cmd_sc_trdid_fifo.read();
+                r_sc_to_tgt_rsp_pktid	= m_cmd_sc_pktid_fifo.read();
+                r_sc_fsm              = SC_IDLE;
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        ////////////////////
+        case SC_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
+        {
+            if( !r_sc_to_tgt_rsp_req ) 
+            {
+                cmd_sc_fifo_get       = true;
+                r_sc_cpt              = 0;
+                r_sc_to_tgt_rsp_req	= true;
+                r_sc_to_tgt_rsp_data	= 0;
+                r_sc_to_tgt_rsp_srcid	= m_cmd_sc_srcid_fifo.read();
+                r_sc_to_tgt_rsp_trdid	= m_cmd_sc_trdid_fifo.read();
+                r_sc_to_tgt_rsp_pktid	= m_cmd_sc_pktid_fifo.read();
+                r_sc_fsm              = SC_IDLE;
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
+}
+#endif
+            }
+            break;
         }
         /////////////////////
-      case SC_UPT_LOCK: 	// Try to register the request in Update Table
-        {
-
-          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
-            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())]; 
-            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);
-            if(wok){
-              // write data in cache
-              m_cache_data[way][set][word] = r_llsc_wdata.read();
-              if(r_llsc_cpt.read()==4)
-                  m_cache_data[way][set][word+1] = m_cmd_llsc_wdata_fifo.read();
-            }
-#ifdef IDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-            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 the Update Table and the Directory if no entry...
-            if ( wok ) r_llsc_fsm = SC_HEAP_LOCK;
-            else       r_llsc_fsm = SC_WAIT;
-          }
-          break;
+        case SC_TRT_GET_LOCK:         // cache miss : request access to transaction Table
+        {
+            if( r_alloc_trt_fsm.read() == ALLOC_TRT_SC ) 
+            {
+                size_t   index = 0;
+                bool hit_read = m_transaction_tab.hit_read(
+                                  m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()],index);
+                bool hit_write = m_transaction_tab.hit_write(
+                                   m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()]);
+                bool wok = !m_transaction_tab.full(index);
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_TRT_GET_LOCK> Check TRT state" 
+              << " / hit_read = "  << hit_read
+              << " / hit_write = " << hit_write
+              << " / wok = " << wok  
+              << " / index = " << index << std::endl;
+}
+#endif
+
+                if ( hit_read || !wok || hit_write ) // missing line already requested or no space in TRT
+                {
+                    r_sc_fsm = SC_WAIT;
+                } 
+                else 
+                {
+                    r_sc_trt_index = index;
+                    r_sc_fsm       = SC_TRT_GET_SET;
+                }
+            }
+            break;
         }
         ////////////////////
-      case SC_WAIT: 	// release all locks
-        {
-          r_llsc_fsm = SC_DIR_LOCK;
-          break;
-        }
-        ////////////////////
-      case SC_HEAP_LOCK: 	// lock the heap
-        {
-          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC ){
-            r_llsc_fsm = SC_UPT_REQ;
-          }
-          break;
-        }
-        ////////////////////
-      case SC_UPT_REQ: 	// Request the update
-        {
-          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC)
-                 ,"MemCache ERROR : bad HEAP allocation");
-          if( !r_llsc_to_init_cmd_multi_req.read() && 
-              !r_llsc_to_init_cmd_brdcast_req.read()  ){
-            r_llsc_to_init_cmd_brdcast_req  = 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        = r_llsc_wdata.read();
-            if(r_llsc_cpt.read() == 4){
-                r_llsc_to_init_cmd_is_long    = true;
-                r_llsc_to_init_cmd_wdata_high = m_cmd_llsc_wdata_fifo.read();
-            } else {
-                r_llsc_to_init_cmd_is_long    = false;
-                r_llsc_to_init_cmd_wdata_high = 0;
-            }
-
-            // We put the first copy in the fifo
-            llsc_to_init_cmd_fifo_put     = true;
-            llsc_to_init_cmd_fifo_inst    = r_llsc_copy_inst.read();
-            llsc_to_init_cmd_fifo_srcid   = r_llsc_copy.read();
-#if L1_MULTI_CACHE
-            llsc_to_init_cmd_fifo_cache_id= r_llsc_copy_cache.read();
-#endif
-            if(r_llsc_count.read() == 1){
-#ifdef LOCK_DEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-              std::cout << "SC_UPT_REQ, only one owner : " << r_llsc_copy.read() << std::endl;
-}
-#endif
-              r_llsc_fsm = LLSC_IDLE;
-              cmd_llsc_fifo_get            = true;
-              r_llsc_to_init_cmd_multi_req = true;
-              r_llsc_cpt = 0;
-            } else {
-              r_llsc_fsm = SC_UPDATE;
-            }
-          }
-          break;
-        }
-        //////////////////
-      case SC_UPDATE:   	// send a multi-update request to INIT_CMD fsm
-        {
-          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC)
-                 ,"MemCache ERROR : bad HEAP allocation");
-          HeapEntry entry = m_heap_directory.read(r_llsc_ptr.read());
-          llsc_to_init_cmd_fifo_srcid    = entry.owner.srcid;
-#if L1_MULTI_CACHE
-          llsc_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
-#endif
-          llsc_to_init_cmd_fifo_inst     = entry.owner.inst;
-          llsc_to_init_cmd_fifo_put = true;
-
-          if( m_llsc_to_init_cmd_inst_fifo.wok() ){
-            r_llsc_ptr = entry.next;
-            if( entry.next == r_llsc_ptr.read() ) { // last copy
-              r_llsc_to_init_cmd_multi_req = true;
-              r_llsc_fsm = LLSC_IDLE; // Response will be sent after receiving
-                                      // all update responses
-              cmd_llsc_fifo_get         = true;
-              r_llsc_cpt = 0;
-            } else {
-              r_llsc_fsm = SC_UPDATE;
-            }
-          } else {
-            r_llsc_fsm = SC_UPDATE;
-          }
-          
-          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] = r_llsc_wdata.read();
-                } else {
-                    if((i==(m_x[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]+1)) && // 64 bit SC
-                        (r_llsc_cpt.read()==4)) {
-                        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       = SC_WAIT;
-              }
-            } else {
-              r_llsc_fsm = SC_WAIT;
-            }
-          }
-          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(m_cpt_cycles > DEBUG_START_CYCLE){
-            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 = SC_WAIT;
-          }
-          break;
-        }
-        //////////////////
-      case SC_DIR_INVAL:
-        {
-          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) &&
-              (r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC )  &&
-              (r_alloc_dir_fsm.read() == ALLOC_DIR_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
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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
-
-            // invalidate directory entry
-            DirectoryEntry entry;
-            entry.valid	        = false;
-            entry.dirty	        = false;
-            entry.tag	        = 0;
-            entry.is_cnt        = false;
-            entry.lock	        = false;
-            entry.count         = 0;
-            entry.owner.srcid   = 0;
-#if L1_MULTI_CACHE
-            entry.owner.cache_id= 0;
-#endif
-            entry.owner.inst    = false;
-            entry.ptr           = 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_multi_req.read() &&
-               !r_llsc_to_init_cmd_brdcast_req.read()) {
-            r_llsc_to_init_cmd_multi_req    = false;
-            r_llsc_to_init_cmd_brdcast_req  = 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_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;
-            r_llsc_cpt = 0;
-          } 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_cpt = 0;
-            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_cpt = 0;
-            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 = SC_WAIT;
-            } 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 ) {
+        case SC_TRT_GET_SET:	// register the GET transaction in TRT
+        {
+            if( r_alloc_trt_fsm.read() == ALLOC_TRT_SC ) 
+            {
                 std::vector<be_t> be_vector;
                 std::vector<data_t> data_vector;
@@ -3429,40 +4325,51 @@
                 }
 
-                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(),
-                  false,
-                  0,
-                  0,
-                  be_vector,
-                  data_vector);
-#ifdef TDEBUG
-if(m_cpt_cycles > DEBUG_START_CYCLE){
-	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()];
-            r_llsc_fsm                   = SC_WAIT;
-          }
-          break;
-        }
-    } // end switch r_llsc_fsm
+                m_transaction_tab.set(r_sc_trt_index.read(),
+                                      true,		// read request		
+                                      m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()],
+                                      m_cmd_sc_srcid_fifo.read(),
+                                      m_cmd_sc_trdid_fifo.read(),
+                                      m_cmd_sc_pktid_fifo.read(),
+                                      false,		// write request from processor
+                                      0,
+                                      0,
+                                      be_vector,
+                                      data_vector);
+                r_sc_fsm = SC_TRT_GET_REQ;        
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_TRT_GET_SET> Register a GET transaction in TRT" << std::hex
+              << " / nline = " << m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()] 
+              << " / trt_index = " << r_sc_trt_index.read() << std::endl;
+}
+#endif
+            }
+            break;
+        }
+        ////////////////////
+        case SC_TRT_GET_REQ:	// request the IXR_CMD FSM to fetch the missing line
+        {
+            if ( !r_sc_to_ixr_cmd_req ) 
+            {
+                r_sc_to_ixr_cmd_req        = true;
+                r_sc_to_ixr_cmd_write      = false;
+                r_sc_to_ixr_cmd_trdid      = r_sc_trt_index.read();
+                r_sc_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()];
+                r_sc_fsm                   = SC_WAIT;
+
+#if DEBUG_MEMC_SC
+if( m_debug_sc_fsm )
+{
+    std::cout << "  <MEMC.SC_TRT_GET_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
+              << " / nline = " << m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()]
+              << " / trt_index = " << r_sc_trt_index.read() << std::endl;
+}
+#endif
+            }
+            break;
+        }
+    } // end switch r_sc_fsm
 
 
@@ -3472,10 +4379,17 @@
     // 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 
+    //
+    // It implements a round-robin priority between the three possible client FSMs
+    // XRAM_RSP, WRITE and SC. Each FSM can request two types of services:
+    // - r_xram_rsp_to_init_cmd_multi_req : multi-inval  
+    //   r_xram_rsp_to_init_cmd_brdcast_req : broadcast-inval  
+    // - r_write_to_init_cmd_multi_req : multi-update  
+    //   r_write_to_init_cmd_brdcast_req : broadcast-inval 
+    // - r_sc_to_init_cmd_multi_req : multi-update  
+    //   r_sc_to_init_cmd_brdcast_req : broadcast-inval
+    //
+    // An 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 
+    // An 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
@@ -3483,217 +4397,274 @@
     ///////////////////////////////////////////////////////////////////////////////
 
-    switch ( r_init_cmd_fsm.read() ) {
-
-      //////////////////////// 
-      case INIT_CMD_UPDT_IDLE:	// Invalidate requests have highest priority
-        {
-
-          if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
-               r_xram_rsp_to_init_cmd_multi_req.read()  ) {
-            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
-            m_cpt_inval++;
-          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
-            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
-            m_cpt_inval++;
-          } else if ( m_write_to_init_cmd_inst_fifo.rok() ||
-                      r_write_to_init_cmd_multi_req.read() ) {
-            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
-            m_cpt_update++;
-          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
-            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
-            m_cpt_inval++;
-          } else if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
-                      r_llsc_to_init_cmd_multi_req.read()  ) {
-            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
-            m_cpt_update++;
-          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
-            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
-            m_cpt_inval++;
-          }
-          break;
+    switch ( r_init_cmd_fsm.read() ) 
+    {
+        //////////////////////// 
+        case INIT_CMD_UPDT_IDLE:	// XRAM_RSP FSM has highest priority
+        {
+            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
+                 r_xram_rsp_to_init_cmd_multi_req.read()  ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+                m_cpt_inval++;
+            } 
+            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
+                m_cpt_inval++;
+            } 
+            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
+                      r_write_to_init_cmd_multi_req.read() ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+                m_cpt_update++;
+            } 
+            else if ( r_write_to_init_cmd_brdcast_req.read() )
+            {
+                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
+                m_cpt_inval++;
+            } 
+            else if ( m_sc_to_init_cmd_inst_fifo.rok() ||
+                      r_sc_to_init_cmd_multi_req.read()  ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+                m_cpt_update++;
+            } 
+            else if( r_sc_to_init_cmd_brdcast_req.read() )
+            {
+                r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+                m_cpt_inval++;
+            }
+            break;
         }
         /////////////////////////
-      case INIT_CMD_INVAL_IDLE:	// Update requests have highest priority
-        {
-          if ( m_write_to_init_cmd_inst_fifo.rok() ||
-               r_write_to_init_cmd_multi_req.read() ) {
-            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
-            m_cpt_update++;
-          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
-            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
-            m_cpt_inval++;
-          } else if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
-                      r_llsc_to_init_cmd_multi_req.read()  ) {
-            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
-            m_cpt_update++;
-          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
-            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
-            m_cpt_inval++;
-          } else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
-                      r_xram_rsp_to_init_cmd_multi_req.read()  ) {
-            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
-            m_cpt_inval++;
-          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
-            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
-            m_cpt_inval++;
-          }
-          break;
+        case INIT_CMD_INVAL_IDLE:	// WRITE FSM has highest priority
+        {
+            if ( m_write_to_init_cmd_inst_fifo.rok() ||
+                 r_write_to_init_cmd_multi_req.read() ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+                m_cpt_update++;
+            } 
+            else if ( r_write_to_init_cmd_brdcast_req.read() )
+            {
+                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
+                m_cpt_inval++;
+            } 
+            else if ( m_sc_to_init_cmd_inst_fifo.rok() ||
+                      r_sc_to_init_cmd_multi_req.read()  ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+                m_cpt_update++;
+            } 
+            else if( r_sc_to_init_cmd_brdcast_req.read() )
+            {
+                r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+                m_cpt_inval++;
+            } 
+            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
+                      r_xram_rsp_to_init_cmd_multi_req.read()  ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+                m_cpt_inval++;
+            } 
+            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
+                m_cpt_inval++;
+            }
+            break;
+        }
+        //////////////////////////
+        case INIT_CMD_SC_UPDT_IDLE:	// SC FSM has highest priority
+        {
+            if ( m_sc_to_init_cmd_inst_fifo.rok() ||
+                 r_sc_to_init_cmd_multi_req.read()  ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+                m_cpt_update++;
+            } 
+            else if( r_sc_to_init_cmd_brdcast_req.read() )
+            {
+                r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+                m_cpt_inval++;
+            } 
+            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
+                      r_xram_rsp_to_init_cmd_multi_req.read()  ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+                m_cpt_inval++;
+            } 
+            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
+                m_cpt_inval++;
+            } 
+            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
+                      r_write_to_init_cmd_multi_req.read() ) 
+            {
+                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+                m_cpt_update++;
+            } 
+            else if ( r_write_to_init_cmd_brdcast_req.read() )
+            {
+                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
+                m_cpt_inval++;
+            }
+            break;
+        }
+        //////////////////////////
+        case INIT_CMD_INVAL_NLINE:	// send a multi-inval (from XRAM_RSP)
+        {
+            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() )
+            {
+                if ( p_vci_ini.cmdack ) 
+                {
+                    m_cpt_inval_mult++;
+                    r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+                    xram_rsp_to_init_cmd_fifo_get = true;
+                }
+            } 
+            else 
+            {
+                if( r_xram_rsp_to_init_cmd_multi_req.read() ) r_xram_rsp_to_init_cmd_multi_req = false;
+                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+            }
+            break;
+        }
+        ///////////////////////////
+        case INIT_CMD_XRAM_BRDCAST:	// send a broadcast-inval (from XRAM_RSP)
+        {
+            if ( p_vci_ini.cmdack ) 
+            {
+                m_cpt_inval_brdcast++;
+                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+                r_xram_rsp_to_init_cmd_brdcast_req = false;
+            }
+            break;
+        }
+        ////////////////////////////
+        case INIT_CMD_WRITE_BRDCAST:	// send a broadcast-inval (from WRITE FSM)
+        {
+            if( p_vci_ini.cmdack ) 
+            {
+
+#if DEBUG_MEMC_INIT_CMD
+if( m_debug_init_cmd_fsm )
+{
+    std::cout << "  <MEMC.INIT_CMD_WRITE_BRDCAST> Broadcast-Inval for line " 
+              << r_write_to_init_cmd_nline.read() << std::endl;
+}
+#endif
+                m_cpt_inval_brdcast++;
+                r_write_to_init_cmd_brdcast_req = false;
+                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
+            }
+            break;
         }
         /////////////////////////
-      case INIT_CMD_SC_UPDT_IDLE:	// Update requests for SCs have highest priority
-        {
-          if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
-               r_llsc_to_init_cmd_multi_req.read()  ) {
-            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
-            m_cpt_update++;
-          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
-            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
-            m_cpt_inval++;
-          } else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
-                      r_xram_rsp_to_init_cmd_multi_req.read()  ) {
-            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
-            m_cpt_inval++;
-          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
-            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
-            m_cpt_inval++;
-          } else if ( m_write_to_init_cmd_inst_fifo.rok() ||
-                      r_write_to_init_cmd_multi_req.read() ) {
-            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
-            m_cpt_update++;
-          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
-            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
-            m_cpt_inval++;
-          }
-          break;
+        case INIT_CMD_UPDT_NLINE:  // send nline for a multi-update (from WRITE FSM)
+        {
+            if ( m_write_to_init_cmd_inst_fifo.rok() ) 
+            {
+                if ( p_vci_ini.cmdack )
+                {
+                    m_cpt_update_mult++;
+                    r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
+                    // write_to_init_cmd_fifo_get = true;
+                }
+            } 
+            else 
+            {
+                if ( r_write_to_init_cmd_multi_req.read() ) r_write_to_init_cmd_multi_req = false;
+                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
+            }
+            break;
+        }
+        /////////////////////////
+        case INIT_CMD_UPDT_INDEX:  // send word index for a multi-update (from WRITE FSM)
+        {
+            r_init_cmd_cpt    = 0;
+            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
+            break;
         }
         ////////////////////////
-      case INIT_CMD_INVAL_NLINE:	// send the cache line index
-        {
-          if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ){
-            if ( p_vci_ini.cmdack ) {
-              m_cpt_inval_mult++;
-              r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
-              xram_rsp_to_init_cmd_fifo_get = true;
-            }
-          } else {
-            if( r_xram_rsp_to_init_cmd_multi_req.read() ){
-              r_xram_rsp_to_init_cmd_multi_req = false;
+        case INIT_CMD_UPDT_DATA:  // send the data for a multi-update (from WRITE FSM)
+        {
+            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_NLINE;
+                    write_to_init_cmd_fifo_get = true;
+                } 
+                else 
+                {
+                    r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
+                }
+            }
+            break;
+        }
+        /////////////////////////
+        case INIT_CMD_SC_BRDCAST:	// send a broadcast-inval (from SC FSM)
+        {
+            if( p_vci_ini.cmdack ) 
+            {
+                m_cpt_inval_brdcast++;
+                r_sc_to_init_cmd_brdcast_req = false;
+                r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
+            }
+            break;
+        }
+        ////////////////////////////
+        case INIT_CMD_SC_UPDT_NLINE:   // send nline for a multi-update (from SC FSM)
+        {
+            if ( m_sc_to_init_cmd_inst_fifo.rok() )
+            {
+                if ( p_vci_ini.cmdack )
+                {
+                    m_cpt_update_mult++;
+                    r_init_cmd_fsm = INIT_CMD_SC_UPDT_INDEX;
+                }
             } 
-            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
-          }
-          break;
+            else 
+            {
+                if( r_sc_to_init_cmd_multi_req.read() ) r_sc_to_init_cmd_multi_req = false;
+                r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
+            }
+            break;
+        }
+        ////////////////////////////
+        case INIT_CMD_SC_UPDT_INDEX:  // send word index for a multi-update (from SC FSM)
+        {
+            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA;
+            break;
+        }
+        ///////////////////////////
+        case INIT_CMD_SC_UPDT_DATA:  // send first data for a multi-update (from SC FSM) 
+        {
+            if ( p_vci_ini.cmdack ) 
+            {
+                if ( r_sc_to_init_cmd_is_long.read() )
+                {
+                    r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA_HIGH;
+                } 
+                else 
+                {
+                    sc_to_init_cmd_fifo_get = true;
+                    r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+                }
+            }
+            break;
         }
         ////////////////////////
-      case INIT_CMD_XRAM_BRDCAST:	// send the cache line index
-        {
-          if ( p_vci_ini.cmdack ) {
-            m_cpt_inval_brdcast++;
-            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
-            r_xram_rsp_to_init_cmd_brdcast_req = false;
-          }
-          break;
-        }
-        /////////////////////////
-      case INIT_CMD_WRITE_BRDCAST:
-        {
-          if( p_vci_ini.cmdack ) {
-            m_cpt_inval_brdcast++;
-            r_write_to_init_cmd_brdcast_req = false;
-            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
-          }
-          break;
-        }
-        /////////////////////////
-      case INIT_CMD_UPDT_NLINE:	// send the cache line index
-        {
-          if ( m_write_to_init_cmd_inst_fifo.rok() ) {
-            if ( p_vci_ini.cmdack ){
-              m_cpt_update_mult++;
-              r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
-            }
-          } else {
-            if ( r_write_to_init_cmd_multi_req.read() ){
-              r_write_to_init_cmd_multi_req = false;
-            }
-            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
-          }
-          break;
-        }
-        /////////////////////////
-      case INIT_CMD_UPDT_INDEX:	// send the first word index
-        {
-          r_init_cmd_cpt    = 0;
-          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_NLINE;
-              write_to_init_cmd_fifo_get = true;
-            } else {
-              r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
-            }
-          }
-          break;
-        }
-        /////////////////////////
-      case INIT_CMD_SC_BRDCAST:
-        {
-          if( p_vci_ini.cmdack ) {
-            m_cpt_inval_brdcast++;
-            r_llsc_to_init_cmd_brdcast_req = false;
-            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
-          }
-          break;
-        }
-        /////////////////////////
-      case INIT_CMD_SC_UPDT_NLINE:	// send the cache line index
-        {
-          if ( m_llsc_to_init_cmd_inst_fifo.rok() ){
-            if ( p_vci_ini.cmdack ){
-              m_cpt_update_mult++;
-              r_init_cmd_fsm = INIT_CMD_SC_UPDT_INDEX;
-            }
-          } else {
-            if( r_llsc_to_init_cmd_multi_req.read() ){
-              r_llsc_to_init_cmd_multi_req = false;
-            }
-            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
-          }
-          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 ) {
-            if(r_llsc_to_init_cmd_is_long.read()){
-                r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA_HIGH;
-            } else {
-                llsc_to_init_cmd_fifo_get = true;
+        case INIT_CMD_SC_UPDT_DATA_HIGH:  // send second data for a multi-update (from SC FSM)
+        {
+            if ( p_vci_ini.cmdack ) 
+            {
+                sc_to_init_cmd_fifo_get = true;
                 r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
             }
-          }
-          break;
-        }
-        ////////////////////////
-      case INIT_CMD_SC_UPDT_DATA_HIGH:	// send the data upper
-        {
-          if ( p_vci_ini.cmdack ) {
-              llsc_to_init_cmd_fifo_get = true;
-              r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
-          }
-          break;
-        }
-
-
+            break;
+        }
     } // end switch r_init_cmd_fsm
 
@@ -3705,19 +4676,20 @@
     // - r_read_to_tgt_rsp_req
     // - r_write_to_tgt_rsp_req
-    // - r_llsc_to_tgt_rsp_req
+    // - r_sc_to_tgt_rsp_req
     // - r_cleanup_to_tgt_rsp_req
+    // - r_xram_rsp_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
+    // The  ordering is :  read > write > sc > xram > init > cleanup
     /////////////////////////////////////////////////////////////////////
 
-    switch ( r_tgt_rsp_fsm.read() ) {
-
-      ///////////////////////
-      case TGT_RSP_READ_IDLE:		// write requests have the highest priority
+    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 ) {
+          else if ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
+          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();
@@ -3725,5 +4697,6 @@
           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     ) {
+          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();
@@ -3732,8 +4705,9 @@
         }
         ////////////////////////
-      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 ) {
+        case TGT_RSP_WRITE_IDLE:	// sc requests have the highest priority
+        {
+          if      ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
+          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();
@@ -3741,5 +4715,6 @@
           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     ) {
+          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();
@@ -3750,7 +4725,8 @@
         }
         ///////////////////////
-      case TGT_RSP_LLSC_IDLE:		// cleanup requests have the highest priority
-        {
-          if ( r_xram_rsp_to_tgt_rsp_req )  {
+        case TGT_RSP_SC_IDLE:		// xram_rsp 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();
@@ -3758,24 +4734,28 @@
           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     ) {
+          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_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
           break;
         }
-      case TGT_RSP_XRAM_IDLE:		// init requests have the highest priority
+        ///////////////////////
+        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     ) {
+          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 )  {
+          else if ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
+          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();
@@ -3784,14 +4764,16 @@
         }
         ///////////////////////
-      case TGT_RSP_INIT_IDLE:		// cleanup requests have the highest priority
+        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     ) {
+          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 ) {
+          else if ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
+          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();
@@ -3801,13 +4783,15 @@
         }
         ///////////////////////
-      case TGT_RSP_CLEANUP_IDLE:		// read requests have the highest priority
-        {
-          if      ( r_read_to_tgt_rsp_req     ) {
+        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 ) {
+          else if ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
+          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();
@@ -3817,73 +4801,143 @@
           break;
         }
+        //////////////////
+        case TGT_RSP_READ:		// send the response to a read 
+        {
+            if ( p_vci_tgt.rspack ) 
+            {
+
+#if DEBUG_MEMC_TGT_RSP
+if( m_debug_tgt_rsp_fsm )
+{
+    std::cout << "  <MEMC.TGT_RSP_READ> Read response"
+              << " / rsrcid = " << std::hex << r_read_to_tgt_rsp_srcid.read()
+              << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
+              << " / rdata = " << r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
+              << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
+}
+#endif
+                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 ) 
+            {
+
+#if DEBUG_MEMC_TGT_RSP
+if( m_debug_tgt_rsp_fsm )
+{
+    std::cout << "  <MEMC.TGT_RSP_WRITE> Write response"
+              << " / rsrcid = " << r_write_to_tgt_rsp_srcid.read()
+              << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read() << std::endl;
+}
+#endif
+                r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
+                r_write_to_tgt_rsp_req = false;
+            }
+            break;
+        }
+        ///////////////////
+        case TGT_RSP_CLEANUP:		// pas clair pour moi (AG)   
+        {
+            if ( p_vci_tgt.rspack ) 
+            {
+
+#if DEBUG_MEMC_TGT_RSP
+if( m_debug_tgt_rsp_fsm )
+{
+    std::cout << "  <MEMC.TGT_RSP_CLEANUP> Cleanup response"
+              << " / rsrcid = " << r_cleanup_to_tgt_rsp_srcid.read()
+              << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read() << std::endl;
+}
+#endif
+                r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
+                r_cleanup_to_tgt_rsp_req = false;
+            }
+            break;
+        }
+        //////////////////
+        case TGT_RSP_SC:		// send one atomic word response
+        {
+            if ( p_vci_tgt.rspack ) 
+            {
+
+#if DEBUG_MEMC_TGT_RSP
+if( m_debug_tgt_rsp_fsm )
+{
+    std::cout << "  <MEMC.TGT_RSP_SC> SC response"
+              << " / rsrcid = " << r_sc_to_tgt_rsp_srcid.read()
+              << " / rtrdid = " << r_sc_to_tgt_rsp_trdid.read() << std::endl;
+}
+#endif
+                r_tgt_rsp_fsm = TGT_RSP_SC_IDLE;
+                r_sc_to_tgt_rsp_req = false;
+            }
+            break;
+        }
+
         ///////////////////////
-      case TGT_RSP_READ:		// send the response
-        {
-          PRINTF("* <MEM_CACHE.TGT> YURI RSP_READ     : rspack %d - cpt %d on %d\n", (int)p_vci_tgt.rspack,(int)r_tgt_rsp_cpt.read(),(int)(r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1));
-
-          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_XRAM:		// send the response after XRAM access
+        {
+            if ( p_vci_tgt.rspack ) 
+            {
+
+#if DEBUG_MEMC_TGT_RSP
+if( m_debug_tgt_rsp_fsm )
+{
+    std::cout << "  <MEMC.TGT_RSP_XRAM> Response following XRAM access"
+              << " / rsrcid = " << r_xram_rsp_to_tgt_rsp_srcid.read()
+              << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
+              << " / rdata = " << r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
+              << " / cpt = " << r_tgt_rsp_cpt.read() << std::endl;
+}
+#endif
+                if ( (r_tgt_rsp_cpt.read() == 
+                     (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
+                   || r_xram_rsp_to_tgt_rsp_rerror.read() ) 
+                {
+                    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_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_xram_rsp_to_tgt_rsp_rerror.read() ) {
-              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;
+        case TGT_RSP_INIT:		// send the write response after coherence transaction
+        {
+            if ( p_vci_tgt.rspack ) 
+            {
+
+#if DEBUG_MEMC_TGT_RSP
+if( m_debug_tgt_rsp_fsm )
+{
+    std::cout << "  <MEMC.TGT_RSP_INIT> Write response after coherence transaction"
+              << " / rsrcid = " << r_init_rsp_to_tgt_rsp_srcid.read()
+              << " / rtrdid = " << r_init_rsp_to_tgt_rsp_trdid.read() << std::endl;
+}
+#endif
+                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
+    //		ALLOC_UPT FSM
     ////////////////////////////////////////////////////////////////////////////////////
     // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
@@ -3896,5 +4950,6 @@
     /////////////////////////////////////////////////////////////////////////////////////
 
-    switch ( r_alloc_upt_fsm.read() ) {
+    switch ( r_alloc_upt_fsm.read() ) 
+    {
 
       ////////////////////////
@@ -3907,6 +4962,6 @@
           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;
+          else if ((r_sc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_sc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_SC;
         }
         break;
@@ -3919,6 +4974,6 @@
           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_sc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_sc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_SC;
           else if (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
         }
@@ -3930,6 +4985,6 @@
         { 
           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_sc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_sc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_SC;
           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)   ||
@@ -3942,6 +4997,6 @@
         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;
+          if      ((r_sc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_sc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_SC;
           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) ||
@@ -3952,7 +5007,7 @@
         
         //////////////////////////
-      case ALLOC_UPT_LLSC:
-        if( (r_llsc_fsm.read() != SC_UPT_LOCK) && 
-            (r_llsc_fsm.read() != SC_INVAL_LOCK))
+      case ALLOC_UPT_SC:
+        if( (r_sc_fsm.read() != SC_UPT_LOCK) && 
+            (r_sc_fsm.read() != SC_INVAL_LOCK))
         {
           if      (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
@@ -3971,9 +5026,10 @@
     // 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 cyclic ordering is READ > WRITE > SC > CLEANUP > XRAM_RSP
     // The ressource is always allocated.
     /////////////////////////////////////////////////////////////////////////////////////
 
-    switch ( r_alloc_dir_fsm.read() ) {
+    switch ( r_alloc_dir_fsm.read() ) 
+    {
 
       ////////////////////
@@ -3990,5 +5046,5 @@
         {
           if        (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
-          else if   (r_llsc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_sc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_SC;
           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;
@@ -4013,5 +5069,5 @@
               (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
         {
-          if        (r_llsc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          if        (r_sc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_SC;
           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;
@@ -4021,19 +5077,19 @@
 
         ////////////////////
-      case ALLOC_DIR_LLSC:
-        if ( ((r_llsc_fsm.read() != SC_DIR_LOCK)       &&
-              (r_llsc_fsm.read() != SC_DIR_HIT_READ )  &&
-              (r_llsc_fsm.read() != SC_DIR_HIT_WRITE ) &&
-              (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() != SC_UPT_LOCK)       &&
-              (r_llsc_fsm.read() != SC_HEAP_LOCK))
+        case ALLOC_DIR_SC:
+        if ( ((r_sc_fsm.read() != SC_DIR_LOCK)       &&
+              (r_sc_fsm.read() != SC_DIR_HIT_READ )  &&
+              (r_sc_fsm.read() != SC_DIR_HIT_WRITE ) &&
+//              (r_sc_fsm.read() != SC_TRT_GET_LOCK )    &&
+              (r_sc_fsm.read() != SC_TRT_PUT_LOCK)       &&
+              (r_sc_fsm.read() != SC_INVAL_LOCK)     &&
+              (r_sc_fsm.read() != SC_UPT_LOCK)       &&
+              (r_sc_fsm.read() != SC_HEAP_LOCK))
             ||
-            ( (r_llsc_fsm.read()       == SC_HEAP_LOCK) &&
-              (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) )
+            ( (r_sc_fsm.read()       == SC_HEAP_LOCK) &&
+              (r_alloc_heap_fsm.read() == ALLOC_HEAP_SC) )
             ||
-            ( (r_llsc_fsm.read()      == LLSC_TRT_LOCK ) &&
-              (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC)    ) )
+            ( (r_sc_fsm.read()      == SC_TRT_GET_LOCK ) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_SC)    ) )
         {
           if      (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
@@ -4045,5 +5101,5 @@
 
         ///////////////////////
-      case ALLOC_DIR_CLEANUP:
+        case ALLOC_DIR_CLEANUP:
         if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
             (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) )
@@ -4052,9 +5108,9 @@
           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() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_sc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_SC;
         }
         break;
         ////////////////////////
-      case ALLOC_DIR_XRAM_RSP:
+        case ALLOC_DIR_XRAM_RSP:
         if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
             (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)   && 
@@ -4063,5 +5119,5 @@
           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() == SC_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if (r_sc_fsm.read() == SC_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_SC;
           else if (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
         }
@@ -4075,9 +5131,10 @@
     // 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 cyclic priority is READ > WRITE > SC > XRAM_RSP
     // The ressource is always allocated.
     ///////////////////////////////////////////////////////////////////////////////////
 
-    switch (r_alloc_trt_fsm) {
+    switch (r_alloc_trt_fsm) 
+    {
 
       ////////////////////
@@ -4087,6 +5144,6 @@
           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_sc_fsm.read() == SC_TRT_GET_LOCK) ||
+                   (r_sc_fsm.read() == SC_TRT_PUT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
           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) ||
@@ -4100,6 +5157,6 @@
              (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;
+          if      ((r_sc_fsm.read() == SC_TRT_GET_LOCK) ||
+                   (r_sc_fsm.read() == SC_TRT_PUT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
           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) ||
@@ -4109,8 +5166,8 @@
         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))
+      case ALLOC_TRT_SC:
+        if ( (r_sc_fsm.read() != SC_TRT_GET_LOCK) &&
+             (r_sc_fsm.read() != SC_TRT_PUT_LOCK) &&
+             (r_sc_fsm.read() != SC_INVAL_LOCK))
         { 
           if      (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
@@ -4132,6 +5189,6 @@
           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_sc_fsm.read() == SC_TRT_GET_LOCK) ||
+                   (r_sc_fsm.read() == SC_TRT_PUT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
         }
         break;
@@ -4143,6 +5200,6 @@
           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_sc_fsm.read() == SC_TRT_GET_LOCK) ||
+                   (r_sc_fsm.read() == SC_TRT_PUT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
           else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
         }
@@ -4156,9 +5213,10 @@
     // The ALLOC_HEAP FSM allocates the access to the heap
     // with a round robin priority between 5 user FSMs :
-    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
+    // The cyclic ordering is READ > WRITE > SC > CLEANUP > XRAM_RSP
     // The ressource is always allocated.
     /////////////////////////////////////////////////////////////////////////////////////
 
-    switch ( r_alloc_heap_fsm.read() ) {
+    switch ( r_alloc_heap_fsm.read() ) 
+    {
 
       ////////////////////
@@ -4168,5 +5226,5 @@
         {
           if        (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
-          else if   (r_llsc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          else if   (r_sc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_SC;
           else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
           else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
@@ -4180,5 +5238,5 @@
               (r_write_fsm.read() != WRITE_UPDATE)  )
         {
-          if        (r_llsc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          if        (r_sc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_SC;
           else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
           else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
@@ -4188,8 +5246,8 @@
 
         ////////////////////
-      case ALLOC_HEAP_LLSC:
-        if (  (r_llsc_fsm.read() != SC_HEAP_LOCK)  &&
-              (r_llsc_fsm.read() != SC_UPT_REQ )    &&
-              (r_llsc_fsm.read() != SC_UPDATE)  )
+      case ALLOC_HEAP_SC:
+        if (  (r_sc_fsm.read() != SC_HEAP_LOCK)  &&
+              (r_sc_fsm.read() != SC_UPT_REQ )    &&
+              (r_sc_fsm.read() != SC_UPT_NEXT)  )
         {
           if      (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
@@ -4209,5 +5267,5 @@
           else if   (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
           else if   (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
-          else if   (r_llsc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          else if   (r_sc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_SC;
         }
         break;
@@ -4218,5 +5276,5 @@
           if        (r_read_fsm.read() == READ_HEAP_LOCK) 	        r_alloc_heap_fsm = ALLOC_HEAP_READ;
           else if   (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
-          else if   (r_llsc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          else if   (r_sc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_SC;
           else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
         }
@@ -4287,31 +5345,31 @@
     }
     ////////////////////////////////////////////////////////////////////////////////////
-    //		TGT_CMD to LLSC FIFO
+    //		TGT_CMD to SC 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_eop_fifo.put_and_get(p_vci_tgt.eop.read()); 
-        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());
+    if ( cmd_sc_fifo_put ) {
+      if ( cmd_sc_fifo_get ) {
+        m_cmd_sc_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_sc_eop_fifo.put_and_get(p_vci_tgt.eop.read()); 
+        m_cmd_sc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_sc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_sc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_sc_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_eop_fifo.simple_put(p_vci_tgt.eop.read()); 
-        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());
+        m_cmd_sc_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_sc_eop_fifo.simple_put(p_vci_tgt.eop.read()); 
+        m_cmd_sc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_sc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_sc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_sc_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_eop_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();
+      if ( cmd_sc_fifo_get ) {
+        m_cmd_sc_addr_fifo.simple_get();
+        m_cmd_sc_eop_fifo.simple_get();
+        m_cmd_sc_srcid_fifo.simple_get();
+        m_cmd_sc_trdid_fifo.simple_get();
+        m_cmd_sc_pktid_fifo.simple_get();
+        m_cmd_sc_wdata_fifo.simple_get();
       }
     }
@@ -4371,41 +5429,39 @@
     }
     ////////////////////////////////////////////////////////////////////////////////////
-    //		LLSC to INIT_CMD FIFO
+    //		SC to INIT_CMD FIFO
     ////////////////////////////////////////////////////////////////////////////////////
 
-    if ( llsc_to_init_cmd_fifo_put ) {
-      if ( llsc_to_init_cmd_fifo_get ) {
-        m_llsc_to_init_cmd_inst_fifo.put_and_get(llsc_to_init_cmd_fifo_inst);
-        m_llsc_to_init_cmd_srcid_fifo.put_and_get(llsc_to_init_cmd_fifo_srcid);
+    if ( sc_to_init_cmd_fifo_put ) {
+      if ( sc_to_init_cmd_fifo_get ) {
+        m_sc_to_init_cmd_inst_fifo.put_and_get(sc_to_init_cmd_fifo_inst);
+        m_sc_to_init_cmd_srcid_fifo.put_and_get(sc_to_init_cmd_fifo_srcid);
 #if L1_MULTI_CACHE
-        m_llsc_to_init_cmd_cache_id_fifo.put_and_get(llsc_to_init_cmd_fifo_cache_id);
+        m_sc_to_init_cmd_cache_id_fifo.put_and_get(sc_to_init_cmd_fifo_cache_id);
 #endif
       } else {
-          m_llsc_to_init_cmd_inst_fifo.simple_put(llsc_to_init_cmd_fifo_inst);
-          m_llsc_to_init_cmd_srcid_fifo.simple_put(llsc_to_init_cmd_fifo_srcid);
+          m_sc_to_init_cmd_inst_fifo.simple_put(sc_to_init_cmd_fifo_inst);
+          m_sc_to_init_cmd_srcid_fifo.simple_put(sc_to_init_cmd_fifo_srcid);
 #if L1_MULTI_CACHE
-          m_llsc_to_init_cmd_cache_id_fifo.simple_put(llsc_to_init_cmd_fifo_cache_id);
+          m_sc_to_init_cmd_cache_id_fifo.simple_put(sc_to_init_cmd_fifo_cache_id);
 #endif
       }
     } else {
-        if ( llsc_to_init_cmd_fifo_get ) {
-            m_llsc_to_init_cmd_inst_fifo.simple_get();
-            m_llsc_to_init_cmd_srcid_fifo.simple_get();
+        if ( sc_to_init_cmd_fifo_get ) {
+            m_sc_to_init_cmd_inst_fifo.simple_get();
+            m_sc_to_init_cmd_srcid_fifo.simple_get();
 #if L1_MULTI_CACHE
-            m_llsc_to_init_cmd_cache_id_fifo.simple_get();
+            m_sc_to_init_cmd_cache_id_fifo.simple_get();
 #endif
       }
     }
 
-
-  //////////////////////////////////////////////////////////////
     m_cpt_cycles++;
 
-    } // end transition()
-
-  /////////////////////////////
-  tmpl(void)::genMoore()
-    /////////////////////////////
-  {
+} // end transition()
+
+/////////////////////////////
+tmpl(void)::genMoore()
+/////////////////////////////
+{
     ////////////////////////////////////////////////////////////
     // Command signals on the p_vci_ixr port
@@ -4430,20 +5486,20 @@
       p_vci_ixr.eop     = true;
     } 
-    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_LLSC_NLINE ) {
-      if(r_llsc_to_ixr_cmd_write.read()){
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_SC_NLINE ) {
+      if(r_sc_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.address = (addr_t)((r_sc_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.wdata   = r_sc_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_sc_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.address = (addr_t)(r_sc_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.trdid   = r_sc_to_ixr_cmd_trdid.read();
         p_vci_ixr.eop     = true;
       }
@@ -4505,12 +5561,9 @@
         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();
+        p_vci_tgt.cmdack  = m_cmd_sc_addr_fifo.wok();
         break;
       default:
@@ -4526,5 +5579,5 @@
       case TGT_RSP_READ_IDLE:
       case TGT_RSP_WRITE_IDLE:
-      case TGT_RSP_LLSC_IDLE:
+      case TGT_RSP_SC_IDLE:
       case TGT_RSP_XRAM_IDLE:
       case TGT_RSP_INIT_IDLE:
@@ -4539,10 +5592,4 @@
         break;
       case TGT_RSP_READ:
-          PRINTF("  * <MEM_CACHE.TGT> RSP_READ     : srcid %d, trdid %d, pktid %d\n"
-                 ,(uint32_t)r_read_to_tgt_rsp_srcid.read()
-                 ,(uint32_t)r_read_to_tgt_rsp_trdid.read()
-                 ,(uint32_t)r_read_to_tgt_rsp_pktid.read()
-                 );
-
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
@@ -4554,10 +5601,4 @@
         break;
       case TGT_RSP_WRITE:
-          PRINTF("  * <MEM_CACHE.TGT> RSP_WRITE    : BURP srcid %d, trdid %d, pktid %d\n"
-                 ,(uint32_t)r_write_to_tgt_rsp_srcid.read()
-                 ,(uint32_t)r_write_to_tgt_rsp_trdid.read()
-                 ,(uint32_t)r_write_to_tgt_rsp_pktid.read()
-                 );
-
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = 0;
@@ -4565,14 +5606,8 @@
         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   = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
+        p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1); 
         p_vci_tgt.reop     = true;
         break;
       case TGT_RSP_CLEANUP:
-          PRINTF("  * <MEM_CACHE.TGT> RSP_CLEANUP  : srcid %d, trdid %d, pktid %d\n"
-                 ,(uint32_t)r_cleanup_to_tgt_rsp_srcid.read()
-                 ,(uint32_t)r_cleanup_to_tgt_rsp_trdid.read()
-                 ,(uint32_t)r_cleanup_to_tgt_rsp_pktid.read()
-                 );
-
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = 0;
@@ -4583,26 +5618,14 @@
         p_vci_tgt.reop     = true;
         break;
-      case TGT_RSP_LLSC:
-          PRINTF("  * <MEM_CACHE.TGT> RSP_LLSC     : srcid %d, trdid %d, pktid %d\n"
-                 ,(uint32_t)r_llsc_to_tgt_rsp_srcid.read()
-                 ,(uint32_t)r_llsc_to_tgt_rsp_trdid.read()
-                 ,(uint32_t)r_llsc_to_tgt_rsp_pktid.read()
-                 );
-
+      case TGT_RSP_SC:
         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.rdata    = r_sc_to_tgt_rsp_data.read();
+        p_vci_tgt.rsrcid   = r_sc_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_sc_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_sc_to_tgt_rsp_pktid.read();
         p_vci_tgt.rerror   = 0;
         p_vci_tgt.reop     = true;
         break;
       case TGT_RSP_XRAM:
-          PRINTF("  * <MEM_CACHE.TGT> RSP_XRAM     : srcid %d, trdid %d, pktid %d\n"
-                 ,(uint32_t)r_xram_rsp_to_tgt_rsp_srcid.read()
-                 ,(uint32_t)r_xram_rsp_to_tgt_rsp_trdid.read()
-                 ,(uint32_t)r_xram_rsp_to_tgt_rsp_pktid.read()
-                 );
-
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
@@ -4611,14 +5634,9 @@
         p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
         p_vci_tgt.rerror   = r_xram_rsp_to_tgt_rsp_rerror.read();
-        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))
+        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))
                               || r_xram_rsp_to_tgt_rsp_rerror.read());
         break;
       case TGT_RSP_INIT:
-          PRINTF("  * <MEM_CACHE.TGT> RSP_INIT     : srcid %d, trdid %d, pktid %d\n"
-                 ,(uint32_t)r_init_rsp_to_tgt_rsp_srcid.read()
-                 ,(uint32_t)r_init_rsp_to_tgt_rsp_trdid.read()
-                 ,(uint32_t)r_init_rsp_to_tgt_rsp_pktid.read()
-                 );
-
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = 0;
@@ -4659,9 +5677,4 @@
       case INIT_CMD_INVAL_NLINE:
       {
-        PRINTF("  * <MEM_CACHE.INIT_CMD> INVAL_NLINE : trdid %d, pktid %d\n"
-               ,(uint32_t)r_xram_rsp_to_init_cmd_trdid.read()
-               ,(uint32_t)m_xram_rsp_to_init_cmd_cache_id_fifo.read()
-               );
-        
         p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
         if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
@@ -4753,25 +5766,25 @@
         p_vci_ini.cmdval  = true;
         p_vci_ini.address = m_broadcast_address;
-        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.wdata   = (addr_t)r_sc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_sc_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();
+        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
         p_vci_ini.pktid   = 0;
         break;
       case INIT_CMD_SC_UPDT_NLINE:
-        p_vci_ini.cmdval  = m_llsc_to_init_cmd_inst_fifo.rok();
-        if(m_llsc_to_init_cmd_inst_fifo.rok()){
-          if( m_llsc_to_init_cmd_inst_fifo.read() ) {
-            p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 12);
+        p_vci_ini.cmdval  = m_sc_to_init_cmd_inst_fifo.rok();
+        if(m_sc_to_init_cmd_inst_fifo.rok()){
+          if( m_sc_to_init_cmd_inst_fifo.read() ) {
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 12);
           } else {
-            p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 8);
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 8);
           }
         } else {
           p_vci_ini.address = 0;
         }
-        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);
-        if(r_llsc_to_init_cmd_is_long.read()){
+        p_vci_ini.wdata   = (uint32_t)r_sc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_sc_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        if(r_sc_to_init_cmd_is_long.read()){
             p_vci_ini.plen    = 4 * 4;
         } else {
@@ -4779,37 +5792,37 @@
         }
         p_vci_ini.eop     = false;
-        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
-        p_vci_ini.pktid   = m_llsc_to_init_cmd_cache_id_fifo.read();
+        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
         break;
       case INIT_CMD_SC_UPDT_INDEX:
         p_vci_ini.cmdval  = true;
-        if( m_llsc_to_init_cmd_inst_fifo.read() ) {
-          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 12);
+        if( m_sc_to_init_cmd_inst_fifo.read() ) {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 12);
         } else {
-          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 8);
-        }
-        p_vci_ini.wdata   = r_llsc_to_init_cmd_index.read();
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 8);
+        }
+        p_vci_ini.wdata   = r_sc_to_init_cmd_index.read();
         p_vci_ini.be      = 0xF;
-        if(r_llsc_to_init_cmd_is_long.read()){
+        if(r_sc_to_init_cmd_is_long.read()){
             p_vci_ini.plen    = 4 * 4;
         } else {
             p_vci_ini.plen    = 4 * 3;
         }
-        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
-        p_vci_ini.pktid   = m_llsc_to_init_cmd_cache_id_fifo.read();
+        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
         p_vci_ini.eop     = false;
         break;
       case INIT_CMD_SC_UPDT_DATA:
         p_vci_ini.cmdval  = true;
-        if( m_llsc_to_init_cmd_inst_fifo.read() ) {
-          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 12);
+        if( m_sc_to_init_cmd_inst_fifo.read() ) {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 12);
         } else {
-          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 8);
-        }
-        p_vci_ini.wdata   = r_llsc_to_init_cmd_wdata.read();
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 8);
+        }
+        p_vci_ini.wdata   = r_sc_to_init_cmd_wdata.read();
         p_vci_ini.be      = 0xF;
-        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
-        p_vci_ini.pktid   = m_llsc_to_init_cmd_cache_id_fifo.read();
-        if(r_llsc_to_init_cmd_is_long.read()){
+        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
+        if(r_sc_to_init_cmd_is_long.read()){
             p_vci_ini.plen    = 4 * 4;
             p_vci_ini.eop     = false;
@@ -4821,14 +5834,14 @@
       case INIT_CMD_SC_UPDT_DATA_HIGH:
         p_vci_ini.cmdval  = true;
-        if( m_llsc_to_init_cmd_inst_fifo.read() ) {
-          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 12);
+        if( m_sc_to_init_cmd_inst_fifo.read() ) {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 12);
         } else {
-          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 8);
-        }
-        p_vci_ini.wdata   = r_llsc_to_init_cmd_wdata_high.read();
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 8);
+        }
+        p_vci_ini.wdata   = r_sc_to_init_cmd_wdata_high.read();
         p_vci_ini.be      = 0xF;
         p_vci_ini.plen    = 4 * 4;
-        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
-        p_vci_ini.pktid   = m_llsc_to_init_cmd_cache_id_fifo.read();
+        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
         p_vci_ini.eop     = true;
         break;
@@ -4863,6 +5876,4 @@
       case CLEANUP_RSP:
         {
-            PRINTF("  * <MEM_CACHE.CLEANUP_RSP> Respons to %d.%d\n",(uint32_t)r_cleanup_srcid.read(),(uint32_t)r_cleanup_pktid.read());
-
           p_vci_tgt_cleanup.rspval = true;
           p_vci_tgt_cleanup.rdata  = 0;
@@ -4877,5 +5888,5 @@
     }
 
-  } // end genMoore()
+} // end genMoore()
 
 }} // end name space
