Index: branches/v5/modules/vci_cc_vcache_wrapper/caba/metadata/vci_cc_vcache_wrapper.sd
===================================================================
--- branches/v5/modules/vci_cc_vcache_wrapper/caba/metadata/vci_cc_vcache_wrapper.sd	(revision 346)
+++ branches/v5/modules/vci_cc_vcache_wrapper/caba/metadata/vci_cc_vcache_wrapper.sd	(revision 351)
@@ -3,48 +3,71 @@
 
 Module('caba:vci_cc_vcache_wrapper',
-	classname = 'soclib::caba::VciCcVCacheWrapper',
-	tmpl_parameters = [ parameter.Module('vci_param', default = 'caba:vci_param'),
-	                    parameter.Module('iss_t') ],
-	header_files =         [ '../source/include/vci_cc_vcache_wrapper.h' ],
-	implementation_files = [ '../source/src/vci_cc_vcache_wrapper.cpp' ],
-	uses = [ Uses('caba:base_module'),
-	         Uses('common:mapping_table'),
-	         Uses('common:iss2'),
-	         Uses('caba:multi_write_buffer'),
-	         Uses('caba:generic_fifo'),
-	         Uses('caba:generic_cache_tsar', 
-                       addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', 
-                       parameter.Reference('addr_size'))),
-	         Uses('caba:generic_tlb', 
-                       addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', 
-                       parameter.Reference('addr_size'))),
-	         Uses('common:address_masking_table', 
-                       data_t = parameter.StringExt('sc_dt::sc_uint<%d> ', 
-                       parameter.Reference('addr_size'))) ],
-	ports = [ Port('caba:vci_initiator', 'p_vci_ini_d'),
-	          Port('caba:vci_initiator', 'p_vci_ini_c'),
-	          Port('caba:vci_target', 'p_vci_tgt_d'),
-	          Port('caba:bit_in','p_irq', parameter.Constant('n_irq')),
-	          Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
-	          Port('caba:clock_in', 'p_clk', auto = 'clock'), ],
-	instance_parameters = [ parameter.Int('proc_id'),
-	                        parameter.Module('mt', 'common:mapping_table'),
-	                        parameter.Module('mc', 'common:mapping_table'),
-	                        parameter.IntTab('initiator_rw_index'),
-	                        parameter.IntTab('initiator_c_index'),
-	                        parameter.IntTab('target_index'),
-    	                        parameter.Int('itlb_ways'),
-    	                        parameter.Int('itlb_sets'),
-    	                        parameter.Int('dtlb_ways'),
-    	                        parameter.Int('dtlb_sets'),
-    	                        parameter.Int('icache_ways'),
-    	                        parameter.Int('icache_sets'),
-    	                        parameter.Int('icache_words'),
-    	                        parameter.Int('dcache_ways'),
-    	                        parameter.Int('dcache_sets'),
-    	                        parameter.Int('dcache_words'),
-    	                        parameter.Int('wbuf_nlines'),
-    	                        parameter.Int('wbuf_nwords'),
-    	                        parameter.Int('max_frozen_cycles'), ],
+	    classname = 'soclib::caba::VciCcVCacheWrapper',
+
+	    tmpl_parameters = [
+            parameter.Module('vci_param', default = 'caba:vci_param'),
+	        parameter.Module('iss_t')
+        ],
+
+	    header_files = [ '../source/include/vci_cc_vcache_wrapper.h' ],
+
+	    implementation_files = [ '../source/src/vci_cc_vcache_wrapper.cpp' ],
+
+	    uses = [
+            Uses('caba:base_module'),
+            Uses('common:mapping_table'),
+	        Uses('common:iss2'),
+	        Uses('caba:multi_write_buffer'),
+	        Uses('caba:generic_fifo'),
+	        Uses(
+                'caba:generic_cache_tsar',
+                addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', 
+                parameter.Reference('addr_size'))
+            ),
+            Uses(
+                'caba:generic_tlb', 
+                addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', 
+                parameter.Reference('addr_size'))
+            ),
+            Uses(
+                'common:address_masking_table', 
+                data_t = parameter.StringExt('sc_dt::sc_uint<%d> ', 
+                parameter.Reference('addr_size'))
+            ),
+			Uses(
+                'caba:dspin_dhccp_param'
+			  ),
+        ],
+
+	    ports = [
+            Port('caba:vci_initiator', 'p_vci_ini_d'),
+            Port('caba:dspin_input', 'p_dspin_in', dspin_data_size = 40),
+            Port('caba:dspin_output', 'p_dspin_out', dspin_data_size = 33),
+	        Port('caba:bit_in','p_irq', parameter.Constant('n_irq')),
+	        Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+	        Port('caba:clock_in', 'p_clk', auto = 'clock')
+        ],
+
+	    instance_parameters = [
+            parameter.Int('proc_id'),
+	        parameter.Module('mt', 'common:mapping_table'),
+	        parameter.Module('mc', 'common:mapping_table'),
+	        parameter.IntTab('initiator_rw_index'),
+	        parameter.IntTab('initiator_c_index'),
+	        parameter.IntTab('target_index'),
+    	    parameter.Int('itlb_ways'),
+    	    parameter.Int('itlb_sets'),
+    	    parameter.Int('dtlb_ways'),
+    	    parameter.Int('dtlb_sets'),
+    	    parameter.Int('icache_ways'),
+    	    parameter.Int('icache_sets'),
+    	    parameter.Int('icache_words'),
+    	    parameter.Int('dcache_ways'),
+    	    parameter.Int('dcache_sets'),
+    	    parameter.Int('dcache_words'),
+    	    parameter.Int('wbuf_nlines'),
+    	    parameter.Int('wbuf_nwords'),
+    	    parameter.Int('max_frozen_cycles')
+        ],
 )
 
Index: branches/v5/modules/vci_cc_vcache_wrapper/caba/source/include/vci_cc_vcache_wrapper.h
===================================================================
--- branches/v5/modules/vci_cc_vcache_wrapper/caba/source/include/vci_cc_vcache_wrapper.h	(revision 346)
+++ branches/v5/modules/vci_cc_vcache_wrapper/caba/source/include/vci_cc_vcache_wrapper.h	(revision 351)
@@ -1,3 +1,4 @@
 /* -*- c++ -*-
+ *
  * File : vci_cc_vcache_wrapper.h
  * Copyright (c) UPMC, Lip6, SoC
@@ -6,24 +7,27 @@
  *
  * SOCLIB_LGPL_HEADER_BEGIN
- * 
+ *
  * This file is part of SoCLib, GNU LGPLv2.1.
- * 
+ *
  * SoCLib is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
  * by the Free Software Foundation; version 2.1 of the License.
- * 
+ *
  * SoCLib is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with SoCLib; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301 USA
- * 
+ *
  * SOCLIB_LGPL_HEADER_END
+ *
+ * Maintainers: cesar.fuguet-tortolero@lip6.fr
+ *              alexandre.joannou@lip6.fr
  */
- 
+
 #ifndef SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER_H
 #define SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER_H
@@ -37,5 +41,6 @@
 #include "generic_cache.h"
 #include "vci_initiator.h"
-#include "vci_target.h"
+#include "dspin_interface.h"
+#include "dspin_dhccp_param.h"
 #include "mapping_table.h"
 #include "static_assert.h"
@@ -68,83 +73,83 @@
     typedef typename vci_param::plen_t  vci_plen_t;
 
-    enum icache_fsm_state_e {  
-        ICACHE_IDLE,             
+    enum icache_fsm_state_e {
+        ICACHE_IDLE,
         // handling XTN processor requests
         ICACHE_XTN_TLB_FLUSH,
-        ICACHE_XTN_CACHE_FLUSH, 
-        ICACHE_XTN_CACHE_FLUSH_GO, 
-        ICACHE_XTN_TLB_INVAL,  
+        ICACHE_XTN_CACHE_FLUSH,
+        ICACHE_XTN_CACHE_FLUSH_GO,
+        ICACHE_XTN_TLB_INVAL,
         ICACHE_XTN_CACHE_INVAL_VA,
-        ICACHE_XTN_CACHE_INVAL_PA,  
+        ICACHE_XTN_CACHE_INVAL_PA,
         ICACHE_XTN_CACHE_INVAL_GO,
         // handling tlb miss
         ICACHE_TLB_WAIT,
         // handling cache miss
-        ICACHE_MISS_SELECT,   
-        ICACHE_MISS_CLEAN,   
-        ICACHE_MISS_WAIT,   
-        ICACHE_MISS_DATA_UPDT, 
-        ICACHE_MISS_DIR_UPDT, 
+        ICACHE_MISS_SELECT,
+        ICACHE_MISS_CLEAN,
+        ICACHE_MISS_WAIT,
+        ICACHE_MISS_DATA_UPDT,
+        ICACHE_MISS_DIR_UPDT,
         // handling unc read
-        ICACHE_UNC_WAIT,  
+        ICACHE_UNC_WAIT,
         // handling coherence requests
-        ICACHE_CC_CLACK,
-        ICACHE_CC_CHECK, 
-        ICACHE_CC_INVAL, 
+        ICACHE_CC_CHECK,
+        ICACHE_CC_INVAL,
         ICACHE_CC_UPDT,
-        ICACHE_CC_BROADCAST, 
-    };
-
-    enum dcache_fsm_state_e {  
-        DCACHE_IDLE,                
+        ICACHE_CC_BROADCAST,
+        ICACHE_CC_SEND_WAIT,
+    };
+
+    enum dcache_fsm_state_e {
+        DCACHE_IDLE,
         // handling itlb & dtlb miss
         DCACHE_TLB_MISS,
-        DCACHE_TLB_PTE1_GET,           
-        DCACHE_TLB_PTE1_SELECT,      
-        DCACHE_TLB_PTE1_UPDT,       
-        DCACHE_TLB_PTE2_GET,    
-        DCACHE_TLB_PTE2_SELECT,       
-        DCACHE_TLB_PTE2_UPDT,           
-        DCACHE_TLB_LR_UPDT,           
-        DCACHE_TLB_LR_WAIT,           
-        DCACHE_TLB_RETURN,         
+        DCACHE_TLB_PTE1_GET,
+        DCACHE_TLB_PTE1_SELECT,
+        DCACHE_TLB_PTE1_UPDT,
+        DCACHE_TLB_PTE2_GET,
+        DCACHE_TLB_PTE2_SELECT,
+        DCACHE_TLB_PTE2_UPDT,
+        DCACHE_TLB_LR_UPDT,
+        DCACHE_TLB_LR_WAIT,
+        DCACHE_TLB_RETURN,
 	    // handling processor XTN requests
         DCACHE_XTN_SWITCH,
         DCACHE_XTN_SYNC,
-        DCACHE_XTN_IC_INVAL_VA,        
-        DCACHE_XTN_IC_FLUSH,        
-        DCACHE_XTN_IC_INVAL_PA,     
-        DCACHE_XTN_IT_INVAL,          
-        DCACHE_XTN_DC_FLUSH,        
-        DCACHE_XTN_DC_FLUSH_GO,     
-        DCACHE_XTN_DC_INVAL_VA,        
-        DCACHE_XTN_DC_INVAL_PA,     
+        DCACHE_XTN_IC_INVAL_VA,
+        DCACHE_XTN_IC_FLUSH,
+        DCACHE_XTN_IC_INVAL_PA,
+        DCACHE_XTN_IT_INVAL,
+        DCACHE_XTN_DC_FLUSH,
+        DCACHE_XTN_DC_FLUSH_GO,
+        DCACHE_XTN_DC_INVAL_VA,
+        DCACHE_XTN_DC_INVAL_PA,
         DCACHE_XTN_DC_INVAL_END,
-        DCACHE_XTN_DC_INVAL_GO,          
-        DCACHE_XTN_DT_INVAL,          
+        DCACHE_XTN_DC_INVAL_GO,
+        DCACHE_XTN_DT_INVAL,
         //handling dirty bit update
         DCACHE_DIRTY_GET_PTE,
-        DCACHE_DIRTY_WAIT,           
+        DCACHE_DIRTY_WAIT,
 	    // handling processor miss requests
         DCACHE_MISS_SELECT,
         DCACHE_MISS_CLEAN,
-        DCACHE_MISS_WAIT,           
-        DCACHE_MISS_DATA_UPDT,           
-        DCACHE_MISS_DIR_UPDT,           
+        DCACHE_MISS_WAIT,
+        DCACHE_MISS_DATA_UPDT,
+        DCACHE_MISS_DIR_UPDT,
         // handling processor unc, ll and sc requests
-        DCACHE_UNC_WAIT,            
-        DCACHE_LL_WAIT,            
-        DCACHE_SC_WAIT,            
+        DCACHE_UNC_WAIT,
+        DCACHE_LL_WAIT,
+        DCACHE_SC_WAIT,
         // handling coherence requests
-        DCACHE_CC_CLACK,            
-        DCACHE_CC_CHECK,            
-        DCACHE_CC_INVAL,            
-        DCACHE_CC_UPDT,             
-        DCACHE_CC_BROADCAST,        
+        DCACHE_CC_CHECK,
+        DCACHE_CC_INVAL,
+        DCACHE_CC_UPDT,
+        DCACHE_CC_BROADCAST,
+        DCACHE_CC_SEND_WAIT,
         // handling TLB inval (after a coherence or XTN request)
-        DCACHE_INVAL_TLB_SCAN,             
-    };
-
-    enum cmd_fsm_state_e {      
+        DCACHE_INVAL_TLB_SCAN,
+    };
+
+    enum cmd_fsm_state_e {
         CMD_IDLE,
         CMD_INS_MISS,
@@ -155,8 +160,8 @@
         CMD_DATA_LL,
         CMD_DATA_SC,
-        CMD_DATA_CAS, 
-    };
-
-    enum rsp_fsm_state_e {       
+        CMD_DATA_CAS,
+    };
+
+    enum rsp_fsm_state_e {
         RSP_IDLE,
         RSP_INS_MISS,
@@ -168,27 +173,21 @@
     };
 
-    enum cleanup_cmd_fsm_state_e {
-        CLEANUP_CMD_DATA_IDLE,
-        CLEANUP_CMD_DATA_GO,
-        CLEANUP_CMD_INS_IDLE,
-        CLEANUP_CMD_INS_GO,
-    };
-
-    enum cleanup_rsp_fsm_state_e {
-        CLEANUP_RSP_IDLE,
-        CLEANUP_RSP_DATA,
-        CLEANUP_RSP_INS,
-    };
-
-    enum tgt_fsm_state_e {  
-        TGT_IDLE,
-        TGT_UPDT_WORD,
-        TGT_UPDT_DATA,
-        TGT_REQ_BROADCAST,
-        TGT_REQ_ICACHE,
-        TGT_REQ_DCACHE,
-        TGT_RSP_BROADCAST,
-        TGT_RSP_ICACHE, 
-        TGT_RSP_DCACHE,
+    enum cc_receive_fsm_state_e {
+        CC_RECEIVE_IDLE,
+        CC_RECEIVE_CLACK,
+        CC_RECEIVE_BRDCAST_HEADER,
+        CC_RECEIVE_BRDCAST_NLINE,
+        CC_RECEIVE_INVAL_HEADER,
+        CC_RECEIVE_INVAL_NLINE,
+        CC_RECEIVE_UPDT_HEADER,
+        CC_RECEIVE_UPDT_NLINE,
+        CC_RECEIVE_UPDT_DATA,
+    };
+
+    enum cc_send_fsm_state_e {
+        CC_SEND_IDLE,
+        CC_SEND_CLEANUP_1,
+        CC_SEND_CLEANUP_2,
+        CC_SEND_MULTI_ACK,
     };
 
@@ -201,5 +200,5 @@
         //  b1 DATA / INS
         //  b0 UNC / MISS
-        // else 
+        // else
         //  b1 accÃšs table llsc type SW / other
         //  b2 WRITE/CAS/LL/SC
@@ -213,5 +212,5 @@
         TYPE_SC                     = 0x7
     };
-    
+
     /* SC return values */
     enum sc_status_type_e
@@ -221,15 +220,20 @@
     };
 
-    // coherence request type
+    // cc_send_type
+    typedef enum {
+        CC_TYPE_CLEANUP,
+        CC_TYPE_MULTI_ACK,
+    } cc_send_t;
+
+    // cc_receive_type
+    typedef enum {
+        CC_TYPE_CLACK,
+        CC_TYPE_BRDCAST,
+        CC_TYPE_INVAL,
+        CC_TYPE_UPDT,
+    } cc_receive_t;
+
+    // TLB Mode : ITLB / DTLB / ICACHE / DCACHE
     enum {
-        CC_TYPE_INVAL_DATA,
-        CC_TYPE_INVAL_INS,
-        CC_TYPE_UPDT_DATA,
-        CC_TYPE_UPDT_INS,
-        CC_TYPE_BROADCAST,
-    };
-
-    // TLB Mode : ITLB / DTLB / ICACHE / DCACHE
-    enum {          
         INS_TLB_MASK    = 0x8,
         DATA_TLB_MASK   = 0x4,
@@ -239,23 +243,23 @@
 
     // Error Type
-    enum mmu_error_type_e 
+    enum mmu_error_type_e
     {
         MMU_NONE                      = 0x0000, // None
-        MMU_WRITE_PT1_UNMAPPED 	      = 0x0001, // Write & Page fault on PT1          
-        MMU_WRITE_PT2_UNMAPPED 	      = 0x0002, // Write & Page fault on PT2          
-        MMU_WRITE_PRIVILEGE_VIOLATION = 0x0004, // Write & Protected access in user mode      
+        MMU_WRITE_PT1_UNMAPPED 	      = 0x0001, // Write & Page fault on PT1
+        MMU_WRITE_PT2_UNMAPPED 	      = 0x0002, // Write & Page fault on PT2
+        MMU_WRITE_PRIVILEGE_VIOLATION = 0x0004, // Write & Protected access in user mode
         MMU_WRITE_ACCES_VIOLATION     = 0x0008, // Write to non writable page
-        MMU_WRITE_UNDEFINED_XTN       = 0x0020, // Write & undefined external access  
-        MMU_WRITE_PT1_ILLEGAL_ACCESS  = 0x0040, // Write & Bus Error accessing PT1       
-        MMU_WRITE_PT2_ILLEGAL_ACCESS  = 0x0080, // Write & Bus Error accessing PT2      
-        MMU_WRITE_DATA_ILLEGAL_ACCESS = 0x0100, // Write & Bus Error in cache access     
-        MMU_READ_PT1_UNMAPPED 	      = 0x1001, // Read & Page fault on PT1  	
-        MMU_READ_PT2_UNMAPPED 	      = 0x1002, // Read & Page fault on PT2  
-        MMU_READ_PRIVILEGE_VIOLATION  = 0x1004, // Read & Protected access in user mode 
-        MMU_READ_EXEC_VIOLATION       = 0x1010, // Read & Exec access to a non exec page 
-        MMU_READ_UNDEFINED_XTN 	      = 0x1020, // Read & Undefined external access  
-        MMU_READ_PT1_ILLEGAL_ACCESS   = 0x1040, // Read & Bus Error accessing PT1      
-        MMU_READ_PT2_ILLEGAL_ACCESS   = 0x1080, // Read & Bus Error accessing PT2 	
-        MMU_READ_DATA_ILLEGAL_ACCESS  = 0x1100, // Read & Bus Error in cache access 
+        MMU_WRITE_UNDEFINED_XTN       = 0x0020, // Write & undefined external access
+        MMU_WRITE_PT1_ILLEGAL_ACCESS  = 0x0040, // Write & Bus Error accessing PT1
+        MMU_WRITE_PT2_ILLEGAL_ACCESS  = 0x0080, // Write & Bus Error accessing PT2
+        MMU_WRITE_DATA_ILLEGAL_ACCESS = 0x0100, // Write & Bus Error in cache access
+        MMU_READ_PT1_UNMAPPED 	      = 0x1001, // Read & Page fault on PT1
+        MMU_READ_PT2_UNMAPPED 	      = 0x1002, // Read & Page fault on PT2
+        MMU_READ_PRIVILEGE_VIOLATION  = 0x1004, // Read & Protected access in user mode
+        MMU_READ_EXEC_VIOLATION       = 0x1010, // Read & Exec access to a non exec page
+        MMU_READ_UNDEFINED_XTN 	      = 0x1020, // Read & Undefined external access
+        MMU_READ_PT1_ILLEGAL_ACCESS   = 0x1040, // Read & Bus Error accessing PT1
+        MMU_READ_PT2_ILLEGAL_ACCESS   = 0x1080, // Read & Bus Error accessing PT2
+        MMU_READ_DATA_ILLEGAL_ACCESS  = 0x1100, // Read & Bus Error in cache access
     };
 
@@ -263,7 +267,7 @@
     enum dcache_miss_type_e
     {
-        PTE1_MISS, 
+        PTE1_MISS,
         PTE2_MISS,
-        PROC_MISS,  
+        PROC_MISS,
     };
 
@@ -282,39 +286,35 @@
     sc_in<bool>                             p_resetn;
     sc_in<bool>                             p_irq[iss_t::n_irq];
-    soclib::caba::VciInitiator<vci_param>   p_vci_ini_d;
-    soclib::caba::VciInitiator<vci_param>   p_vci_ini_c;
-    soclib::caba::VciTarget<vci_param>      p_vci_tgt_c;
+    soclib::caba::VciInitiator<vci_param>   p_vci;
+    soclib::caba::DspinInput <40>           p_dspin_in;
+    soclib::caba::DspinOutput<33>           p_dspin_out;
 
 private:
 
     // STRUCTURAL PARAMETERS
-    soclib::common::AddressDecodingTable<uint32_t, bool>    	m_cacheability_table;
-    const soclib::common::Segment                           	m_segment;
-    const vci_srcid_t                                       	m_srcid_d;
-    const vci_srcid_t                                       	m_srcid_c;
-
+    soclib::common::AddressDecodingTable<uint32_t, bool> m_cacheability_table;
+
+    const vci_srcid_t                   m_srcid;
+    const size_t                        m_cc_global_id;
+    const size_t                        m_nline_width;
     const size_t  						m_itlb_ways;
     const size_t  						m_itlb_sets;
-
     const size_t  						m_dtlb_ways;
     const size_t  						m_dtlb_sets;
-
     const size_t  						m_icache_ways;
     const size_t  						m_icache_sets;
     const paddr_t 						m_icache_yzmask;
     const size_t  						m_icache_words;
-
     const size_t  						m_dcache_ways;
     const size_t  						m_dcache_sets;
     const paddr_t 						m_dcache_yzmask;
     const size_t  						m_dcache_words;
-
     const size_t                        m_x_width;
     const size_t                        m_y_width;
-
-    const size_t                        m_memory_cache_local_id;
     const size_t                        m_proc_id;
     const uint32_t						m_max_frozen_cycles;
-    const size_t  						m_paddr_nbits;  
+    const size_t  						m_paddr_nbits;
+    uint32_t                            m_debug_start_cycle;
+    bool                                m_debug_ok;
 
     ////////////////////////////////////////
@@ -329,11 +329,8 @@
     // debug variables (for each FSM)
     /////////////////////////////////////////////
-    uint32_t                            m_debug_start_cycle;
-    bool                                m_debug_ok;
     bool                                m_debug_previous_hit;
     bool                                m_idebug_previous_hit;
     bool                                m_debug_dcache_fsm;
     bool                                m_debug_icache_fsm;
-    bool                                m_debug_cleanup_fsm;
     bool                                m_debug_inval_itlb_fsm;
     bool                                m_debug_inval_dtlb_fsm;
@@ -359,10 +356,10 @@
     sc_signal<int>          r_icache_fsm;               // state register
     sc_signal<int>          r_icache_fsm_save;          // return state for coherence op
-    sc_signal<paddr_t>      r_icache_vci_paddr;      	// physical address 
+    sc_signal<paddr_t>      r_icache_vci_paddr;      	// physical address
     sc_signal<uint32_t>     r_icache_vaddr_save;        // virtual address from processor
 
     // icache miss handling
     sc_signal<size_t>       r_icache_miss_way;		    // selected way for cache update
-    sc_signal<size_t>       r_icache_miss_set;		    // selected set for cache update 
+    sc_signal<size_t>       r_icache_miss_set;		    // selected set for cache update
     sc_signal<size_t>       r_icache_miss_word;		    // word index ( cache update)
     sc_signal<bool>         r_icache_miss_inval;        // coherence request matching a miss
@@ -373,4 +370,5 @@
     sc_signal<size_t>       r_icache_cc_set;		    // selected set for cc update/inval
     sc_signal<size_t>       r_icache_cc_word;		    // word counter for cc update
+    sc_signal<bool>         r_icache_cc_need_write;     // activate the cache for writing
 
     // icache flush handling
@@ -383,10 +381,12 @@
     // communication between ICACHE FSM and DCACHE FSM
     sc_signal<bool>	        r_icache_tlb_miss_req;       // (set icache/reset dcache)
-    sc_signal<bool>         r_icache_tlb_rsp_error;      // tlb miss response error 
-
-    // communication between ICACHE FSM and CLEANUP FSMs
-    sc_signal<bool>         r_icache_cleanup_req;        // ICACHE cleanup request
-    sc_signal<paddr_t>      r_icache_cleanup_line;       // ICACHE cleanup NLINE
-    sc_signal<size_t>       r_icache_cleanup_way;        // ICACHE cleanup way 
+    sc_signal<bool>         r_icache_tlb_rsp_error;      // tlb miss response error
+
+    // communication between ICACHE FSM and CC_SEND FSM
+    sc_signal<bool>         r_icache_cc_send_req;           // ICACHE cc_send request
+    sc_signal<cc_send_t>    r_icache_cc_send_type;          // ICACHE cc_send request type
+    sc_signal<paddr_t>      r_icache_cc_send_nline;         // ICACHE cc_send nline
+    sc_signal<size_t>       r_icache_cc_send_way;           // ICACHE cc_send way
+    sc_signal<size_t>       r_icache_cc_send_updt_tab_idx;  // ICACHE cc_send update table index
 
     ///////////////////////////////
@@ -402,11 +402,11 @@
     sc_signal<uint32_t>     r_dcache_save_wdata;        // write data (from proc)
     sc_signal<vci_be_t>     r_dcache_save_be;           // byte enable (from proc)
-    sc_signal<paddr_t>      r_dcache_save_paddr;        // physical address 
-    sc_signal<bool>         r_dcache_save_cacheable;	// address cacheable 
-    sc_signal<size_t>       r_dcache_save_cache_way;	// selected way (from dcache) 
-    sc_signal<size_t>       r_dcache_save_cache_set;	// selected set (from dcache)    
-    sc_signal<size_t>       r_dcache_save_cache_word;	// selected word (from dcache)    
+    sc_signal<paddr_t>      r_dcache_save_paddr;        // physical address
+    sc_signal<bool>         r_dcache_save_cacheable;	// address cacheable
+    sc_signal<size_t>       r_dcache_save_cache_way;	// selected way (from dcache)
+    sc_signal<size_t>       r_dcache_save_cache_set;	// selected set (from dcache)
+    sc_signal<size_t>       r_dcache_save_cache_word;	// selected word (from dcache)
     // registers used by the Dirty bit sub-fsm
-    sc_signal<paddr_t>      r_dcache_dirty_paddr;       // PTE physical address 
+    sc_signal<paddr_t>      r_dcache_dirty_paddr;       // PTE physical address
     sc_signal<size_t>       r_dcache_dirty_way;	        // way to invalidate in dcache
     sc_signal<size_t>       r_dcache_dirty_set;	        // set to invalidate in dcache
@@ -425,6 +425,6 @@
 
     // register used for XTN inval
-    sc_signal<size_t>       r_dcache_xtn_way;		    // selected way (from dcache) 
-    sc_signal<size_t>       r_dcache_xtn_set;		    // selected set (from dcache)    
+    sc_signal<size_t>       r_dcache_xtn_way;		    // selected way (from dcache)
+    sc_signal<size_t>       r_dcache_xtn_set;		    // selected set (from dcache)
 
     // write buffer state extension
@@ -443,4 +443,5 @@
     sc_signal<size_t>       r_dcache_cc_set;		    // selected set for cc update/inval
     sc_signal<size_t>       r_dcache_cc_word;		    // word counter for cc update
+    sc_signal<bool>         r_dcache_cc_need_write;     // activate the cache for writing
 
     // dcache flush handling
@@ -456,12 +457,12 @@
     sc_signal<uint32_t>     r_dcache_tlb_pte_flags;	    // pte1 or first word of pte2
     sc_signal<uint32_t>     r_dcache_tlb_pte_ppn;	    // second word of pte2
-    sc_signal<size_t>       r_dcache_tlb_cache_way;	    // selected way in dcache 
-    sc_signal<size_t>       r_dcache_tlb_cache_set;	    // selected set in dcache 
+    sc_signal<size_t>       r_dcache_tlb_cache_way;	    // selected way in dcache
+    sc_signal<size_t>       r_dcache_tlb_cache_set;	    // selected set in dcache
     sc_signal<size_t>       r_dcache_tlb_cache_word;	// selected word in dcache
-    sc_signal<size_t>       r_dcache_tlb_way;		    // selected way in tlb    
-    sc_signal<size_t>       r_dcache_tlb_set;		    // selected set in tlb    
+    sc_signal<size_t>       r_dcache_tlb_way;		    // selected way in tlb
+    sc_signal<size_t>       r_dcache_tlb_set;		    // selected set in tlb
 
     // ITLB and DTLB invalidation
-    sc_signal<paddr_t>      r_dcache_tlb_inval_line;	// line index 
+    sc_signal<paddr_t>      r_dcache_tlb_inval_line;	// line index
     sc_signal<size_t>       r_dcache_tlb_inval_set;     // tlb set counter
 
@@ -470,8 +471,10 @@
     sc_signal<int>          r_dcache_xtn_opcode;        // xtn request type
 
-    // communication between DCACHE FSM and CLEANUP FSMs
-    sc_signal<bool>         r_dcache_cleanup_req;       // DCACHE cleanup request
-    sc_signal<paddr_t>      r_dcache_cleanup_line;      // DCACHE cleanup nline
-    sc_signal<size_t>       r_dcache_cleanup_way;       // DCACHE cleanup way 
+    // communication between DCACHE FSM and CC_SEND FSM
+    sc_signal<bool>         r_dcache_cc_send_req;           // DCACHE cc_send request
+    sc_signal<cc_send_t>    r_dcache_cc_send_type;          // DCACHE cc_send request type
+    sc_signal<paddr_t>      r_dcache_cc_send_nline;         // DCACHE cc_send nline
+    sc_signal<size_t>       r_dcache_cc_send_way;           // DCACHE cc_send way
+    sc_signal<size_t>       r_dcache_cc_send_updt_tab_idx;  // DCACHE cc_send update table index
 
     // dcache directory extension
@@ -483,7 +486,7 @@
     ///////////////////////////////////
     sc_signal<int>          r_vci_cmd_fsm;
-    sc_signal<size_t>       r_vci_cmd_min;      	    // used for write bursts 
-    sc_signal<size_t>       r_vci_cmd_max;      	    // used for write bursts 
-    sc_signal<size_t>       r_vci_cmd_cpt;    		    // used for write bursts 
+    sc_signal<size_t>       r_vci_cmd_min;      	    // used for write bursts
+    sc_signal<size_t>       r_vci_cmd_max;      	    // used for write bursts
+    sc_signal<size_t>       r_vci_cmd_cpt;    		    // used for write bursts
     sc_signal<bool>         r_vci_cmd_imiss_prio;	    // round-robin between imiss & dmiss
 
@@ -499,46 +502,42 @@
 
     ///////////////////////////////////
-    //  CLEANUP_CMD FSM REGISTER
+    //  CC_SEND FSM REGISTER
     ///////////////////////////////////
-    sc_signal<int>          r_cleanup_cmd_fsm;          // state register
-    sc_signal<size_t>       r_cleanup_cmd_trdid;        // contains way & data/ins flag
+    sc_signal<int>          r_cc_send_fsm;          // state register
+    sc_signal<bool>         r_cc_send_last_client;  // round robin flip-flop : 0 dcache / 1 icache
 
     ///////////////////////////////////
-    //  CLEANUP_RSP FSM REGISTER
+    //  CC_RECEIVE FSM REGISTER
     ///////////////////////////////////
-    sc_signal<int>          r_cleanup_rsp_fsm;          // state register
-    sc_signal<bool>         r_cleanup_icache_req;       // cleanup_rsp to icache request  
-    sc_signal<size_t>       r_cleanup_icache_way;       // cleanup_rsp to icache way      
-    sc_signal<size_t>       r_cleanup_icache_set;       // cleanup_rsp to icache set
-    sc_signal<bool>         r_cleanup_dcache_req;       // cleanup_rsp to dcache request  
-    sc_signal<size_t>       r_cleanup_dcache_way;       // cleanup_rsp to dcache way      
-    sc_signal<size_t>       r_cleanup_dcache_set;       // cleanup_rsp to dcache set
-
-    ///////////////////////////////////
-    //  TGT FSM REGISTERS
-    ///////////////////////////////////
-    sc_signal<int>          r_tgt_fsm;			        // state register
-    sc_signal<paddr_t>      r_tgt_paddr;		        // cache line physical address
-    sc_signal<size_t>       r_tgt_word_count;		    // word index
-    sc_signal<size_t>       r_tgt_word_min;		        // index of the first word 
-    sc_signal<size_t>       r_tgt_word_max;		        // index of the last word 
-    sc_signal<int>          r_tgt_cc_type;	            // type of coherence request
-    sc_signal<vci_srcid_t>  r_tgt_srcid;
-    sc_signal<vci_pktid_t>  r_tgt_pktid;
-    sc_signal<vci_trdid_t>  r_tgt_trdid;
-    uint32_t                *r_tgt_buf;			        // cache line word buffer 
-    vci_be_t                *r_tgt_be;			        // cache line be buffer 
-
-    // communications between TGT FSM and DCACHE/ICACHE FSMs
-    sc_signal<bool>         r_tgt_icache_req;		    // coherence request (set by tgt)
-    sc_signal<bool>         r_tgt_dcache_req;		    // coherence request (set by tgt)
-    sc_signal<bool>         r_icache_tgt_need_rsp;      // response required (set by icache)
-    sc_signal<bool>         r_dcache_tgt_need_rsp;      // response required (set by dcache)
+    sc_signal<int>          r_cc_receive_fsm;          // state register
+    sc_signal<bool>         r_cc_receive_data_ins;     // request concerning : 0 dcache / 1 icache
+
+    // communication cc updt FIFO between CC_RECEIVE FSM and ICACHE/DCACHE FSM
+    sc_signal<size_t>       r_cc_receive_word_idx;  // word index
+    GenericFifo<uint32_t>   r_cc_receive_updt_fifo_be;
+    GenericFifo<uint32_t>   r_cc_receive_updt_fifo_data;
+    GenericFifo<bool>       r_cc_receive_updt_fifo_eop;
+
+    // communication between CC_RECEIVE FSM and ICACHE FSM
+    sc_signal<bool>         r_cc_receive_icache_req;       // cc_receive to icache request
+    sc_signal<cc_receive_t> r_cc_receive_icache_type;      // cc_receive type of coherence request
+    sc_signal<size_t>       r_cc_receive_icache_way;       // cc_receive to icache way
+    sc_signal<size_t>       r_cc_receive_icache_set;       // cc_receive to icache set
+    sc_signal<size_t>       r_cc_receive_icache_updt_tab_idx;  // cc_receive update table index
+    sc_signal<paddr_t>      r_cc_receive_icache_nline;	   // cache line physical address
+
+    // communication between CC_RECEIVE FSM and DCACHE FSM
+    sc_signal<bool>         r_cc_receive_dcache_req;       // cc_receive to dcache request
+    sc_signal<cc_receive_t> r_cc_receive_dcache_type;      // cc_receive type of coherence request
+    sc_signal<size_t>       r_cc_receive_dcache_way;       // cc_receive to dcache way
+    sc_signal<size_t>       r_cc_receive_dcache_set;       // cc_receive to dcache set
+    sc_signal<size_t>       r_cc_receive_dcache_updt_tab_idx;  // cc_receive update table index
+    sc_signal<paddr_t>      r_cc_receive_dcache_nline;	   // cache line physical address
 
     //////////////////////////////////////////////////////////////////
-    // processor, write buffer, caches , TLBs and CAM for cleanups 
+    // processor, write buffer, caches , TLBs
     //////////////////////////////////////////////////////////////////
 
-    iss_t                       r_iss;   
+    iss_t                       r_iss;
     MultiWriteBuffer<paddr_t>	r_wbuf;
     GenericCache<paddr_t>   	r_icache;
@@ -582,5 +581,5 @@
     uint32_t m_cpt_ins_spc_miss;            // number of speculative instruction miss
 
-    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
+    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer
     uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
     uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
@@ -597,5 +596,5 @@
     uint32_t m_cost_unc_transaction;        // cumulated duration for VCI UNC transactions
     uint32_t m_cost_write_transaction;      // cumulated duration for VCI WRITE transactions
-    uint32_t m_cost_icache_unc_transaction; // cumulated duration for VCI IUNC transactions    
+    uint32_t m_cost_icache_unc_transaction; // cumulated duration for VCI IUNC transactions
     uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions
 
@@ -603,16 +602,16 @@
     uint32_t m_cpt_ins_tlb_read;            // number of instruction tlb read
     uint32_t m_cpt_ins_tlb_miss;            // number of instruction tlb miss
-    uint32_t m_cpt_ins_tlb_update_acc;      // number of instruction tlb update 
-    uint32_t m_cpt_ins_tlb_occup_cache;     // number of instruction tlb occupy data cache line 
+    uint32_t m_cpt_ins_tlb_update_acc;      // number of instruction tlb update
+    uint32_t m_cpt_ins_tlb_occup_cache;     // number of instruction tlb occupy data cache line
     uint32_t m_cpt_ins_tlb_hit_dcache;      // number of instruction tlb hit in data cache
 
     uint32_t m_cpt_data_tlb_read;           // number of data tlb read
     uint32_t m_cpt_data_tlb_miss;           // number of data tlb miss
-    uint32_t m_cpt_data_tlb_update_acc;     // number of data tlb update 
+    uint32_t m_cpt_data_tlb_update_acc;     // number of data tlb update
     uint32_t m_cpt_data_tlb_update_dirty;   // number of data tlb update dirty
     uint32_t m_cpt_data_tlb_hit_dcache;     // number of data tlb hit in data cache
     uint32_t m_cpt_data_tlb_occup_cache;    // number of data tlb occupy data cache line
     uint32_t m_cpt_tlb_occup_dcache;
-    
+
     uint32_t m_cost_ins_tlb_miss_frz;       // number of frozen cycles related to instruction tlb miss
     uint32_t m_cost_data_tlb_miss_frz;      // number of frozen cycles related to data tlb miss
@@ -647,5 +646,5 @@
     uint32_t m_cpt_cc_inval_dcache;             // number of coherence inval data commands
     uint32_t m_cpt_cc_broadcast;                // number of coherence broadcast commands
-    
+
     uint32_t m_cost_updt_data_frz;              // number of frozen cycles related to coherence update data packets
     uint32_t m_cost_inval_ins_frz;              // number of frozen cycles related to coherence inval instruction packets
@@ -664,5 +663,5 @@
     uint32_t m_cpt_ins_tlb_inval;           // number of ins tlb invalidate
 
-    uint32_t m_cost_data_tlb_inval_frz;     // number of frozen cycles related to checking data tlb invalidate    
+    uint32_t m_cost_data_tlb_inval_frz;     // number of frozen cycles related to checking data tlb invalidate
     uint32_t m_cpt_data_tlb_inval;          // number of data tlb invalidate
 
@@ -672,7 +671,6 @@
     uint32_t m_cpt_fsm_cmd        [64];
     uint32_t m_cpt_fsm_rsp        [64];
-    uint32_t m_cpt_fsm_tgt        [64];
-    uint32_t m_cpt_fsm_cmd_cleanup[64];
-    uint32_t m_cpt_fsm_rsp_cleanup[64];
+    uint32_t m_cpt_fsm_cc_receive [64];
+    uint32_t m_cpt_fsm_cc_send    [64];
 
     uint32_t m_cpt_stop_simulation;		// used to stop simulation if frozen
@@ -683,29 +681,26 @@
 public:
     VciCcVCacheWrapper(
-        sc_module_name insname,
-        int proc_id,
-        const soclib::common::MappingTable &mtp,
-        const soclib::common::MappingTable &mtc,
-        const soclib::common::IntTab &initiator_index_d,
-        const soclib::common::IntTab &initiator_index_c,
-        const soclib::common::IntTab &target_index_d,
-        size_t   itlb_ways,
-        size_t   itlb_sets,
-        size_t   dtlb_ways,
-        size_t   dtlb_sets,
-        size_t   icache_ways,
-        size_t   icache_sets,
-        size_t   icache_words,
-        size_t   dcache_ways,
-        size_t   dcache_sets,
-        size_t   dcache_words,
-        size_t   wbuf_nlines, 
-        size_t   wbuf_nwords, 
-        size_t   x_width,
-        size_t   y_width,
-        uint32_t memory_cache_local_id,
-        uint32_t max_frozen_cycles,
-        uint32_t debug_start_cycle,
-        bool     debug_ok);
+        sc_module_name                      name,
+        const int                           proc_id,
+        const soclib::common::MappingTable  &mtd,
+        const soclib::common::IntTab        &srcid,
+        const size_t                        cc_global_id,
+        const size_t                        itlb_ways,
+        const size_t                        itlb_sets,
+        const size_t                        dtlb_ways,
+        const size_t                        dtlb_sets,
+        const size_t                        icache_ways,
+        const size_t                        icache_sets,
+        const size_t                        icache_words,
+        const size_t                        dcache_ways,
+        const size_t                        dcache_sets,
+        const size_t                        dcache_words,
+        const size_t                        wbuf_nlines,
+        const size_t                        wbuf_nwords,
+        const size_t                        x_width,
+        const size_t                        y_width,
+        const uint32_t                      max_frozen_cycles,
+        const uint32_t                      debug_start_cycle,
+        const bool                          debug_ok );
 
     ~VciCcVCacheWrapper();
@@ -740,6 +735,2 @@
 
 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
-
-
-
-
Index: branches/v5/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp
===================================================================
--- branches/v5/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp	(revision 346)
+++ branches/v5/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp	(revision 351)
@@ -5,21 +5,21 @@
  *
  * SOCLIB_LGPL_HEADER_BEGIN
- * 
+ *
  * This file is part of SoCLib, GNU LGPLv2.1.
- * 
+ *
  * SoCLib is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
  * by the Free Software Foundation; version 2.1 of the License.
- * 
+ *
  * SoCLib is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with SoCLib; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301 USA
- * 
+ *
  * SOCLIB_LGPL_HEADER_END
  *
@@ -36,5 +36,5 @@
 #define DEBUG_CLEANUP		0
 
-namespace soclib { 
+namespace soclib {
 namespace caba {
 
@@ -42,9 +42,9 @@
 const char *icache_fsm_state_str[] = {
         "ICACHE_IDLE",
-     
-        "ICACHE_XTN_TLB_FLUSH", 
-        "ICACHE_XTN_CACHE_FLUSH", 
-        "ICACHE_XTN_CACHE_FLUSH_GO", 
-        "ICACHE_XTN_TLB_INVAL",  
+
+        "ICACHE_XTN_TLB_FLUSH",
+        "ICACHE_XTN_CACHE_FLUSH",
+        "ICACHE_XTN_CACHE_FLUSH_GO",
+        "ICACHE_XTN_TLB_INVAL",
         "ICACHE_XTN_CACHE_INVAL_VA",
         "ICACHE_XTN_CACHE_INVAL_PA",
@@ -59,35 +59,35 @@
         "ICACHE_MISS_DIR_UPDT",
 
-        "ICACHE_UNC_WAIT",  
-
-        "ICACHE_CC_CLACK", 
-        "ICACHE_CC_CHECK", 
-        "ICACHE_CC_INVAL", 
-        "ICACHE_CC_UPDT", 
+        "ICACHE_UNC_WAIT",
+
+        "ICACHE_CC_CHECK",
+        "ICACHE_CC_INVAL",
+        "ICACHE_CC_UPDT",
         "ICACHE_CC_BROADCAST",
+        "ICACHE_CC_SEND_WAIT",
     };
 
 const char *dcache_fsm_state_str[] = {
-        "DCACHE_IDLE",       
+        "DCACHE_IDLE",
 
         "DCACHE_TLB_MISS",
         "DCACHE_TLB_PTE1_GET",
-        "DCACHE_TLB_PTE1_SELECT",  
-        "DCACHE_TLB_PTE1_UPDT", 
-        "DCACHE_TLB_PTE2_GET", 
+        "DCACHE_TLB_PTE1_SELECT",
+        "DCACHE_TLB_PTE1_UPDT",
+        "DCACHE_TLB_PTE2_GET",
         "DCACHE_TLB_PTE2_SELECT",
-        "DCACHE_TLB_PTE2_UPDT",   
+        "DCACHE_TLB_PTE2_UPDT",
         "DCACHE_TLB_LR_UPDT",
         "DCACHE_TLB_LR_WAIT",
         "DCACHE_TLB_RETURN",
 
-        "DCACHE_XTN_SWITCH", 
-        "DCACHE_XTN_SYNC", 
+        "DCACHE_XTN_SWITCH",
+        "DCACHE_XTN_SYNC",
         "DCACHE_XTN_IC_INVAL_VA",
-        "DCACHE_XTN_IC_FLUSH", 
+        "DCACHE_XTN_IC_FLUSH",
         "DCACHE_XTN_IC_INVAL_PA",
         "DCACHE_XTN_IT_INVAL",
-        "DCACHE_XTN_DC_FLUSH", 
-        "DCACHE_XTN_DC_FLUSH_GO", 
+        "DCACHE_XTN_DC_FLUSH",
+        "DCACHE_XTN_DC_FLUSH_GO",
         "DCACHE_XTN_DC_INVAL_VA",
         "DCACHE_XTN_DC_INVAL_PA",
@@ -97,21 +97,21 @@
 
         "DCACHE_DIRTY_PTE_GET",
-        "DCACHE_DIRTY_WAIT",  
+        "DCACHE_DIRTY_WAIT",
 
         "DCACHE_MISS_SELECT",
         "DCACHE_MISS_CLEAN",
-        "DCACHE_MISS_WAIT",  
-        "DCACHE_MISS_DATA_UPDT",  
-        "DCACHE_MISS_DIR_UPDT",  
-
-        "DCACHE_UNC_WAIT",   
-        "DCACHE_LL_WAIT",   
-        "DCACHE_SC_WAIT",   
-
-        "DCACHE_CC_CLACK",
+        "DCACHE_MISS_WAIT",
+        "DCACHE_MISS_DATA_UPDT",
+        "DCACHE_MISS_DIR_UPDT",
+
+        "DCACHE_UNC_WAIT",
+        "DCACHE_LL_WAIT",
+        "DCACHE_SC_WAIT",
+
         "DCACHE_CC_CHECK",
         "DCACHE_CC_INVAL",
         "DCACHE_CC_UPDT",
         "DCACHE_CC_BROADCAST",
+        "DCACHE_CC_SEND_WAIT",
 
         "DCACHE_INVAL_TLB_SCAN",
@@ -119,115 +119,104 @@
 
 const char *cmd_fsm_state_str[] = {
-        "CMD_IDLE",           
-        "CMD_INS_MISS",     
-        "CMD_INS_UNC",     
-        "CMD_DATA_MISS",    
-        "CMD_DATA_UNC",     
-        "CMD_DATA_WRITE", 
+        "CMD_IDLE",
+        "CMD_INS_MISS",
+        "CMD_INS_UNC",
+        "CMD_DATA_MISS",
+        "CMD_DATA_UNC",
+        "CMD_DATA_WRITE",
         "CMD_DATA_LL",
         "CMD_DATA_SC",
-        "CMD_DATA_CAS", 
+        "CMD_DATA_CAS",
     };
 
 const char *rsp_fsm_state_str[] = {
-        "RSP_IDLE",                  
-        "RSP_INS_MISS",   
-        "RSP_INS_UNC",           
-        "RSP_DATA_MISS",             
-        "RSP_DATA_UNC",              
+        "RSP_IDLE",
+        "RSP_INS_MISS",
+        "RSP_INS_UNC",
+        "RSP_DATA_MISS",
+        "RSP_DATA_UNC",
         "RSP_DATA_LL",
-        "RSP_DATA_WRITE",     
+        "RSP_DATA_WRITE",
     };
 
-const char *cleanup_fsm_state_str[] = {
-        "CLEANUP_DATA_IDLE",           
-        "CLEANUP_DATA_GO",    
-        "CLEANUP_INS_IDLE",      
-        "CLEANUP_INS_GO",      
+const char *cc_receive_fsm_state_str[] = {
+        "CC_RECEIVE_IDLE",
+        "CC_RECEIVE_CLACK",
+        "CC_RECEIVE_BRDCAST_HEADER",
+        "CC_RECEIVE_BRDCAST_NLINE",
+        "CC_RECEIVE_INVAL_HEADER",
+        "CC_RECEIVE_INVAL_NLINE",
+        "CC_RECEIVE_UPDT_HEADER",
+        "CC_RECEIVE_UPDT_NLINE",
+        "CC_RECEIVE_UPDT_DATA",
     };
 
-const char *tgt_fsm_state_str[] = {
-        "TGT_IDLE",
-        "TGT_UPDT_WORD",
-        "TGT_UPDT_DATA",
-        "TGT_REQ_BROADCAST",
-        "TGT_REQ_ICACHE",
-        "TGT_REQ_DCACHE",
-        "TGT_RSP_BROADCAST",
-        "TGT_RSP_ICACHE",
-        "TGT_RSP_DCACHE",
-    };	
+const char *cc_send_fsm_state_str[] = {
+        "CC_SEND_IDLE",
+        "CC_SEND_CLEANUP_1",
+        "CC_SEND_CLEANUP_2",
+        "CC_SEND_MULTI_ACK",
+    };
 }
 
 #define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcVCacheWrapper<vci_param, iss_t>
 
-using soclib::common::uint32_log2;
+using namespace soclib::common;
 
 /////////////////////////////////
 tmpl(/**/)::VciCcVCacheWrapper(
     sc_module_name 			name,
-    int 				proc_id,
-    const soclib::common::MappingTable 	&mtd,
-    const soclib::common::MappingTable 	&mtc,
-    const soclib::common::IntTab 	&initiator_index_d,
-    const soclib::common::IntTab 	&initiator_index_c,
-    const soclib::common::IntTab 	&target_index_c,
-    size_t 				itlb_ways,
-    size_t 				itlb_sets,
-    size_t 				dtlb_ways,
-    size_t 				dtlb_sets,
-    size_t 				icache_ways,
-    size_t 				icache_sets,
-    size_t 				icache_words,
-    size_t 				dcache_ways,
-    size_t 				dcache_sets,
-    size_t 				dcache_words,
-    size_t 				wbuf_nlines, 
-    size_t 				wbuf_nwords, 
-    size_t				x_width,
-    size_t				y_width,
-    uint32_t			memory_cache_local_id,
-    uint32_t			max_frozen_cycles,
-    uint32_t			debug_start_cycle,
-    bool				debug_ok)
+    const int 				proc_id,
+    const MappingTable 	    &mtd,
+    const IntTab 	        &srcid,
+    const size_t 	        cc_global_id,
+    const size_t 			itlb_ways,
+    const size_t 			itlb_sets,
+    const size_t 			dtlb_ways,
+    const size_t 			dtlb_sets,
+    const size_t 			icache_ways,
+    const size_t 			icache_sets,
+    const size_t 			icache_words,
+    const size_t 			dcache_ways,
+    const size_t 			dcache_sets,
+    const size_t 			dcache_words,
+    const size_t 			wbuf_nlines,
+    const size_t 			wbuf_nwords,
+    const size_t			x_width,
+    const size_t			y_width,
+    const uint32_t			max_frozen_cycles,
+    const uint32_t			debug_start_cycle,
+    const bool				debug_ok )
     : soclib::caba::BaseModule(name),
 
-      p_clk("clk"),
-      p_resetn("resetn"),
-      p_vci_ini_d("vci_ini_d"),
-      p_vci_ini_c("vci_ini_c"),
-      p_vci_tgt_c("vci_tgt_d"),
-
-      m_cacheability_table(mtd.getCacheabilityTable()),
-      m_segment(mtc.getSegment(target_index_c)),
-      m_srcid_d(mtd.indexForId(initiator_index_d)),
-      m_srcid_c(mtc.indexForId(initiator_index_c)),
-
-      m_itlb_ways(itlb_ways),
-      m_itlb_sets(itlb_sets),
-
-      m_dtlb_ways(dtlb_ways),
-      m_dtlb_sets(dtlb_sets),
-
-      m_icache_ways(icache_ways),
-      m_icache_sets(icache_sets),
-      m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
-      m_icache_words(icache_words),
-
-      m_dcache_ways(dcache_ways),
-      m_dcache_sets(dcache_sets),
-      m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
-      m_dcache_words(dcache_words),
-
-      m_x_width(x_width),
-      m_y_width(y_width),
-
-      m_memory_cache_local_id(memory_cache_local_id),      
-      m_proc_id(proc_id),
-      m_max_frozen_cycles(max_frozen_cycles),
-      m_paddr_nbits(vci_param::N),
-
-      m_debug_start_cycle(debug_start_cycle),
-      m_debug_ok(debug_ok),
+      p_clk("p_clk"),
+      p_resetn("p_resetn"),
+      p_vci("p_vci"),
+      p_dspin_in("p_dspin_in"),
+      p_dspin_out("p_dspin_out"),
+
+      m_cacheability_table( mtd.getCacheabilityTable() ),
+      m_srcid( mtd.indexForId(srcid) ),
+      m_cc_global_id( cc_global_id ),
+      m_nline_width( vci_param::N - (uint32_log2(dcache_words)) - 2 ),
+      m_itlb_ways( itlb_ways ),
+      m_itlb_sets( itlb_sets ),
+      m_dtlb_ways( dtlb_ways ),
+      m_dtlb_sets( dtlb_sets ),
+      m_icache_ways( icache_ways ),
+      m_icache_sets( icache_sets ),
+      m_icache_yzmask( (~0)<<(uint32_log2(icache_words) + 2) ),
+      m_icache_words( icache_words ),
+      m_dcache_ways( dcache_ways ),
+      m_dcache_sets( dcache_sets ),
+      m_dcache_yzmask( (~0)<<(uint32_log2(dcache_words) + 2) ),
+      m_dcache_words( dcache_words ),
+      m_x_width( x_width ),
+      m_y_width( y_width ),
+      m_proc_id( proc_id ),
+      m_max_frozen_cycles( max_frozen_cycles ),
+      m_paddr_nbits( vci_param::N ),
+      m_debug_start_cycle( debug_start_cycle ),
+      m_debug_ok( debug_ok ),
 
       r_mmu_ptpr("r_mmu_ptpr"),
@@ -254,4 +243,5 @@
       r_icache_cc_set("r_icache_cc_set"),
       r_icache_cc_word("r_icache_cc_word"),
+      r_icache_cc_need_write("r_icache_cc_need_write"),
 
       r_icache_flush_count("r_icache_flush_count"),
@@ -263,6 +253,9 @@
       r_icache_tlb_rsp_error("r_icache_tlb_rsp_error"),
 
-      r_icache_cleanup_req("r_icache_cleanup_req"),
-      r_icache_cleanup_line("r_icache_cleanup_line"),
+      r_icache_cc_send_req("r_icache_cc_send_req"),
+      r_icache_cc_send_type("r_icache_cc_send_type"),
+      r_icache_cc_send_nline("r_icache_cc_send_nline"),
+      r_icache_cc_send_way("r_icache_cc_send_way"),
+      r_icache_cc_send_updt_tab_idx("r_icache_cc_send_updt_tab_idx"),
 
       r_dcache_fsm("r_dcache_fsm"),
@@ -276,8 +269,8 @@
       r_dcache_save_be("r_dcache_save_be"),
       r_dcache_save_paddr("r_dcache_save_paddr"),
-      r_dcache_save_cacheable("r_dcache_save_cacheable"), 
-      r_dcache_save_cache_way("r_dcache_save_cache_way"), 
-      r_dcache_save_cache_set("r_dcache_save_cache_set"), 
-      r_dcache_save_cache_word("r_dcache_save_cache_word"), 
+      r_dcache_save_cacheable("r_dcache_save_cacheable"),
+      r_dcache_save_cache_way("r_dcache_save_cache_way"),
+      r_dcache_save_cache_set("r_dcache_save_cache_set"),
+      r_dcache_save_cache_word("r_dcache_save_cache_word"),
 
       r_dcache_dirty_paddr("r_dcache_dirty_paddr"),
@@ -310,4 +303,5 @@
       r_dcache_cc_set("r_dcache_cc_set"),
       r_dcache_cc_word("r_dcache_cc_word"),
+      r_dcache_cc_need_write("r_dcache_cc_need_write"),
 
       r_dcache_flush_count("r_dcache_flush_count"),
@@ -331,6 +325,9 @@
       r_dcache_xtn_opcode("r_dcache_xtn_opcode"),
 
-      r_dcache_cleanup_req("r_dcache_cleanup_req"),
-      r_dcache_cleanup_line("r_dcache_cleanup_line"),
+      r_dcache_cc_send_req("r_dcache_cc_send_req"),
+      r_dcache_cc_send_type("r_dcache_cc_send_type"),
+      r_dcache_cc_send_nline("r_dcache_cc_send_nline"),
+      r_dcache_cc_send_way("r_dcache_cc_send_way"),
+      r_dcache_cc_send_updt_tab_idx("r_dcache_cc_send_updt_tab_idx"),
 
       r_vci_cmd_fsm("r_vci_cmd_fsm"),
@@ -347,29 +344,27 @@
       r_vci_rsp_fifo_dcache("r_vci_rsp_fifo_dcache", 2),	// 2 words depth
 
-      r_cleanup_cmd_fsm("r_cleanup_cmd_fsm"),
-      r_cleanup_cmd_trdid("r_cleanup_cmd_trdid"),
-
-      r_cleanup_rsp_fsm("r_cleanup_rsp_fsm"),
-      r_cleanup_icache_req("r_cleanup_icache_req"),
-      r_cleanup_icache_way("r_cleanup_icache_way"),
-      r_cleanup_icache_set("r_cleanup_icache_set"),
-      r_cleanup_dcache_req("r_cleanup_dcache_req"),
-      r_cleanup_dcache_way("r_cleanup_dcache_way"),
-      r_cleanup_dcache_set("r_cleanup_dcache_set"),
-
-      r_tgt_fsm("r_tgt_fsm"),
-      r_tgt_paddr("r_tgt_paddr"),
-      r_tgt_word_count("r_tgt_word_count"),
-      r_tgt_word_min("r_tgt_word_min"),
-      r_tgt_word_max("r_tgt_word_max"),
-      r_tgt_cc_type("r_tgt_cc_type"),
-      r_tgt_srcid("r_tgt_srcid"),
-      r_tgt_pktid("r_tgt_pktid"),
-      r_tgt_trdid("r_tgt_trdid"),
-
-      r_tgt_icache_req("r_tgt_icache_req"),
-      r_tgt_dcache_req("r_tgt_dcache_req"),
-      r_icache_tgt_need_rsp("r_icache_tgt_need_rsp"),
-      r_dcache_tgt_need_rsp("r_dcache_tgt_need_rsp"),
+      r_cc_send_fsm("r_cc_send_fsm"),
+      r_cc_send_last_client("r_cc_send_last_client"),
+
+      r_cc_receive_fsm("r_cc_receive_fsm"),
+      r_cc_receive_data_ins("r_cc_receive_data_ins"),
+      r_cc_receive_word_idx("r_cc_receive_word_idx"),
+      r_cc_receive_updt_fifo_be("r_cc_receive_updt_fifo_be", 2),	// 2 words depth
+      r_cc_receive_updt_fifo_data("r_cc_receive_updt_fifo_data", 2),	// 2 words depth
+      r_cc_receive_updt_fifo_eop("r_cc_receive_updt_fifo_eop", 2),	// 2 words depth
+
+      r_cc_receive_icache_req("r_cc_receive_icache_req"),
+      r_cc_receive_icache_type("r_cc_receive_icache_type"),
+      r_cc_receive_icache_way("r_cc_receive_icache_way"),
+      r_cc_receive_icache_set("r_cc_receive_icache_set"),
+      r_cc_receive_icache_updt_tab_idx("r_cc_receive_icache_updt_tab_idx"),
+      r_cc_receive_icache_nline("r_cc_receive_icache_nline"),
+
+      r_cc_receive_dcache_req("r_cc_receive_dcache_req"),
+      r_cc_receive_dcache_type("r_cc_receive_dcache_type"),
+      r_cc_receive_dcache_way("r_cc_receive_dcache_way"),
+      r_cc_receive_dcache_set("r_cc_receive_dcache_set"),
+      r_cc_receive_dcache_updt_tab_idx("r_cc_receive_dcache_updt_tab_idx"),
+      r_cc_receive_dcache_nline("r_cc_receive_dcache_nline"),
 
       r_iss(this->name(), proc_id),
@@ -403,13 +398,11 @@
     r_mmu_release = (uint32_t)(1 << 16) | 0x1;
 
-    r_tgt_buf             = new uint32_t[dcache_words];
-    r_tgt_be              = new vci_be_t[dcache_words];
-    r_dcache_in_tlb       = new bool[dcache_ways*dcache_sets];          
-    r_dcache_contains_ptd = new bool[dcache_ways*dcache_sets];          
+    r_dcache_in_tlb       = new bool[dcache_ways*dcache_sets];
+    r_dcache_contains_ptd = new bool[dcache_ways*dcache_sets];
 
     SC_METHOD(transition);
     dont_initialize();
     sensitive << p_clk.pos();
-  
+
     SC_METHOD(genMoore);
     dont_initialize();
@@ -431,8 +424,6 @@
 /////////////////////////////////////
 {
-    delete [] r_tgt_be;
-    delete [] r_tgt_buf;
-    delete [] r_dcache_in_tlb;          
-    delete [] r_dcache_contains_ptd;     
+    delete [] r_dcache_in_tlb;
+    delete [] r_dcache_contains_ptd;
 }
 
@@ -441,5 +432,5 @@
 ////////////////////////
 {
-    std::cout << name() << " CPI = " 
+    std::cout << name() << " CPI = "
         << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
 }
@@ -467,6 +458,6 @@
               << " | " << cmd_fsm_state_str[r_vci_cmd_fsm.read()]
               << " | " << rsp_fsm_state_str[r_vci_rsp_fsm.read()]
-              << " | " << tgt_fsm_state_str[r_tgt_fsm.read()] 
-              << " | " << cleanup_fsm_state_str[r_cleanup_cmd_fsm.read()];
+              << " | " << cc_receive_fsm_state_str[r_cc_receive_fsm.read()]
+              << " | " << cc_send_fsm_state_str[r_cc_send_fsm.read()];
     if (r_dcache_updt_req.read() ) std::cout << " | P1_UPDT";
     if (r_dcache_wbuf_req.read() ) std::cout << " | P1_WBUF";
@@ -502,5 +493,5 @@
 tmpl(void)::cache_monitor( paddr_t addr )
 //////////////////////////////////////////
-{ 
+{
     size_t	cache_way;
     size_t	cache_set;
@@ -519,5 +510,5 @@
     if ( cache_hit != m_debug_previous_hit )
     {
-        std::cout << "PROC " << name() 
+        std::cout << "PROC " << name()
                   << " dcache change at cycle " << std::dec << m_cpt_total_cycles
                   << " for adresse " << std::hex << addr
@@ -527,5 +518,5 @@
     if ( icache_hit != m_idebug_previous_hit )
     {
-        std::cout << "PROC " << name() 
+        std::cout << "PROC " << name()
                   << " icache change at cycle " << std::dec << m_cpt_total_cycles
                   << " for adresse " << std::hex << addr
@@ -542,19 +533,19 @@
     float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
     std::cout << name() << std::endl
-        << "- CPI                    = " << (float)m_cpt_total_cycles/run_cycles << std::endl 
-        << "- READ RATE              = " << (float)m_cpt_read/run_cycles << std::endl 
+        << "- CPI                    = " << (float)m_cpt_total_cycles/run_cycles << std::endl
+        << "- READ RATE              = " << (float)m_cpt_read/run_cycles << std::endl
         << "- WRITE RATE             = " << (float)m_cpt_write/run_cycles << std::endl
         << "- IMISS_RATE             = " << (float)m_cpt_ins_miss/m_cpt_ins_read << std::endl
-        << "- DMISS RATE             = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl  
-        << "- INS MISS COST          = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl     
-        << "- DATA MISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl 
-        << "- WRITE COST             = " << (float)m_cost_write_frz/m_cpt_write << std::endl        
+        << "- DMISS RATE             = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl
+        << "- INS MISS COST          = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl
+        << "- DATA MISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl
+        << "- WRITE COST             = " << (float)m_cost_write_frz/m_cpt_write << std::endl
         << "- UNC COST               = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl
-        << "- UNCACHED READ RATE     = " << (float)m_cpt_unc_read/m_cpt_read << std::endl 
-        << "- CACHED WRITE RATE      = " << (float)m_cpt_write_cached/m_cpt_write << std::endl 
+        << "- UNCACHED READ RATE     = " << (float)m_cpt_unc_read/m_cpt_read << std::endl
+        << "- CACHED WRITE RATE      = " << (float)m_cpt_write_cached/m_cpt_write << std::endl
         << "- INS TLB MISS RATE      = " << (float)m_cpt_ins_tlb_miss/m_cpt_ins_tlb_read << std::endl
         << "- DATA TLB MISS RATE     = " << (float)m_cpt_data_tlb_miss/m_cpt_data_tlb_read << std::endl
         << "- ITLB MISS COST         = " << (float)m_cost_ins_tlb_miss_frz/m_cpt_ins_tlb_miss << std::endl
-        << "- DTLB MISS COST         = " << (float)m_cost_data_tlb_miss_frz/m_cpt_data_tlb_miss << std::endl   
+        << "- DTLB MISS COST         = " << (float)m_cost_data_tlb_miss_frz/m_cpt_data_tlb_miss << std::endl
         << "- ITLB UPDATE ACC COST   = " << (float)m_cost_ins_tlb_update_acc_frz/m_cpt_ins_tlb_update_acc << std::endl
         << "- DTLB UPDATE ACC COST   = " << (float)m_cost_data_tlb_update_acc_frz/m_cpt_data_tlb_update_acc << std::endl
@@ -595,9 +586,9 @@
     m_cpt_icache_dir_read   = 0;
     m_cpt_icache_dir_write  = 0;
-    
+
     m_cpt_frz_cycles        = 0;
     m_cpt_dcache_frz_cycles = 0;
     m_cpt_total_cycles      = 0;
-    
+
     m_cpt_read         = 0;
     m_cpt_write        = 0;
@@ -607,16 +598,16 @@
     m_cpt_write_cached = 0;
     m_cpt_ins_read     = 0;
-    
+
     m_cost_write_frz     = 0;
     m_cost_data_miss_frz = 0;
     m_cost_unc_read_frz  = 0;
     m_cost_ins_miss_frz  = 0;
-    
+
     m_cpt_imiss_transaction      = 0;
     m_cpt_dmiss_transaction      = 0;
     m_cpt_unc_transaction        = 0;
     m_cpt_write_transaction      = 0;
-    m_cpt_icache_unc_transaction = 0;	
-    
+    m_cpt_icache_unc_transaction = 0;
+
     m_cost_imiss_transaction      = 0;
     m_cost_dmiss_transaction      = 0;
@@ -625,20 +616,20 @@
     m_cost_icache_unc_transaction = 0;
     m_length_write_transaction    = 0;
-    
-    m_cpt_ins_tlb_read       = 0;             
-    m_cpt_ins_tlb_miss       = 0;             
-    m_cpt_ins_tlb_update_acc = 0;         
-    
-    m_cpt_data_tlb_read         = 0;           
-    m_cpt_data_tlb_miss         = 0;           
-    m_cpt_data_tlb_update_acc   = 0;       
-    m_cpt_data_tlb_update_dirty = 0;    
+
+    m_cpt_ins_tlb_read       = 0;
+    m_cpt_ins_tlb_miss       = 0;
+    m_cpt_ins_tlb_update_acc = 0;
+
+    m_cpt_data_tlb_read         = 0;
+    m_cpt_data_tlb_miss         = 0;
+    m_cpt_data_tlb_update_acc   = 0;
+    m_cpt_data_tlb_update_dirty = 0;
     m_cpt_ins_tlb_hit_dcache    = 0;
     m_cpt_data_tlb_hit_dcache   = 0;
     m_cpt_ins_tlb_occup_cache   = 0;
     m_cpt_data_tlb_occup_cache  = 0;
-    
-    m_cost_ins_tlb_miss_frz          = 0;      
-    m_cost_data_tlb_miss_frz         = 0;      
+
+    m_cost_ins_tlb_miss_frz          = 0;
+    m_cost_data_tlb_miss_frz         = 0;
     m_cost_ins_tlb_update_acc_frz    = 0;
     m_cost_data_tlb_update_acc_frz   = 0;
@@ -646,21 +637,21 @@
     m_cost_ins_tlb_occup_cache_frz   = 0;
     m_cost_data_tlb_occup_cache_frz  = 0;
-    
-    m_cpt_itlbmiss_transaction      = 0;    
-    m_cpt_itlb_ll_transaction       = 0;  
-    m_cpt_itlb_sc_transaction       = 0;  
-    m_cpt_dtlbmiss_transaction      = 0;  
-    m_cpt_dtlb_ll_transaction       = 0;  
-    m_cpt_dtlb_sc_transaction       = 0;  
-    m_cpt_dtlb_ll_dirty_transaction = 0;  
-    m_cpt_dtlb_sc_dirty_transaction = 0;  
-    
-    m_cost_itlbmiss_transaction      = 0;   
-    m_cost_itlb_ll_transaction       = 0;  
-    m_cost_itlb_sc_transaction       = 0;  
-    m_cost_dtlbmiss_transaction      = 0;   
-    m_cost_dtlb_ll_transaction       = 0;   
-    m_cost_dtlb_sc_transaction       = 0;   
-    m_cost_dtlb_ll_dirty_transaction = 0;   
+
+    m_cpt_itlbmiss_transaction      = 0;
+    m_cpt_itlb_ll_transaction       = 0;
+    m_cpt_itlb_sc_transaction       = 0;
+    m_cpt_dtlbmiss_transaction      = 0;
+    m_cpt_dtlb_ll_transaction       = 0;
+    m_cpt_dtlb_sc_transaction       = 0;
+    m_cpt_dtlb_ll_dirty_transaction = 0;
+    m_cpt_dtlb_sc_dirty_transaction = 0;
+
+    m_cost_itlbmiss_transaction      = 0;
+    m_cost_itlb_ll_transaction       = 0;
+    m_cost_itlb_sc_transaction       = 0;
+    m_cost_dtlbmiss_transaction      = 0;
+    m_cost_dtlb_ll_transaction       = 0;
+    m_cost_dtlb_sc_transaction       = 0;
+    m_cost_dtlb_ll_dirty_transaction = 0;
     m_cost_dtlb_sc_dirty_transaction = 0;
 
@@ -686,5 +677,5 @@
 {
     #define LLSCLocalTable GenericLLSCLocalTable<8000, 1, paddr_t, vci_trdid_t, vci_data_t>
-    if ( not p_resetn.read() ) 
+    if ( not p_resetn.read() )
     {
         r_iss.reset();
@@ -692,6 +683,6 @@
         r_icache.reset();
         r_dcache.reset();
-        r_itlb.reset();    
-        r_dtlb.reset();    
+        r_itlb.reset();
+        r_dtlb.reset();
 
         r_dcache_fsm      = DCACHE_IDLE;
@@ -699,7 +690,6 @@
         r_vci_cmd_fsm     = CMD_IDLE;
         r_vci_rsp_fsm     = RSP_IDLE;
-        r_tgt_fsm         = TGT_IDLE;
-        r_cleanup_cmd_fsm = CLEANUP_CMD_DATA_IDLE;
-        r_cleanup_rsp_fsm = CLEANUP_RSP_IDLE;
+        r_cc_receive_fsm  = CC_RECEIVE_IDLE;
+        r_cc_send_fsm     = CC_SEND_IDLE;
 
         // reset dcache directory extension
@@ -708,5 +698,5 @@
             r_dcache_in_tlb[i]       = false;
             r_dcache_contains_ptd[i] = false;
-        } 
+        }
 
         // Response FIFOs and cleanup buffer
@@ -722,9 +712,9 @@
 
         // No request from ICACHE_FSM to DCACHE FSM
-        r_icache_tlb_miss_req      = false;      
- 
-        // No request from ICACHE_FSM to CLEANUP_CMD FSM
-        r_icache_cleanup_req       = false;      
-        
+        r_icache_tlb_miss_req      = false;
+
+        // No request from ICACHE_FSM to CC_SEND FSM
+        r_icache_cc_send_req       = false;
+
         // No pending write in pipeline
         r_dcache_wbuf_req          = false;
@@ -744,14 +734,13 @@
         r_dcache_xtn_req           = false;
 
-        // No request from DCACHE FSM to CLEANUP_CMD FSM
-        r_dcache_cleanup_req      = false;
-
-        // No request from CLEANUP_RSP FSM to ICACHE/DCACHE FSMs
-        r_cleanup_icache_req      = false;
-        r_cleanup_dcache_req      = false;
-
-        // No request from TGT FSM to ICACHE/DCACHE FSMs
-        r_tgt_icache_req          = false;
-        r_tgt_dcache_req          = false;
+        // No request from DCACHE FSM to CC_SEND FSM
+        r_dcache_cc_send_req       = false;
+
+        // No request from CC_RECEIVE FSM to ICACHE/DCACHE FSMs
+        r_cc_receive_icache_req    = false;
+        r_cc_receive_dcache_req    = false;
+
+        // last cc_send client was dcache
+        r_cc_send_last_client      = false;
 
         // No pending cleanup after a replacement
@@ -760,17 +749,16 @@
 
         // No signalisation of a coherence request matching a pending miss
-        r_icache_miss_inval       = false;
-        r_dcache_miss_inval       = false;
+        r_icache_miss_inval        = false;
+        r_dcache_miss_inval        = false;
 
         // No signalisation  of errors
-        r_vci_rsp_ins_error       = false;
-        r_vci_rsp_data_error      = false;
+        r_vci_rsp_ins_error        = false;
+        r_vci_rsp_data_error       = false;
 
         // Debug variables
-        m_debug_previous_hit      = false;
-        m_idebug_previous_hit     = false;
-        m_debug_dcache_fsm	      = false;
-        m_debug_icache_fsm	      = false;
-        m_debug_cleanup_fsm  	  = false;
+        m_debug_previous_hit       = false;
+        m_idebug_previous_hit      = false;
+        m_debug_dcache_fsm	       = false;
+        m_debug_icache_fsm	       = false;
 
         // activity counters
@@ -803,5 +791,5 @@
         m_cpt_unc_transaction   = 0;
         m_cpt_write_transaction = 0;
-        m_cpt_icache_unc_transaction = 0;	
+        m_cpt_icache_unc_transaction = 0;
 
         m_cost_imiss_transaction      = 0;
@@ -812,12 +800,12 @@
         m_length_write_transaction    = 0;
 
-        m_cpt_ins_tlb_read       = 0;             
-        m_cpt_ins_tlb_miss       = 0;             
-        m_cpt_ins_tlb_update_acc = 0;         
-
-        m_cpt_data_tlb_read         = 0;           
-        m_cpt_data_tlb_miss         = 0;           
-        m_cpt_data_tlb_update_acc   = 0;       
-        m_cpt_data_tlb_update_dirty = 0;    
+        m_cpt_ins_tlb_read       = 0;
+        m_cpt_ins_tlb_miss       = 0;
+        m_cpt_ins_tlb_update_acc = 0;
+
+        m_cpt_data_tlb_read         = 0;
+        m_cpt_data_tlb_miss         = 0;
+        m_cpt_data_tlb_update_acc   = 0;
+        m_cpt_data_tlb_update_dirty = 0;
         m_cpt_ins_tlb_hit_dcache    = 0;
         m_cpt_data_tlb_hit_dcache   = 0;
@@ -825,6 +813,6 @@
         m_cpt_data_tlb_occup_cache  = 0;
 
-        m_cost_ins_tlb_miss_frz          = 0;      
-        m_cost_data_tlb_miss_frz         = 0;      
+        m_cost_ins_tlb_miss_frz          = 0;
+        m_cost_data_tlb_miss_frz         = 0;
         m_cost_ins_tlb_update_acc_frz    = 0;
         m_cost_data_tlb_update_acc_frz   = 0;
@@ -833,8 +821,8 @@
         m_cost_data_tlb_occup_cache_frz  = 0;
 
-    	m_cpt_ins_tlb_inval       = 0;           
-    	m_cpt_data_tlb_inval      = 0;          
-    	m_cost_ins_tlb_inval_frz  = 0;     
-    	m_cost_data_tlb_inval_frz = 0;         
+    	m_cpt_ins_tlb_inval       = 0;
+    	m_cpt_data_tlb_inval      = 0;
+    	m_cost_ins_tlb_inval_frz  = 0;
+    	m_cost_data_tlb_inval_frz = 0;
 
         m_cpt_cc_broadcast   = 0;
@@ -848,22 +836,22 @@
    	    m_cpt_cc_cleanup_ins  = 0;
 
-        m_cpt_itlbmiss_transaction      = 0;    
-        m_cpt_itlb_ll_transaction       = 0;  
-        m_cpt_itlb_sc_transaction       = 0;  
-        m_cpt_dtlbmiss_transaction      = 0;  
-        m_cpt_dtlb_ll_transaction       = 0;  
-        m_cpt_dtlb_sc_transaction       = 0;  
-        m_cpt_dtlb_ll_dirty_transaction = 0;  
-        m_cpt_dtlb_sc_dirty_transaction = 0;  
- 
-        m_cost_itlbmiss_transaction      = 0;   
-        m_cost_itlb_ll_transaction       = 0;  
-        m_cost_itlb_sc_transaction       = 0;  
-        m_cost_dtlbmiss_transaction      = 0;   
-        m_cost_dtlb_ll_transaction       = 0;   
-        m_cost_dtlb_sc_transaction       = 0;   
-        m_cost_dtlb_ll_dirty_transaction = 0;   
-        m_cost_dtlb_sc_dirty_transaction = 0;    
-/* 
+        m_cpt_itlbmiss_transaction      = 0;
+        m_cpt_itlb_ll_transaction       = 0;
+        m_cpt_itlb_sc_transaction       = 0;
+        m_cpt_dtlbmiss_transaction      = 0;
+        m_cpt_dtlb_ll_transaction       = 0;
+        m_cpt_dtlb_sc_transaction       = 0;
+        m_cpt_dtlb_ll_dirty_transaction = 0;
+        m_cpt_dtlb_sc_dirty_transaction = 0;
+
+        m_cost_itlbmiss_transaction      = 0;
+        m_cost_itlb_ll_transaction       = 0;
+        m_cost_itlb_sc_transaction       = 0;
+        m_cost_dtlbmiss_transaction      = 0;
+        m_cost_dtlb_ll_transaction       = 0;
+        m_cost_dtlb_sc_transaction       = 0;
+        m_cost_dtlb_ll_dirty_transaction = 0;
+        m_cost_dtlb_sc_dirty_transaction = 0;
+/*
         m_cpt_dcache_frz_cycles = 0;
         m_cpt_read              = 0;
@@ -878,7 +866,4 @@
         for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_cmd         [i]   = 0;
         for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_rsp         [i]   = 0;
-        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_tgt         [i]   = 0;
-        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_cmd_cleanup [i]   = 0;
-        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_rsp_cleanup [i]   = 0;
 
         // init the llsc reservation buffer
@@ -889,11 +874,18 @@
 
     // Response FIFOs default values
-    bool       vci_rsp_fifo_icache_get       = false;
-    bool       vci_rsp_fifo_icache_put       = false;
-    uint32_t   vci_rsp_fifo_icache_data      = 0;
-
-    bool       vci_rsp_fifo_dcache_get       = false;
-    bool       vci_rsp_fifo_dcache_put       = false;
-    uint32_t   vci_rsp_fifo_dcache_data      = 0;
+    bool       vci_rsp_fifo_icache_get   = false;
+    bool       vci_rsp_fifo_icache_put   = false;
+    uint32_t   vci_rsp_fifo_icache_data  = 0;
+
+    bool       vci_rsp_fifo_dcache_get   = false;
+    bool       vci_rsp_fifo_dcache_put   = false;
+    uint32_t   vci_rsp_fifo_dcache_data  = 0;
+
+    // updt fifo
+    bool       cc_receive_updt_fifo_get  = false;
+    bool       cc_receive_updt_fifo_put  = false;
+    uint32_t   cc_receive_updt_fifo_be   = 0;
+    uint32_t   cc_receive_updt_fifo_data = 0;
+    bool       cc_receive_updt_fifo_eop  = false;
 
 #ifdef INSTRUMENTATION
@@ -908,288 +900,6 @@
     m_cpt_total_cycles++;
 
-    m_debug_cleanup_fsm    = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;
     m_debug_icache_fsm     = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;
     m_debug_dcache_fsm     = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;
-
-    //////////////////////////////////////////////////////////////////////////////
-    //   TARGET TSM
-    // All VCI commands must be CMD_WRITE.
-    // - If the 2 LSB bits of the VCI address are 11, it is a broadcast request.
-    //   It is a multicast request otherwise.
-    // - For multicast requests, the ADDRESS[2] bit distinguishes DATA/INS
-    //   (0 for data / 1 for instruction), and the ADDRESS[3] bit distinguishes
-    //   INVAL/UPDATE (0 for invalidate / 1 for UPDATE).
-    //
-    // For all types of coherence request, the line index (i.e. the Z & Y fields) 
-    // is coded on 34 bits, and is contained in the WDATA and BE fields 
-    // of the first VCI flit.
-    // -  for a multicast invalidate or for a broadcast invalidate request
-    //    the VCI packet length is 1 word. 
-    // -  for an update request the VCI packet length is (n+2) words.
-    //    The WDATA field of the second VCI word contains the word index.
-    //    The WDATA field of the n following words contains the values.
-    // -  for all transaction types, the VCI response is one single word.
-    // In case of errors in the VCI command packet, the simulation
-    // is stopped with an error message.
-    //
-    // This FSM is NOT pipelined : It consumes a new coherence request 
-    // on the VCI port only when the previous request is completed.
-    //
-    // The VCI_TGT FSM stores the external request arguments in the
-    // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 
-    // and/or the r_tgt_dcache_req flip-flops to signal the coherence request 
-    // to the ICACHE & DCACHE FSMs in the REQ_ICACHE, REQ_DCACHE & REQ_BROADCAST
-    // states. It waits the completion of the coherence request  by polling the
-    // r_tgt_*cache_req flip-flops in the RSP_ICACHE, RSP_DCACHE & RSP_BROADCAST
-    // states. These flip-flops are reset by the ICACHE and DCACHE FSMs. 
-    // These two FSMs signal if a VCI answer must be send by setting
-    // the r_tgt_icache_rsp and/or the r_tgt_dcache_rsp flip_flops.
-    ///////////////////////////////////////////////////////////////////////////////
-    //   CC_RECEIVE  FSM (To Be Done)
-    // This FSM receive all coherence packets on a DSPIN40 port.
-    // There is 4 packet types:
-    // - CC_DATA_INVAL : DCACHE invalidate request
-    // - CC_DATA_UPDT  : DCACHE update request (multi-words)
-    // - CC_INST_INVAL : ICACHE invalidate request
-    // - CC_INST_UPDT  : ICACHE update request (multi-words)
-    // - CC_BROADCAST  : Broadcast invalidate request (both DCACHE & ICACHE)
-    // - CC_DATA_CLACK : DCACHE cleanup acknowledge
-    // - CC_INST_CLACK : ICACHE cleanup acknowledge
-    //////////////////////////////////////////////////////////////////////////////
-
-    switch( r_tgt_fsm.read() ) 
-    {
-    //////////////
-    case TGT_IDLE:
-    {
-        if ( p_vci_tgt_c.cmdval.read() ) 
-        {
-            paddr_t address = p_vci_tgt_c.address.read();
-
-            // command checking
-            if ( p_vci_tgt_c.cmd.read() != vci_param::CMD_WRITE) 
-            {
-                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
-                std::cout << "the received VCI coherence command is not a write" << std::endl;
-                exit(0);
-            }
-
-            // address checking
-            if ( ( (address & 0x3) != 0x3 ) && ( not m_segment.contains(address)) ) 
-            {
-                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
-                std::cout << "out of segment VCI coherence command received" << std::endl;
-                exit(0);
-            }
-
-            r_tgt_srcid = p_vci_tgt_c.srcid.read();
-            r_tgt_trdid = p_vci_tgt_c.trdid.read();
-            r_tgt_pktid = p_vci_tgt_c.pktid.read();
-
-	    if (sizeof(paddr_t) <= 32) 
-        {
-		     assert(p_vci_tgt_c.be.read() == 0 
-             && "byte enable should be 0 for 32bits paddr");
-             r_tgt_paddr  = (paddr_t)p_vci_tgt_c.wdata.read() * m_dcache_words * 4; 
-	    }
-        else 
-        {
-             r_tgt_paddr  = (paddr_t)(p_vci_tgt_c.be.read() & 0x3) << 32 |
-			                (paddr_t)p_vci_tgt_c.wdata.read() * m_dcache_words * 4; 
-	    }
-
-            if ( (address&0x3) == 0x3 ) // broadcast invalidate for data or instruction type
-            {
-                if ( not p_vci_tgt_c.eop.read() ) 
-                {
-                    std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
-                    std::cout << "the BROADCAST INVALIDATE command must be one flit" << std::endl;
-                    exit(0);
-                }
-                r_tgt_cc_type = CC_TYPE_BROADCAST;
-                r_tgt_fsm     = TGT_REQ_BROADCAST;
-
-#ifdef INSTRUMENTATION
-m_cpt_cc_broadcast++;
-#endif
-            }
-            else                // multi-update or multi-invalidate for data type
-            {
-                paddr_t cell = address - m_segment.baseAddress();   
-
-                if (cell == 0)                      // invalidate data
-                {                         
-                    if ( not p_vci_tgt_c.eop.read() ) 
-                    {
-                        std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
-                        std::cout << "the MULTI-INVALIDATE command must be one flit" << std::endl;
-                        exit(0);
-                    }
-                    r_tgt_cc_type = CC_TYPE_INVAL_DATA; 
-                    r_tgt_fsm     = TGT_REQ_DCACHE;
-
-#ifdef INSTRUMENTATION
-m_cpt_cc_inval_dcache++;
-#endif
-                }
-                else if (cell == 4)                // invalidate instruction
-                {                                
-                    if ( not p_vci_tgt_c.eop.read() ) 
-                    {
-                        std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
-                        std::cout << "the MULTI-INVALIDATE command must be one flit" << std::endl;
-                        exit(0);
-                    }
-                    r_tgt_cc_type = CC_TYPE_INVAL_INS;
-                    r_tgt_fsm     = TGT_REQ_ICACHE;
-
-#ifdef INSTRUMENTATION
-m_cpt_cc_inval_icache++;
-#endif
-                }     
-                else if (cell == 8)		                // update data
-                {
-                    if ( p_vci_tgt_c.eop.read() ) 
-                    {
-                        std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
-                        std::cout << "the MULTI-UPDATE command must be N+2 flits" << std::endl;
-                        exit(0);
-                    }
-                    r_tgt_cc_type     = CC_TYPE_UPDT_DATA; 
-                    r_tgt_fsm         = TGT_UPDT_WORD;
-
-#ifdef INSTRUMENTATION
-m_cpt_cc_update_dcache++;
-#endif
-		        }
-                else                                  // update instruction
-                {
-                    if ( p_vci_tgt_c.eop.read() ) 
-                    {
-                        std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
-                        std::cout << "the MULTI-UPDATE command must be N+2 flits" << std::endl;
-                        exit(0);
-                    }
-                    r_tgt_cc_type     = CC_TYPE_UPDT_INS; 
-                    r_tgt_fsm         = TGT_UPDT_WORD;
-
-#ifdef INSTRUMENTATION
-m_cpt_cc_update_icache++;
-#endif
-                }
-            } // end if multi      
-        } // end if cmdval
-        break;
-    }
-    ///////////////////
-    case TGT_UPDT_WORD:		// first word index acquisition
-    {
-        if (p_vci_tgt_c.cmdval.read()) 
-        {
-            if ( p_vci_tgt_c.eop.read() ) 
-            {
-                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
-                std::cout << "the MULTI-UPDATE command must be N+2 flits" << std::endl;
-                exit(0);
-            }
-            for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_be[i] = false;
-
-            r_tgt_word_min   = p_vci_tgt_c.wdata.read(); // first modifid word index
-            r_tgt_word_count = p_vci_tgt_c.wdata.read(); // initializing word index
-            r_tgt_fsm = TGT_UPDT_DATA;
-        }
-        break;
-    }
-    ///////////////////
-    case TGT_UPDT_DATA:
-    {
-        if (p_vci_tgt_c.cmdval.read()) 
-        {
-            size_t word = r_tgt_word_count.read();
-            if (word >= m_dcache_words) 
-            {
-                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
-                std::cout << "the reveived MULTI-UPDATE command is wrong" << std::endl;
-                exit(0);
-            }
-            r_tgt_buf[word]  = p_vci_tgt_c.wdata.read();
-            r_tgt_be[word]   = p_vci_tgt_c.be.read();
-            r_tgt_word_count = word + 1;	
-
-            if (p_vci_tgt_c.eop.read()) 	// last word
-            {
-                 r_tgt_word_max = word;
-                 if ( r_tgt_cc_type.read() == CC_TYPE_UPDT_DATA ) r_tgt_fsm = TGT_REQ_DCACHE;
-                 else					                          r_tgt_fsm = TGT_REQ_ICACHE;
-            }
-        }
-        break;
-    }
-    ///////////////////////
-    case TGT_REQ_BROADCAST:	// set requests to DCACHE & ICACHE FSMs 
-    {
-        if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() ) 
-        {
-            r_tgt_fsm = TGT_RSP_BROADCAST; 
-            r_tgt_icache_req = true;
-            r_tgt_dcache_req = true;
-        }
-        break;
-    }
-    /////////////////////
-    case TGT_REQ_ICACHE:	// set request to ICACHE FSM (if no previous request pending)
-    {
-        if ( not r_tgt_icache_req.read() ) 
-        {
-            r_tgt_fsm = TGT_RSP_ICACHE; 
-            r_tgt_icache_req = true;
-        }
-        break;
-    }
-    ////////////////////
-    case TGT_REQ_DCACHE:	// set request to DCACHE FSM (if no previous request pending)
-    {
-        if ( not r_tgt_dcache_req.read() ) 
-        {
-            r_tgt_fsm = TGT_RSP_DCACHE; 
-            r_tgt_dcache_req = true;
-        }
-        break;
-    }
-    ///////////////////////
-    case TGT_RSP_BROADCAST:	// waiting responses from both DCACHE & ICACHE FSMs
-                            // no VCI response por a broadcast
-    {
-        if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() ) 
-        {
-            r_tgt_fsm = TGT_IDLE;
-        }
-        break;
-    }
-    ////////////////////
-    case TGT_RSP_ICACHE:	// waiting response from ICACHE FSM
-                            // a VCI response is sent only
-                            // if r_icache_tgt_need_rsp is set
-    {
-        if ( not r_tgt_icache_req.read() ) 
-        {
-            if ( not r_icache_tgt_need_rsp.read() or
-                 p_vci_tgt_c.rspack.read() ) r_tgt_fsm = TGT_IDLE;
-        }
-        break;
-    }
-    ////////////////////
-    case TGT_RSP_DCACHE:    // waiting response from DCACHE FSM
-                            // a VCI response is sent only
-                            // if r_dcache_tgt_need_rsp is set
-    {
-        if ( not r_tgt_dcache_req.read() )
-        {
-            if ( not r_dcache_tgt_need_rsp.read() or
-                 p_vci_tgt_c.rspack.read() ) r_tgt_fsm = TGT_IDLE;
-        }
-        break;
-    }
-    } // end switch TGT_FSM
 
     /////////////////////////////////////////////////////////////////////
@@ -1202,14 +912,14 @@
     //      ICACHE_FSM
     //
-    // 1/ Coherence operations 
+    // 1/ Coherence operations
     //    They are handled as interrupts generated by the CC_RECEIVE FSM.
     //    - There is a coherence request when r_tgt_icache_req is set.
     //    They are taken in IDLE, MISS_WAIT, MISS_DIR_UPDT, UNC_WAIT, states.
-    //    - There is a cleanup ack request when r_cleanup_icache_req is set. 
+    //    - There is a cleanup ack request when r_cleanup_icache_req is set.
     //    They are taken in IDLE, MISS_SELECT, MISS_CLEAN, MISS_WAIT,
     //    MISS_DATA_UPDT, MISS_DIR_UPDT and UNC_WAIT states.
-    //    - For both types of requests, actions associated to the pre-empted state 
-    //    are not executed. The DCACHE FSM goes to the proper sub-FSM (CC_CHECK 
-    //    or CC_CLACK) to execute the requested coherence operation, and returns 
+    //    - For both types of requests, actions associated to the pre-empted state
+    //    are not executed. The DCACHE FSM goes to the proper sub-FSM (CC_CHECK
+    //    or CC_CLACK) to execute the requested coherence operation, and returns
     //    to the pre-empted state.
     //
@@ -1218,34 +928,34 @@
     //    instruction, the ICACHE FSM request a VCI transaction to CMD FSM,
     //    using the r_icache_miss_req or r_icache_unc_req flip-flops. These
-    //    flip-flops are reset when the transaction starts. 
-    //    - In case of miss the ICACHE FSM  goes to the ICACHE_MISS_SELECT state 
-    //    to select a slot and possibly request a cleanup transaction to the CC_SEND FSM. 
-    //    It goes next to the ICACHE_MISS_WAIT state waiting a response from RSP FSM, 
+    //    flip-flops are reset when the transaction starts.
+    //    - In case of miss the ICACHE FSM  goes to the ICACHE_MISS_SELECT state
+    //    to select a slot and possibly request a cleanup transaction to the CC_SEND FSM.
+    //    It goes next to the ICACHE_MISS_WAIT state waiting a response from RSP FSM,
     //    The availability of the missing cache line is signaled by the response fifo,
     //    and the cache update is done (one word per cycle) in the ICACHE_MISS_DATA_UPDT
-    //    and ICACHE_MISS_DIR_UPDT states. 
-    //    - In case of uncacheable instruction, the ICACHE FSM goes to ICACHE_UNC_WAIT 
-    //    to wait the response from the RSP FSM, through the response fifo. 
+    //    and ICACHE_MISS_DIR_UPDT states.
+    //    - In case of uncacheable instruction, the ICACHE FSM goes to ICACHE_UNC_WAIT
+    //    to wait the response from the RSP FSM, through the response fifo.
     //    The missing instruction is directly returned to processor in this state.
-    // 
+    //
     // 3/ TLB miss
-    //    In case of tlb miss, the ICACHE FSM request to the DCACHE FSM to update the 
-    //    ITLB using the r_icache_tlb_miss_req flip-flop and the r_icache_tlb_miss_vaddr 
+    //    In case of tlb miss, the ICACHE FSM request to the DCACHE FSM to update the
+    //    ITLB using the r_icache_tlb_miss_req flip-flop and the r_icache_tlb_miss_vaddr
     //    register, and goes to the ICACHE_TLB_WAIT state.
-    //    The tlb update is entirely done by the DCACHE FSM (who becomes the owner 
-    //    of ITLB until the update is completed, and reset r_icache_tlb_miss_req 
+    //    The tlb update is entirely done by the DCACHE FSM (who becomes the owner
+    //    of ITLB until the update is completed, and reset r_icache_tlb_miss_req
     //    to signal the completion.
     //
     // 4/ XTN requests
     //    The DCACHE FSM signals XTN processor requests to ICACHE_FSM
-    //    using the r_dcache_xtn_req flip-flop. 
+    //    using the r_dcache_xtn_req flip-flop.
     //    The request opcode and the address to be invalidated are transmitted
     //    in the r_dcache_xtn_opcode and r_dcache_save_wdata registers respectively.
-    //    The r_dcache_xtn_req flip-flop is reset by the ICACHE_FSM when the operation 
+    //    The r_dcache_xtn_req flip-flop is reset by the ICACHE_FSM when the operation
     //    is completed.
     //
     // 5/ Error Handling
     //    The r_vci_rsp_ins_error flip-flop is set by the RSP FSM in case of bus error
-    //    in a cache miss or uncacheable read VCI transaction. Nothing is written 
+    //    in a cache miss or uncacheable read VCI transaction. Nothing is written
     //    in the response fifo. This flip-flop is reset by the ICACHE-FSM.
     ////////////////////////////////////////////////////////////////////////////////////////
@@ -1256,18 +966,17 @@
     m_irsp.instruction = 0;
 
-    switch( r_icache_fsm.read() ) 
+    switch( r_icache_fsm.read() )
     {
     /////////////////
     case ICACHE_IDLE:	// In this state, we handle processor requests, XTN requests,
                         // and coherence requests with a fixed priority:
-                        // 1/ Coherence requests 				        => ICACHE_CC_CHECK
-                        // 2/ Cleanup ack requests 				        => ICACHE_CC_CLACK
-                        // 3/ XTN processor requests (from DCACHE FSM)  => ICACHE_XTN_*
-                        // 4/ tlb miss                                  => ICACHE_TLB_WAIT 
-                        // 5/ cacheable read miss 				        => ICACHE_MISS_SELECT
-                        // 6/ uncacheable read miss 				    => ICACHE_UNC_REQ 
+                        // 1/ Coherence requests                        => ICACHE_CC_CHECK
+                        // 2/ XTN processor requests (from DCACHE FSM)  => ICACHE_XTN_*
+                        // 3/ tlb miss                                  => ICACHE_TLB_WAIT
+                        // 4/ cacheable read miss                       => ICACHE_MISS_SELECT
+                        // 5/ uncacheable read miss                     => ICACHE_UNC_REQ
     {
         // coherence interrupt
-        if ( r_tgt_icache_req.read() )
+        if ( r_cc_receive_icache_req.read() )
         {
             r_icache_fsm = ICACHE_CC_CHECK;
@@ -1276,48 +985,40 @@
         }
 
-        // cleanup ack interrupt
-        if ( r_cleanup_icache_req.read() )
-        {
-            r_icache_fsm = ICACHE_CC_CLACK;
-            r_icache_fsm_save = r_icache_fsm.read();
-            break;
-        }
-
-        // XTN requests sent by DCACHE FSM  
+        // XTN requests sent by DCACHE FSM
         // These request are not executed in this IDLE state, because
         // they require access to icache or itlb, that are already accessed
         if ( r_dcache_xtn_req.read() )
         {
-            if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_PTPR ) 
-            {
-                r_icache_fsm         = ICACHE_XTN_TLB_FLUSH;   
+            if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_PTPR )
+            {
+                r_icache_fsm         = ICACHE_XTN_TLB_FLUSH;
             }
             else if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_ICACHE_FLUSH)
             {
                 r_icache_flush_count = 0;
-                r_icache_fsm         = ICACHE_XTN_CACHE_FLUSH;   
-            }
-            else if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_ITLB_INVAL) 
-            {
-                r_icache_fsm         = ICACHE_XTN_TLB_INVAL;   
-            }
-            else if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_ICACHE_INVAL) 
-            {
-                r_icache_fsm         = ICACHE_XTN_CACHE_INVAL_VA;   
-            }
-            else if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_MMU_ICACHE_PA_INV) 
-            {
-		        if (sizeof(paddr_t) <= 32) 
+                r_icache_fsm         = ICACHE_XTN_CACHE_FLUSH;
+            }
+            else if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_ITLB_INVAL)
+            {
+                r_icache_fsm         = ICACHE_XTN_TLB_INVAL;
+            }
+            else if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_ICACHE_INVAL)
+            {
+                r_icache_fsm         = ICACHE_XTN_CACHE_INVAL_VA;
+            }
+            else if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_MMU_ICACHE_PA_INV)
+            {
+		        if (sizeof(paddr_t) <= 32)
                 {
 			        assert(r_mmu_word_hi.read() == 0 &&
 			        "illegal XTN request in ICACHE: high bits should be 0 for 32bit paddr");
 			        r_icache_vci_paddr = (paddr_t)r_mmu_word_lo.read();
-                } 
-                else 
-                {
-			        r_icache_vci_paddr = (paddr_t)r_mmu_word_hi.read() << 32 | 
+                }
+                else
+                {
+			        r_icache_vci_paddr = (paddr_t)r_mmu_word_hi.read() << 32 |
 				                         (paddr_t)r_mmu_word_lo.read();
 		        }
-                r_icache_fsm         = ICACHE_XTN_CACHE_INVAL_PA;   
+                r_icache_fsm         = ICACHE_XTN_CACHE_INVAL_PA;
             }
             else
@@ -1334,7 +1035,7 @@
             bool	    cacheable;
             paddr_t	    paddr;
-            bool        tlb_hit = false;  
-            pte_info_t  tlb_flags; 
-            size_t      tlb_way;  
+            bool        tlb_hit = false;
+            pte_info_t  tlb_flags;
+            size_t      tlb_way;
             size_t      tlb_set;
             paddr_t     tlb_nline;
@@ -1371,5 +1072,5 @@
             {
 
-                
+
 #ifdef INSTRUMENTATION
 m_cpt_icache_data_read++;
@@ -1383,5 +1084,5 @@
                                &cache_state );
             }
-           
+
             // We compute cacheability and check access rights:
             // - If MMU activated : cacheability is defined by the C bit in the PTE,
@@ -1390,5 +1091,5 @@
             //   and there is no access rights checking
 
-            if ( not (r_mmu_mode.read() & INS_TLB_MASK) ) 	// tlb not activated: 
+            if ( not (r_mmu_mode.read() & INS_TLB_MASK) ) 	// tlb not activated:
             {
                 // cacheability
@@ -1399,10 +1100,10 @@
             {
                 if ( tlb_hit )	// ITLB hit
-                {  
+                {
                     // cacheability
                     if ( not (r_mmu_mode.read() & INS_CACHE_MASK) ) cacheable = false;
                     else  cacheable = tlb_flags.c;
 
-                    // access rights checking 
+                    // access rights checking
                     if ( not tlb_flags.u && (m_ireq.mode == iss_t::MODE_USER) )
                     {
@@ -1424,5 +1125,5 @@
                     }
                 }
-                else           // ITLB miss 
+                else           // ITLB miss
                 {
 
@@ -1433,12 +1134,12 @@
                     r_icache_tlb_miss_req = true;
                     break;
-                } 
+                }
             } // end if itlb activated
 
-            // physical address registration 
+            // physical address registration
             r_icache_vci_paddr   = paddr;
 
             // Finally, we send the response to processor, and compute next state
-            if ( cacheable )  
+            if ( cacheable )
             {
                 if (cache_state == CACHE_SLOT_STATE_EMPTY)	    // cache miss
@@ -1459,7 +1160,7 @@
                 else			                            // cache hit
                 {
-      
+
 #ifdef INSTRUMENTATION
-m_cpt_ins_read++; 
+m_cpt_ins_read++;
 #endif
                     // return instruction to processor
@@ -1479,5 +1180,5 @@
     /////////////////////
     case ICACHE_TLB_WAIT:	// Waiting the itlb update by the DCACHE FSM after a tlb miss
-                            // the itlb is udated by the DCACHE FSM, as well as the 
+                            // the itlb is udated by the DCACHE FSM, as well as the
                             // r_mmu_ietr and r_mmu_ibvar registers in case of error.
                             // the itlb is not accessed by ICACHE FSM until DCACHE FSM
@@ -1485,6 +1186,6 @@
                             // external coherence request are accepted in this state.
     {
-        // external coherence request
-        if ( r_tgt_icache_req.read() )
+        // coherence interrupt
+        if ( r_cc_receive_icache_req.read() )
         {
             r_icache_fsm = ICACHE_CC_CHECK;
@@ -1514,6 +1215,6 @@
     //////////////////////////
     case ICACHE_XTN_TLB_FLUSH:   	// invalidate in one cycle all non global TLB entries
-    {   
-        r_itlb.flush();   
+    {
+        r_itlb.flush();
         r_dcache_xtn_req     = false;
         r_icache_fsm         = ICACHE_IDLE;
@@ -1527,7 +1228,7 @@
                                     // We test here the slot state, and make the actual inval
                                     // (if line is valid) in ICACHE_XTN_CACHE_FLUSH_GO state.
-                       		        // A cleanup request is generated for each valid line 
-    {
-        if ( not r_icache_cleanup_req.read() ) // blocked until previous cleanup is sent
+                       		        // A cleanup request is generated for each valid line
+    {
+        if ( not r_icache_cc_send_req.read() ) // blocked until previous cc_send request is sent
         {
             int       state;
@@ -1539,6 +1240,6 @@
 m_cpt_icache_dir_read++;
 #endif
-            r_icache.read_dir( way, 
-                               set, 
+            r_icache.read_dir( way,
+                               set,
                                &tag,
                                &state );
@@ -1547,8 +1248,9 @@
             {
                 // request cleanup
-                r_icache_cleanup_req  = true;
-                r_icache_cleanup_line = tag * m_icache_sets;
-                r_icache_cleanup_way  = way;
-                
+                r_icache_cc_send_req   = true;
+                r_icache_cc_send_nline = tag * m_icache_sets;
+                r_icache_cc_send_way   = way;
+                r_icache_cc_send_type  = CC_TYPE_CLEANUP;
+
                 // goes to ICACHE_XTN_CACHE_FLUSH_GO to make inval
                 r_icache_miss_way     = way;
@@ -1572,5 +1274,5 @@
         }
         break;
-    }    
+    }
     ///////////////////////////////
     case ICACHE_XTN_CACHE_FLUSH_GO:	    // Switch slot state to ZOMBI for an XTN flush
@@ -1601,7 +1303,7 @@
         break;
     }
-                          
+
     //////////////////////////
-    case ICACHE_XTN_TLB_INVAL: 		// invalidate one TLB entry selected by the virtual address 
+    case ICACHE_XTN_TLB_INVAL: 		// invalidate one TLB entry selected by the virtual address
         				            // stored in the r_dcache_save_wdata register
     {
@@ -1614,8 +1316,8 @@
     case ICACHE_XTN_CACHE_INVAL_VA:	// Selective cache line invalidate with virtual address
                                     // requires 3 cycles (in case of hit on itlb and icache).
-					                // In this state, access TLB to translate virtual address 
+					                // In this state, access TLB to translate virtual address
         				            // stored in the r_dcache_save_wdata register.
     {
-        paddr_t 	paddr;                     
+        paddr_t 	paddr;
         bool    	hit;
 
@@ -1627,7 +1329,7 @@
 m_cpt_itlb_read++;
 #endif
-            hit = r_itlb.translate(r_dcache_save_wdata.read(), 
-                                   &paddr); 
-        } 
+            hit = r_itlb.translate(r_dcache_save_wdata.read(),
+                                   &paddr);
+        }
         else 						// itlb not activated
         {
@@ -1638,5 +1340,5 @@
         if ( hit )		// continue the selective inval process
         {
-            r_icache_vci_paddr    = paddr;                
+            r_icache_vci_paddr    = paddr;
             r_icache_fsm          = ICACHE_XTN_CACHE_INVAL_PA;
         }
@@ -1654,5 +1356,5 @@
     }
     ///////////////////////////////
-    case ICACHE_XTN_CACHE_INVAL_PA:	// selective invalidate cache line with physical address 
+    case ICACHE_XTN_CACHE_INVAL_PA:	// selective invalidate cache line with physical address
                                     // require 2 cycles. In this state, we read directory
                                     // with address stored in r_icache_vci_paddr register.
@@ -1680,5 +1382,5 @@
         else		// miss : acknowlege the XTN request and return
         {
-            r_dcache_xtn_req = false; 
+            r_dcache_xtn_req = false;
             r_icache_fsm     = ICACHE_IDLE;
         }
@@ -1688,5 +1390,5 @@
     case ICACHE_XTN_CACHE_INVAL_GO:  // Switch slot to ZOMBI state for an XTN inval
     {
-        if ( not r_icache_cleanup_req.read() )  // blocked if previous cleanup not sent
+        if ( not r_icache_cc_send_req.read() )  // blocked until previous cc_send request not sent
         {
 
@@ -1699,11 +1401,12 @@
                                 CACHE_SLOT_STATE_ZOMBI );
 
-            // request cleanup 
-            r_icache_cleanup_req  = true;
-            r_icache_cleanup_line = r_icache_vci_paddr.read() / (m_icache_words<<2);
-            r_icache_cleanup_way  = r_icache_miss_way.read();
+            // request cleanup
+            r_icache_cc_send_req   = true;
+            r_icache_cc_send_nline = r_icache_vci_paddr.read() / (m_icache_words<<2);
+            r_icache_cc_send_way   = r_icache_miss_way.read();
+            r_icache_cc_send_type  = CC_TYPE_CLEANUP;
 
             // acknowledge the XTN request and return
-            r_dcache_xtn_req      = false; 
+            r_dcache_xtn_req      = false;
             r_icache_fsm          = ICACHE_IDLE;
         }
@@ -1713,5 +1416,5 @@
     case ICACHE_MISS_SELECT:       // Try to select a slot in associative set,
                                    // if previous cleanup has been sent.
-                                   // Waiting in this state if no slot available. 
+                                   // Waiting in this state if no slot available.
                                    // Set the r_icache_cleanup_req flip-flop
                                    // and the r_icache_miss_clack flip-flop,
@@ -1720,13 +1423,13 @@
         if (m_ireq.valid) m_cost_ins_miss_frz++;
 
-        // cleanup ack interrupt
-        if ( r_cleanup_icache_req.read() )     
-        {
+        // coherence interrupt
+        if ( r_cc_receive_icache_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
             r_icache_fsm_save = r_icache_fsm.read();
-            r_icache_fsm = ICACHE_CC_CLACK;
             break;
         }
 
-        if ( not r_icache_cleanup_req.read() )
+        if ( not r_icache_cc_send_req.read() ) // wait for previous cc_send request to be sent
         {
             bool        found;
@@ -1740,6 +1443,6 @@
 #endif
             r_icache.read_select(r_icache_vci_paddr.read(),
-                                 &victim, 
-                                 &way, 
+                                 &victim,
+                                 &way,
                                  &set,
                                  &found,
@@ -1749,12 +1452,14 @@
                 r_icache_miss_way     = way;
                 r_icache_miss_set     = set;
-            
-                if ( cleanup ) 
-                {
-                    r_icache_fsm          = ICACHE_MISS_CLEAN;
-                    r_icache_cleanup_req  = true;
-                    r_icache_cleanup_line = victim;
-                    r_icache_cleanup_way  = way;
-                    r_icache_miss_clack   = true;
+
+                if ( cleanup )
+                {
+                    r_icache_fsm           = ICACHE_MISS_CLEAN;
+                    r_icache_miss_clack    = true;
+                    // request cleanup
+                    r_icache_cc_send_req   = true;
+                    r_icache_cc_send_nline = victim;
+                    r_icache_cc_send_way   = way;
+                    r_icache_cc_send_type  = CC_TYPE_CLEANUP;
                 }
                 else
@@ -1768,5 +1473,5 @@
     std::cout << "  <PROC " << name()
               << " ICACHE_MISS_SELECT> Select a slot:" << std::dec
-              << " / WAY = " << way 
+              << " / WAY = " << way
               << " / SET = " << set;
     if (cleanup) std::cout << " / VICTIM = " << std::hex << victim << std::endl;
@@ -1783,9 +1488,9 @@
         if (m_ireq.valid) m_cost_ins_miss_frz++;
 
-        // cleanup ack interrupt
-        if ( r_cleanup_icache_req.read() )     
-        {
+        // coherence interrupt
+        if ( r_cc_receive_icache_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
             r_icache_fsm_save = r_icache_fsm.read();
-            r_icache_fsm = ICACHE_CC_CLACK;
             break;
         }
@@ -1803,5 +1508,5 @@
     std::cout << "  <PROC " << name()
               << " ICACHE_MISS_CLEAN> Switch to ZOMBI state" << std::dec
-              << " / WAY = " << r_icache_miss_way.read() 
+              << " / WAY = " << r_icache_miss_way.read()
               << " / SET = " << r_icache_miss_set.read() << std::endl;
 }
@@ -1817,5 +1522,5 @@
 
         // coherence interrupt
-        if ( r_tgt_icache_req.read() )
+        if ( r_cc_receive_icache_req.read() )
         {
             r_icache_fsm = ICACHE_CC_CHECK;
@@ -1824,15 +1529,7 @@
         }
 
-        // cleanup ack interrupt
-        if ( r_cleanup_icache_req.read() )     
-        {
-            r_icache_fsm_save = r_icache_fsm.read();
-            r_icache_fsm = ICACHE_CC_CLACK;
-            break;
-        }
-
-        if ( r_vci_rsp_ins_error.read() ) // bus error 
-        {
-            r_mmu_ietr          = MMU_READ_DATA_ILLEGAL_ACCESS; 
+        if ( r_vci_rsp_ins_error.read() ) // bus error
+        {
+            r_mmu_ietr          = MMU_READ_DATA_ILLEGAL_ACCESS;
             r_mmu_ibvar         = r_icache_vaddr_save.read();
             m_irsp.valid        = true;
@@ -1844,20 +1541,12 @@
         {
             r_icache_miss_word = 0;
-            r_icache_fsm       = ICACHE_MISS_DATA_UPDT;  
-        }	
+            r_icache_fsm       = ICACHE_MISS_DATA_UPDT;
+        }
         break;
     }
     ///////////////////////////
-    case ICACHE_MISS_DATA_UPDT:	  // update the cache (one word per cycle) 
+    case ICACHE_MISS_DATA_UPDT:	  // update the cache (one word per cycle)
     {
         if ( m_ireq.valid ) m_cost_ins_miss_frz++;
-
-        // cleanup ack interrupt
-        if ( r_cleanup_icache_req.read() )     
-        {
-            r_icache_fsm_save = r_icache_fsm.read();
-            r_icache_fsm = ICACHE_CC_CLACK;
-            break;
-        }
 
         if ( r_vci_rsp_fifo_icache.rok() )	// response available
@@ -1896,5 +1585,5 @@
                                 // and the cleanup ack has not been received,
                                 // as indicated by r_icache_miss_clack.
-                                // - If no matching coherence request (r_icache_miss_inval) 
+                                // - If no matching coherence request (r_icache_miss_inval)
                                 //   switch directory slot to VALID state.
                                 // - If matching coherence request, switch directory slot
@@ -1904,5 +1593,5 @@
 
         // coherence interrupt
-        if ( r_tgt_icache_req.read() )
+        if ( r_cc_receive_icache_req.read() )
         {
             r_icache_fsm = ICACHE_CC_CHECK;
@@ -1911,22 +1600,16 @@
         }
 
-        // cleanup ack interrupt
-        if ( r_cleanup_icache_req.read() )     
-        {
-            r_icache_fsm_save = r_icache_fsm.read();
-            r_icache_fsm = ICACHE_CC_CLACK;
-            break;
-        }
-                    
         if ( not r_icache_miss_clack.read() ) // waiting cleanup acknowledge for victim line
         {
             if ( r_icache_miss_inval )    // Switch slot to ZOMBI state, and new cleanup
             {
-                if ( not r_icache_cleanup_req.read() )	
-                {
-                    r_icache_cleanup_req    = true;
-                    r_icache_cleanup_line   = r_icache_vci_paddr.read() / (m_icache_words<<2);
-                    r_icache_cleanup_way    = r_icache_miss_way.read();
-                    r_icache_miss_inval     = false;
+                if ( not r_icache_cc_send_req.read() )
+                {
+                    r_icache_miss_inval    = false;
+                    // request cleanup
+                    r_icache_cc_send_req   = true;
+                    r_icache_cc_send_nline = r_icache_vci_paddr.read() / (m_icache_words<<2);
+                    r_icache_cc_send_way   = r_icache_miss_way.read();
+                    r_icache_cc_send_type  = CC_TYPE_CLEANUP;
 
 #ifdef INSTRUMENTATION
@@ -1948,4 +1631,6 @@
 #endif
                 }
+                else
+                    break;
             }
             else                          // Switch slot to VALID state
@@ -1969,5 +1654,5 @@
 }
 #endif
-            }   
+            }
 
             r_icache_fsm = ICACHE_IDLE;
@@ -1979,22 +1664,14 @@
     {
         // coherence interrupt
-        if ( r_tgt_icache_req.read() ) 
-        {
-            r_icache_fsm      = ICACHE_CC_CHECK;
+        if ( r_cc_receive_icache_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
             r_icache_fsm_save = r_icache_fsm.read();
             break;
         }
 
-        // cleanup ack interrupt
-        if ( r_cleanup_icache_req.read() )     
-        {
-            r_icache_fsm_save = r_icache_fsm.read();
-            r_icache_fsm = ICACHE_CC_CLACK;
-            break;
-        }
-
         if ( r_vci_rsp_ins_error.read() ) // bus error
         {
-            r_mmu_ietr          = MMU_READ_DATA_ILLEGAL_ACCESS;    
+            r_mmu_ietr          = MMU_READ_DATA_ILLEGAL_ACCESS;
             r_mmu_ibvar         = m_ireq.addr;
             r_vci_rsp_ins_error = false;
@@ -2007,5 +1684,5 @@
             vci_rsp_fifo_icache_get = true;
             r_icache_fsm            = ICACHE_IDLE;
-            if ( m_ireq.valid and 
+            if ( m_ireq.valid and
                 (m_ireq.addr == r_icache_vaddr_save.read()) ) // request unmodified
             {
@@ -2013,41 +1690,5 @@
                 m_irsp.instruction = r_vci_rsp_fifo_icache.read();
             }
-        }	
-        break;
-    }
-    /////////////////////
-    case ICACHE_CC_CLACK:  	// This state is the entry point of the sub-fsm
-                            // handling the cleanup ack requests for ICACHE.
-                           	// We switch the directory slot to EMPTY state
-                            // and reset r_icache_miss_clack if the cleanup ack
-                            // is matching a pending miss
-    {
-        if ( m_ireq.valid ) m_cost_ins_miss_frz++;
-
-#ifdef INSTRUMENTATION
-m_cpt_icache_dir_write++;
-#endif
-        r_icache.write_dir( 0,
-                            r_cleanup_icache_way.read(),
-                            r_cleanup_icache_set.read(),
-                            CACHE_SLOT_STATE_EMPTY);
-
-        if ( (r_icache_miss_set.read() == r_cleanup_icache_set.read()) and
-             (r_icache_miss_way.read() == r_cleanup_icache_way.read()) )
-              r_icache_miss_clack = false;
- 
-        r_icache_fsm = r_icache_fsm_save.read() ;
-        r_cleanup_icache_req = false;
-
-#if DEBUG_ICACHE
-if ( m_debug_icache_fsm )
-{
-    std::cout << "  <PROC " << name() 
-              << " ICACHE_CC_CLACK> slot returns to empty state"
-              << " set = " << r_cleanup_icache_set.read()
-              << " / way = " << r_cleanup_icache_way.read() << std::endl;
-}
-#endif
-        
+        }
         break;
     }
@@ -2059,18 +1700,70 @@
                                 // The return state is defined in r_icache_fsm_save.
     {
-        paddr_t  paddr = r_tgt_paddr.read();
+        paddr_t  paddr = r_cc_receive_icache_nline.read() * m_icache_words * 4;
         paddr_t  mask  = ~((m_icache_words<<2)-1);
 
-        if( ((r_icache_fsm_save.read() == ICACHE_MISS_WAIT) or
-             (r_icache_fsm_save.read() == ICACHE_MISS_DIR_UPDT)) and
-            ((r_icache_vci_paddr.read() & mask) == (paddr & mask))) // matching 
+        if (r_cc_receive_icache_type.read() == CC_TYPE_CLACK)
+                           	// We switch the directory slot to EMPTY state
+                            // and reset r_icache_miss_clack if the cleanup ack
+                            // is matching a pending miss
+        {
+
+            if ( m_ireq.valid ) m_cost_ins_miss_frz++;
+
+#ifdef INSTRUMENTATION
+m_cpt_icache_dir_write++;
+#endif
+            r_icache.write_dir( 0,
+                                r_cc_receive_icache_way.read(),
+                                r_cc_receive_icache_set.read(),
+                                CACHE_SLOT_STATE_EMPTY);
+
+            if ( (r_icache_miss_set.read() == r_cc_receive_icache_set.read()) and
+                 (r_icache_miss_way.read() == r_cc_receive_icache_way.read()) )
+                    r_icache_miss_clack = false;
+
+            r_icache_fsm = r_icache_fsm_save.read() ;
+            r_cc_receive_icache_req = false;
+
+#if DEBUG_ICACHE
+if ( m_debug_icache_fsm )
+{
+    std::cout << "  <PROC " << name()
+    << " ICACHE_CC_CHECK>  CC_TYPE_CLACK slot returns to empty state"
+    << " set = " << r_cc_receive_icache_set.read()
+    << " / way = " << r_cc_receive_icache_way.read() << std::endl;
+}
+#endif
+        }
+        else if( ((r_icache_fsm_save.read() == ICACHE_MISS_WAIT) or
+                 (r_icache_fsm_save.read() == ICACHE_MISS_DIR_UPDT)) and
+                 ((r_icache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching
         {
             // signaling the matching
-            r_icache_miss_inval   = true;
-
-            // coherence request completed, CC_ACK required if update  
-            r_tgt_icache_req      = false;
-            r_icache_tgt_need_rsp = (r_tgt_cc_type.read() == CC_TYPE_UPDT_INS);
-            r_icache_fsm          = r_icache_fsm_save.read();
+            r_icache_miss_inval     = true;
+
+            // in case of update, go to CC_UPDT
+            // JUST TO POP THE FIFO
+            if (r_cc_receive_icache_type.read() == CC_TYPE_UPDT)
+            {
+                r_icache_fsm        = ICACHE_CC_UPDT;
+                r_icache_cc_word    = r_cc_receive_word_idx.read();
+                // just pop the fifo , don't write in icache
+                r_icache_cc_need_write = false;
+            }
+            // the request is dealt with
+            else
+            {
+                r_cc_receive_icache_req = false;
+                r_icache_fsm          = r_icache_fsm_save.read();
+            }
+#if DEBUG_ICACHE
+if ( m_debug_icache_fsm )
+{
+    std::cout << "  <PROC " << name()
+              << " ICACHE_CC_CHECK> Coherence request matching a pending miss:"
+              << " PADDR = " << std::hex << paddr << std::endl;
+}
+#endif
         }
         else  								                            // no match
@@ -2084,8 +1777,8 @@
 m_cpt_icache_dir_read++;
 #endif
-            r_icache.read_dir(paddr, 
+            r_icache.read_dir(paddr,
                               &state,
-                              &way, 
-                              &set, 
+                              &way,
+                              &set,
                               &word);
 
@@ -2093,26 +1786,37 @@
             r_icache_cc_set = set;
 
-            if ( state == CACHE_SLOT_STATE_VALID)            // hit  
-            {
-                if (r_tgt_cc_type.read() == CC_TYPE_UPDT_INS)  // hit update
+            if ( state == CACHE_SLOT_STATE_VALID)            // hit
+            {
+                // need to update the cache state
+                r_icache_cc_need_write = true;
+                if (r_cc_receive_icache_type.read() == CC_TYPE_UPDT)  // hit update
                 {
                     r_icache_fsm          = ICACHE_CC_UPDT;
-                    r_icache_cc_word      = r_tgt_word_min.read();
+                    r_icache_cc_word      = r_cc_receive_word_idx.read();
                 }
-                else if (r_tgt_cc_type == CC_TYPE_INVAL_INS)   // hit inval
+                else if (r_cc_receive_icache_type.read() == CC_TYPE_INVAL)   // hit inval
                 {
                     r_icache_fsm          = ICACHE_CC_INVAL;
                 }
-                else if ( r_tgt_cc_type == CC_TYPE_BROADCAST)  // hit broadcast
-                {
-                    r_icache_fsm          = ICACHE_CC_BROADCAST;                
+                else if (r_cc_receive_icache_type.read() == CC_TYPE_BRDCAST)  // hit broadcast
+                {
+                    r_icache_fsm          = ICACHE_CC_BROADCAST;
                 }
             }
             else                                      // miss
             {
-                // coherence request completed, CC_ACK required if update only 
-                r_tgt_icache_req      = false;
-                r_icache_tgt_need_rsp = (r_tgt_cc_type.read() == CC_TYPE_UPDT_INS);
-                r_icache_fsm          = r_icache_fsm_save.read();
+                // multicast acknowledgement required in case of update
+                if(r_cc_receive_icache_type.read() == CC_TYPE_UPDT)
+                {
+                    r_icache_fsm          = ICACHE_CC_UPDT;
+                    r_icache_cc_word      = r_cc_receive_word_idx.read();
+                    // just pop the fifo , don't write in icache
+                    r_icache_cc_need_write = false;
+                }
+                else // No response needed
+                {
+                    r_cc_receive_icache_req = false;
+                    r_icache_fsm          = r_icache_fsm_save.read();
+                }
             }
         }
@@ -2121,10 +1825,10 @@
     /////////////////////
     case ICACHE_CC_INVAL:  	// hit inval : switch slot to EMPTY state
-    {                       
+    {
 
 #if DEBUG_ICACHE
 if ( m_debug_icache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " ICACHE_CC_INVAL> slot returns to empty state"
               << " set = " << r_icache_cc_set.read()
@@ -2136,17 +1840,32 @@
 m_cpt_icache_dir_read++;
 #endif
-        r_icache.write_dir( 0,
-	                        r_icache_cc_way.read(),
-	                        r_icache_cc_set.read(),
-                            CACHE_SLOT_STATE_EMPTY );
-
-        // coherence request completed, CC_ACK required if hit inval
-        r_tgt_icache_req      = false;
-        r_icache_tgt_need_rsp = true;
-        r_icache_fsm          = r_icache_fsm_save.read();
+        if (r_icache_cc_need_write.read())
+        {
+            r_icache.write_dir( 0,
+	                            r_icache_cc_way.read(),
+	                            r_icache_cc_set.read(),
+                                CACHE_SLOT_STATE_EMPTY );
+            // no need to write in the cache anymore
+            r_icache_cc_need_write = false;
+        }
+
+        // multicast acknowledgement
+        // send a request to cc_send_fsm
+        if(not r_icache_cc_send_req.read()) // cc_send is available
+        {
+            // coherence request completed
+            r_cc_receive_icache_req = false;
+            // request multicast acknowledgement
+            r_icache_cc_send_req = true;
+            r_icache_cc_send_updt_tab_idx = r_cc_receive_icache_updt_tab_idx.read();
+            r_icache_cc_send_type = CC_TYPE_MULTI_ACK;
+
+            r_icache_fsm          = r_icache_fsm_save.read();
+        }
+        //else wait for previous cc_send request to be sent
         break;
     }
     ////////////////////
-    case ICACHE_CC_UPDT:	// hit update : write one word per cycle 
+    case ICACHE_CC_UPDT:	// hit update : write one word per cycle
     {
 
@@ -2154,8 +1873,8 @@
 if ( m_debug_icache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " ICACHE_CC_UPDT> Write one word "
               << " set = " << r_icache_cc_set.read()
-              << " / way = " << r_icache_cc_way.read() 
+              << " / way = " << r_icache_cc_way.read()
               << " / word = " << r_icache_cc_word.read() << std::endl;
 }
@@ -2169,18 +1888,40 @@
         size_t  set   = r_icache_cc_set.read();
 
-        r_icache.write( way,
-                        set,
-                        word,
-                        r_tgt_buf[word],
-                        r_tgt_be[word] );
-
-        r_icache_cc_word = word+1;
-
-        if ( word == r_tgt_word_max.read() )	// last word
-        {
-            // coherence operation request, CC_ACK required if hit update  
-            r_tgt_icache_req      = false;
-            r_icache_tgt_need_rsp = true;
-            r_icache_fsm          = r_icache_fsm_save.read();
+        if (r_cc_receive_updt_fifo_be.rok())
+        {
+            if (r_icache_cc_need_write.read())
+            {
+                r_icache.write( way,
+                                set,
+                                word,
+                                r_cc_receive_updt_fifo_data.read(),
+                                r_cc_receive_updt_fifo_be.read() );
+
+                r_icache_cc_word = word+1;
+            }
+            if ( r_cc_receive_updt_fifo_eop.read() )	// last word
+            {
+                // no need to write in the cache anymore
+                r_icache_cc_need_write = false;
+                // wait to send a request to cc_send_fsm
+                if(not r_icache_cc_send_req.read()) // cc_send is available
+                {
+                    //consume last flit
+                    cc_receive_updt_fifo_get  = true;
+                    // coherence request completed
+                    r_cc_receive_icache_req = false;
+                    // request multicast acknowledgement
+                    r_icache_cc_send_req = true;
+                    r_icache_cc_send_updt_tab_idx = r_cc_receive_icache_updt_tab_idx.read();
+                    r_icache_cc_send_type = CC_TYPE_MULTI_ACK;
+
+                    r_icache_fsm          = r_icache_fsm_save.read();
+                }
+            }
+            else
+            {
+                //consume fifo if not eop
+                cc_receive_updt_fifo_get  = true;
+            }
         }
         break;
@@ -2194,5 +1935,5 @@
 if ( m_debug_icache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " ICACHE_CC_BROADCAST > Slot goes to zombi state "
               << " set = " << r_icache_cc_set.read()
@@ -2204,16 +1945,29 @@
 m_cpt_icache_dir_write++;
 #endif
-        r_icache.write_dir( 0,
-	                        r_icache_cc_way.read(),
-	                        r_icache_cc_set.read(),
-                            CACHE_SLOT_STATE_ZOMBI );
-	    
-        // coherence operation completed, no CC_ACK for hit broadcast
-        r_icache_tgt_need_rsp = false;
-        r_tgt_icache_req      = false;
-        r_icache_cleanup_req  = true;
-        r_icache_cleanup_line = r_tgt_paddr.read() / (m_icache_words<<2);
-        r_icache_cleanup_way  = r_icache_cc_way.read();
-        r_icache_fsm          = r_icache_fsm_save.read();
+        if (r_icache_cc_need_write.read())
+        {
+            r_icache.write_dir( 0,
+	                            r_icache_cc_way.read(),
+	                            r_icache_cc_set.read(),
+                                CACHE_SLOT_STATE_ZOMBI );
+            // no need to write in the cache anymore
+            r_icache_cc_need_write = false;
+        }
+
+        // cleanup
+        // send a request to cc_send_fsm
+        if(not r_icache_cc_send_req.read()) // cc_send is available
+        {
+            // coherence request completed
+            r_cc_receive_icache_req = false;
+            // request cleanup
+            r_icache_cc_send_req = true;
+            r_icache_cc_send_nline = r_cc_receive_icache_nline.read();
+            r_icache_cc_send_way   = r_icache_cc_way.read();
+            r_icache_cc_send_type  = CC_TYPE_CLEANUP;
+
+            r_icache_fsm          = r_icache_fsm_save.read();
+        }
+        //else wait for previous cc_send request to be sent
         break;
     }
@@ -2221,17 +1975,17 @@
 
     ////////////////////////////////////////////////////////////////////////////////////
-    //      DCACHE FSM 
+    //      DCACHE FSM
     //
-    // 1/ Coherence operations 
+    // 1/ Coherence operations
     //    They are handled as interrupts generated by the CC_RECEIVE FSM.
     //    - There is a coherence request when r_tgt_dcache_req is set.
-    //    They are taken in IDLE, MISS_WAIT, MISS_DIR_UPDT, UNC_WAIT, LL_WAIT 
+    //    They are taken in IDLE, MISS_WAIT, MISS_DIR_UPDT, UNC_WAIT, LL_WAIT
     //    and SC_WAIT states.
-    //    - There is a cleanup acknowledge request when r_cleanup_dcache_req is set. 
-    //    They are taken in IDLE, MISS_SELECT, MISS_CLEAN, MISS_WAIT, MISS_DATA_UPDT, 
+    //    - There is a cleanup acknowledge request when r_cleanup_dcache_req is set.
+    //    They are taken in IDLE, MISS_SELECT, MISS_CLEAN, MISS_WAIT, MISS_DATA_UPDT,
     //    MISS_DIR_UPDT, UNC_WAIT, LL_WAIT, SC_WAIT states.
-    //    - For both types of requests, actions associated to the pre-empted state 
-    //    are not executed. The DCACHE FSM goes to the proper sub-FSM (CC_CHECK 
-    //    or CC_CLACK) to execute the requested coherence operation, and returns 
+    //    - For both types of requests, actions associated to the pre-empted state
+    //    are not executed. The DCACHE FSM goes to the proper sub-FSM (CC_CHECK
+    //    or CC_CLACK) to execute the requested coherence operation, and returns
     //    to the pre-empted state.
     //
@@ -2242,15 +1996,15 @@
     //    this sub-fsm implement the table-walk...
     //
-    // 3/ processor requests 
+    // 3/ processor requests
     //    Processor requests are taken in IDLE state only.
     //    The IDLE state implements a two stages pipe-line to handle write bursts:
     //    - Both DTLB and DCACHE are accessed in stage P0 (if processor request valid).
     //    - The registration in wbuf and the dcache update is done in stage P1
-    //      (if the processor request is a write).  
+    //      (if the processor request is a write).
     //    The two r_dcache_wbuf_req and r_dcache_updt_req flip-flops define
     //    the operations that must be done in P1 stage, and the access type
     //    (read or write) to the DATA part of DCACHE depends on r_dcache_updt_req.
     //    READ requests are delayed if a cache update is requested.
-    //    WRITE or SC requests can require a PTE Dirty bit update (in memory), 
+    //    WRITE or SC requests can require a PTE Dirty bit update (in memory),
     //    that is done (before handling the processor request) by a dedicated sub-fsm.
     //    If a PTE is modified, both the itlb and dtlb are selectively, but sequencially
@@ -2259,12 +2013,12 @@
     // 4/ Atomic instructions LL/SC
     //    The LL/SC address are non cacheable (systematic access to memory).
-    //    The llsc buffer contains a registration for an active LL/SC operation 
+    //    The llsc buffer contains a registration for an active LL/SC operation
     //    (with an address, a registration key, an aging counter and a valid bit).
     //    - LL requests from the processor are transmitted as a one flit VCI command
     //      (CMD_LOCKED_READ as CMD, and TYPE_LL as PKTID value). PLEN must
-    //      be 8 as the response is 2 flits long (data and registration key) 
-    //    - SC requests from the processor are systematically transmitted to the 
-    //      memory cache as 2 flits VCI command (CMD_STORE_COND as CMD, and TYPE_SC 
-    //      as PKTID value).  The first flit contains the registration key, the second 
+    //      be 8 as the response is 2 flits long (data and registration key)
+    //    - SC requests from the processor are systematically transmitted to the
+    //      memory cache as 2 flits VCI command (CMD_STORE_COND as CMD, and TYPE_SC
+    //      as PKTID value).  The first flit contains the registration key, the second
     //      flit contains the data to write in case of success.
     //      The cache is not updated, as this is done in case of success by the
@@ -2278,9 +2032,9 @@
     //    a non cacheable write transaction posted in the write buffer by setting the
     //    r_dcache_pending_unc_write flip_flop. All other non cacheable requests
-    //    are stalled until this flip-flop is reset by the VCI_RSP_FSM (when the 
+    //    are stalled until this flip-flop is reset by the VCI_RSP_FSM (when the
     //    pending non cacheable write transaction completes).
     //
-    // 6/ Error handling:  
-    //    When the MMU is not activated, Read Bus Errors are synchronous events, 
+    // 6/ Error handling:
+    //    When the MMU is not activated, Read Bus Errors are synchronous events,
     //    but Write Bus Errors are asynchronous events (processor is not frozen).
     //    - If a Read Bus Error is detected, the VCI_RSP FSM sets the
@@ -2299,9 +2053,9 @@
     m_drsp.rdata = 0;
 
-    switch ( r_dcache_fsm.read() ) 
+    switch ( r_dcache_fsm.read() )
     {
     case DCACHE_IDLE: // There are 10 conditions to exit the IDLE state :
                       // 1) ITLB/DTLB inval request (update)  => DCACHE_INVAL_TLB_SCAN
-                      // 2) Coherence request (TGT FSM)       => DCACHE_CC_CHECK 
+                      // 2) Coherence request (TGT FSM)       => DCACHE_CC_CHECK
                       // 3) ITLB miss request (ICACHE FSM)    => DCACHE_TLB_MISS
                       // 4) XTN request (processor)           => DCACHE_XTN_*
@@ -2309,12 +2063,12 @@
                       // 6) Dirty bit update (processor)      => DCACHE_DIRTY_GET_PTE
                       // 7) Cacheable read miss (processor)   => DCACHE_MISS_SELECT
-                      // 8) Uncacheable read (processor)      => DCACHE_UNC_WAIT 
+                      // 8) Uncacheable read (processor)      => DCACHE_UNC_WAIT
                       // 9) LL access (processor)             => DCACHE_LL_WAIT
                       // 10) SC access (processor)            => DCACHE_SC_WAIT
                       //
-                      // There is a fixed priority to handle requests to DCACHE: 
+                      // There is a fixed priority to handle requests to DCACHE:
                       //    1/ the ITLB/DTLB invalidate requests
                       //    2/ the coherence requests,
-                      //    3/ the processor requests (including DTLB miss), 
+                      //    3/ the processor requests (including DTLB miss),
                       //    4/ the ITLB miss requests,
                       // The address space processor request are handled as follows:
@@ -2322,5 +2076,5 @@
                       // If DTLB hit, the P1 stage is activated (writes WBUF, and
                       // updates DCACHE if DCACHE hit) & processor request acknowledged.
-                      // - READ request generate a simultaneouss access to  DCACHE.DATA 
+                      // - READ request generate a simultaneouss access to  DCACHE.DATA
                       // and DCACHE.DIR, but is delayed if DCACHE update required.
                       //
@@ -2328,5 +2082,5 @@
                       // DTLB, DCACHE.DATA, and DCACHE.DIR, depending on the
                       // dreq.valid (dreq) and r_dcache_updt_req (updt) signals:
-                      //    dreq / updt / DTLB  / DCACHE.DIR / DCACHE.DATA /                   
+                      //    dreq / updt / DTLB  / DCACHE.DIR / DCACHE.DATA /
                       //     0   /  0   / NOP   / NOP        / NOP         /
                       //     0   /  1   / NOP   / NOP        / WRITE       /
@@ -2335,16 +2089,16 @@
                       // Those two registers are set at each cycle from the 3 signals
                       // updt_request, wbuf_request, wbuf_write_miss.
-    { 
+    {
         paddr_t     paddr;                          // physical address
-        pte_info_t 	tlb_flags; 
-        size_t     	tlb_way; 
-        size_t     	tlb_set; 
-        paddr_t    	tlb_nline; 
+        pte_info_t 	tlb_flags;
+        size_t     	tlb_way;
+        size_t     	tlb_set;
+        paddr_t    	tlb_nline;
         size_t		cache_way;
         size_t		cache_set;
         size_t		cache_word;
         uint32_t	cache_rdata = 0;
-        bool	    tlb_hit = false;                     
-        int	        cache_state = CACHE_SLOT_STATE_EMPTY; 
+        bool	    tlb_hit = false;
+        int	        cache_state = CACHE_SLOT_STATE_EMPTY;
 
         bool        tlb_inval_required = false;     // request TLB inval after cache update
@@ -2362,6 +2116,6 @@
                                             &tlb_flags,
                                             &tlb_nline,
-                                            &tlb_way,	
-                                            &tlb_set );	
+                                            &tlb_way,
+                                            &tlb_set );
 #ifdef INSTRUMENTATION
 m_cpt_dtlb_read++;
@@ -2375,5 +2129,5 @@
 
         // systematic DCACHE access depending on r_dcache_updt_req (if activated)
-        if ( r_mmu_mode.read() & DATA_CACHE_MASK)  	
+        if ( r_mmu_mode.read() & DATA_CACHE_MASK)
         {
             if ( m_dreq.valid and r_dcache_updt_req.read() ) // read DIR and write DATA
@@ -2413,5 +2167,5 @@
                                 r_dcache_save_cache_set.read(),
                                 r_dcache_save_cache_word.read(),
-                                r_dcache_save_wdata.read(), 
+                                r_dcache_save_wdata.read(),
                                 r_dcache_save_be.read() );
 #ifdef INSTRUMENTATION
@@ -2419,5 +2173,5 @@
 #endif
             }
-        } // end dcache access    
+        } // end dcache access
 
         // DCACHE update in P1 stage can require ITLB / DTLB inval or flush
@@ -2432,5 +2186,5 @@
 	            r_dcache_tlb_inval_set   = 0;
 	            r_dcache_tlb_inval_line  = r_dcache_save_paddr.read()>>
-                                           (uint32_log2(m_dcache_words<<2)); 
+                                           (uint32_log2(m_dcache_words<<2));
 	            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
             }
@@ -2445,8 +2199,8 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_IDLE> Cache update in P1 stage" << std::dec
-              << " / WAY = " << r_dcache_save_cache_way.read() 
-              << " / SET = " << r_dcache_save_cache_set.read() 
+              << " / WAY = " << r_dcache_save_cache_way.read()
+              << " / SET = " << r_dcache_save_cache_set.read()
               << " / WORD = " << r_dcache_save_cache_word.read() << std::hex
               << " / DATA = " << r_dcache_save_wdata.read()
@@ -2462,5 +2216,5 @@
         {
             // miss if write not cacheable, and previous non cacheable write registered
-            if ( not r_dcache_save_cacheable.read() and r_dcache_pending_unc_write.read() ) 
+            if ( not r_dcache_save_cacheable.read() and r_dcache_pending_unc_write.read() )
             {
                 wbuf_write_miss = true;
@@ -2472,5 +2226,5 @@
                                          r_dcache_save_wdata.read(),
                                          r_dcache_save_cacheable.read() );
-#ifdef INSTRUMENTATION 
+#ifdef INSTRUMENTATION
 m_cpt_wbuf_write++;
 #endif
@@ -2487,6 +2241,6 @@
         } // end WBUF update
 
-        // Computing the response to processor, 
-        // and the next value for r_dcache_fsm 
+        // Computing the response to processor,
+        // and the next value for r_dcache_fsm
 
         // itlb/dtlb invalidation self-request
@@ -2498,15 +2252,8 @@
 
         // coherence request (from CC_RECEIVE FSM)
-        else if ( r_tgt_dcache_req.read() )   
-        {
-            r_dcache_fsm_cc_save   = r_dcache_fsm.read();
-            r_dcache_fsm           = DCACHE_CC_CHECK;
-        }
-
-        // cleanup ack request (from CC_RECEIVE FSM)
-        else if ( r_cleanup_dcache_req.read() )
-        {
-            r_dcache_fsm_cc_save   = r_dcache_fsm.read();
-            r_dcache_fsm           = DCACHE_CC_CLACK;
+        else if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
         }
 
@@ -2528,5 +2275,5 @@
             // They are executed in this DCACHE_IDLE state.
             // The processor must not be in user mode
-            if (m_dreq.type == iss_t::XTN_READ) 
+            if (m_dreq.type == iss_t::XTN_READ)
             {
                 int xtn_opcode = (int)m_dreq.addr/4;
@@ -2535,5 +2282,5 @@
                 if (m_dreq.mode  == iss_t::MODE_USER)
                 {
-                    r_mmu_detr   = MMU_READ_PRIVILEGE_VIOLATION; 
+                    r_mmu_detr   = MMU_READ_PRIVILEGE_VIOLATION;
                     r_mmu_dbvar  = m_dreq.addr;
                     m_drsp.valid = true;
@@ -2542,7 +2289,7 @@
                     r_dcache_fsm = DCACHE_IDLE;
                 }
-                else 
-                {
-                    switch( xtn_opcode ) 
+                else
+                {
+                    switch( xtn_opcode )
                     {
                     case iss_t::XTN_INS_ERROR_TYPE:
@@ -2559,5 +2306,5 @@
 
                     case iss_t::XTN_INS_BAD_VADDR:
-                        m_drsp.rdata = r_mmu_ibvar.read();       
+                        m_drsp.rdata = r_mmu_ibvar.read();
                         m_drsp.valid = true;
                         m_drsp.error = false;
@@ -2565,5 +2312,5 @@
 
                     case iss_t::XTN_DATA_BAD_VADDR:
-                        m_drsp.rdata = r_mmu_dbvar.read();        
+                        m_drsp.rdata = r_mmu_dbvar.read();
                         m_drsp.valid = true;
                         m_drsp.error = false;
@@ -2607,5 +2354,5 @@
 
                     default:
-                        r_mmu_detr = MMU_READ_UNDEFINED_XTN; 
+                        r_mmu_detr = MMU_READ_UNDEFINED_XTN;
                         r_mmu_dbvar  = m_dreq.addr;
                         m_drsp.valid = true;
@@ -2623,5 +2370,5 @@
             // Caches can be invalidated or flushed in user mode,
             // and the sync instruction can be executed in user mode
-            else if (m_dreq.type == iss_t::XTN_WRITE) 
+            else if (m_dreq.type == iss_t::XTN_WRITE)
             {
                 int xtn_opcode      = (int)m_dreq.addr/4;
@@ -2636,5 +2383,5 @@
                      (xtn_opcode != iss_t::XTN_ICACHE_FLUSH) )
                 {
-                    r_mmu_detr   = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                    r_mmu_detr   = MMU_WRITE_PRIVILEGE_VIOLATION;
                     r_mmu_dbvar  = m_dreq.addr;
                     m_drsp.valid = true;
@@ -2645,6 +2392,6 @@
                 else
                 {
-                    switch( xtn_opcode ) 
-                    {     
+                    switch( xtn_opcode )
+                    {
                     case iss_t::XTN_PTPR:   			// itlb & dtlb must be flushed
                         r_dcache_xtn_req = true;
@@ -2652,5 +2399,5 @@
                         break;
 
-                    case iss_t::XTN_TLB_MODE:			// no cache or tlb access 
+                    case iss_t::XTN_TLB_MODE:			// no cache or tlb access
                         r_mmu_mode       = m_dreq.wdata;
                         m_drsp.valid     = true;
@@ -2659,10 +2406,10 @@
 
                     case iss_t::XTN_DTLB_INVAL:     		// dtlb access
-                        r_dcache_fsm     = DCACHE_XTN_DT_INVAL;  
+                        r_dcache_fsm     = DCACHE_XTN_DT_INVAL;
                         break;
 
                     case iss_t::XTN_ITLB_INVAL:     		// itlb access
                         r_dcache_xtn_req = true;
-                        r_dcache_fsm     = DCACHE_XTN_IT_INVAL;  
+                        r_dcache_fsm     = DCACHE_XTN_IT_INVAL;
                         break;
 
@@ -2673,34 +2420,34 @@
                     case iss_t::XTN_MMU_DCACHE_PA_INV:  	// dcache, dtlb & itlb access
                         r_dcache_fsm     = DCACHE_XTN_DC_INVAL_PA;
-                        if (sizeof(paddr_t) <= 32) 
+                        if (sizeof(paddr_t) <= 32)
                         {
                             assert(r_mmu_word_hi.read() == 0 &&
                             "high bits should be 0 for 32bit paddr");
                             r_dcache_save_paddr = (paddr_t)r_mmu_word_lo.read();
-                        } 
-                        else 
+                        }
+                        else
                         {
-                            r_dcache_save_paddr = (paddr_t)r_mmu_word_hi.read() << 32 | 
+                            r_dcache_save_paddr = (paddr_t)r_mmu_word_hi.read() << 32 |
                                                   (paddr_t)r_mmu_word_lo.read();
                         }
                         break;
 
-                    case iss_t::XTN_DCACHE_FLUSH:   	       // itlb and dtlb must be reset  
+                    case iss_t::XTN_DCACHE_FLUSH:   	       // itlb and dtlb must be reset
                         r_dcache_flush_count = 0;
-                        r_dcache_fsm     = DCACHE_XTN_DC_FLUSH; 
+                        r_dcache_fsm     = DCACHE_XTN_DC_FLUSH;
                         break;
 
                     case iss_t::XTN_ICACHE_INVAL:   		// icache and itlb access
                         r_dcache_xtn_req = true;
-                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_VA; 
+                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_VA;
                         break;
 
-                    case iss_t::XTN_MMU_ICACHE_PA_INV:		// icache access 
+                    case iss_t::XTN_MMU_ICACHE_PA_INV:		// icache access
                         r_dcache_xtn_req = true;
-                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_PA; 
+                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_PA;
                         break;
 
                     case iss_t::XTN_ICACHE_FLUSH:   		// icache access
-                        r_dcache_xtn_req = true; 
+                        r_dcache_xtn_req = true;
                         r_dcache_fsm     = DCACHE_XTN_IC_FLUSH;
                         break;
@@ -2733,7 +2480,7 @@
                         r_dcache_fsm     = DCACHE_IDLE;
 		            break;
-	
+
                     default:
-                        r_mmu_detr   = MMU_WRITE_UNDEFINED_XTN; 
+                        r_mmu_detr   = MMU_WRITE_UNDEFINED_XTN;
                         r_mmu_dbvar  = m_dreq.addr;
                         m_drsp.valid = true;
@@ -2742,5 +2489,5 @@
                         break;
                     } // end switch xtn_opcode
-                } // end else 
+                } // end else
             } // end if XTN_WRITE
 
@@ -2751,5 +2498,5 @@
             //   and there is no access rights checking.
             // - If DTLB activated : cacheability is defined by the C bit in the PTE,
-            //   and the U & W bits of the PTE are checked, as well as the DTLB hit. 
+            //   and the U & W bits of the PTE are checked, as well as the DTLB hit.
             //   Jumps to the TLB_MISS sub-fsm in case of dtlb miss.
             else
@@ -2758,5 +2505,5 @@
                 bool	    cacheable;
 
-                if ( not (r_mmu_mode.read() & DATA_TLB_MASK) )		// dtlb not activated 
+                if ( not (r_mmu_mode.read() & DATA_TLB_MASK) )		// dtlb not activated
                 {
                     valid_req     = true;
@@ -2773,13 +2520,13 @@
                         else cacheable = tlb_flags.c;
 
-                        // access rights checking 
-                        if ( not tlb_flags.u and (m_dreq.mode == iss_t::MODE_USER)) 
+                        // access rights checking
+                        if ( not tlb_flags.u and (m_dreq.mode == iss_t::MODE_USER))
                         {
-                            if ( (m_dreq.type == iss_t::DATA_READ) or 
+                            if ( (m_dreq.type == iss_t::DATA_READ) or
                                  (m_dreq.type == iss_t::DATA_LL) )
                             {
                                 r_mmu_detr = MMU_READ_PRIVILEGE_VIOLATION;
                             }
-                            else 
+                            else
                             {
                                 r_mmu_detr = MMU_WRITE_PRIVILEGE_VIOLATION;
@@ -2793,14 +2540,14 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << ".DCACHE_IDLE> HIT in dtlb, but privilege violation" << std::endl;
 }
 #endif
                         }
-                        else if ( not tlb_flags.w and 
-                                  ((m_dreq.type == iss_t::DATA_WRITE) or 
-                                   (m_dreq.type == iss_t::DATA_SC)) ) 
+                        else if ( not tlb_flags.w and
+                                  ((m_dreq.type == iss_t::DATA_WRITE) or
+                                   (m_dreq.type == iss_t::DATA_SC)) )
                         {
-                            r_mmu_detr   = MMU_WRITE_ACCES_VIOLATION;  
+                            r_mmu_detr   = MMU_WRITE_ACCES_VIOLATION;
                             valid_req    = false;
                             r_mmu_dbvar  = m_dreq.addr;
@@ -2811,5 +2558,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << ".DCACHE_IDLE> HIT in dtlb, but writable violation" << std::endl;
 }
@@ -2825,5 +2572,5 @@
                         valid_req            = false;
                         r_dcache_tlb_vaddr   = m_dreq.addr;
-                        r_dcache_tlb_ins     = false; 
+                        r_dcache_tlb_ins     = false;
                         r_dcache_fsm         = DCACHE_TLB_MISS;
                     }
@@ -2837,7 +2584,7 @@
                     // The read requests are taken only if there is no cache update.
                     // We request a VCI transaction to CMD FSM if miss or uncachable
-                    if ( ((m_dreq.type == iss_t::DATA_READ)) 
+                    if ( ((m_dreq.type == iss_t::DATA_READ))
                           and not r_dcache_updt_req.read() )
-                    { 
+                    {
                         if ( cacheable )           	// cacheable read
                         {
@@ -2855,5 +2602,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << ".DCACHE_IDLE> READ MISS in dcache" << std::endl;
 }
@@ -2877,5 +2624,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << ".DCACHE_IDLE> READ HIT in dcache" << std::endl;
 }
@@ -2892,5 +2639,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << ".DCACHE_IDLE> READ UNCACHEABLE in dcache" << std::endl;
 }
@@ -2904,5 +2651,5 @@
                     else if (m_dreq.type == iss_t::DATA_LL)
                     {
-                        // register paddr in LLSC buffer 
+                        // register paddr in LLSC buffer
                         r_dcache_llsc_paddr = paddr;
                         r_dcache_llsc_count = LLSC_TIMEOUT;
@@ -2918,5 +2665,5 @@
 
                     // WRITE request:
-                    // If the TLB is activated and the PTE Dirty bit is not set, we stall 
+                    // If the TLB is activated and the PTE Dirty bit is not set, we stall
                     // the processor and set the Dirty bit before handling the write request,
                     // going to the DCACHE_DIRTY_GT_PTE state.
@@ -2927,5 +2674,5 @@
                     else if ( m_dreq.type == iss_t::DATA_WRITE )
                     {
-                        if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
+                        if ( (r_mmu_mode.read() & DATA_TLB_MASK )
                               and not tlb_flags.d )		// Dirty bit must be set
                         {
@@ -2961,18 +2708,18 @@
                         }
                     } // end WRITE
- 
+
                     // SC request:
-                    // If the TLB is activated and the PTE Dirty bit is not set, we stall 
-                    // the processor and set the Dirty bit before handling the write request, 
+                    // If the TLB is activated and the PTE Dirty bit is not set, we stall
+                    // the processor and set the Dirty bit before handling the write request,
                     // going to the DCACHE_DIRTY_GT_PTE state.
                     // If we don't need to set the Dirty bit, we test the llsc buffer:
                     // If failure, we send a negative response to processor.
-                    // If success, we request a SC transaction to CMD FSM and go 
+                    // If success, we request a SC transaction to CMD FSM and go
                     // to DCACHE_SC_WAIT state.
-                    // We don't check a possible write hit in dcache, as the cache update 
+                    // We don't check a possible write hit in dcache, as the cache update
                     // is done by the coherence transaction induced by the SC...
                     else if ( m_dreq.type == iss_t::DATA_SC )
                     {
-                        if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
+                        if ( (r_mmu_mode.read() & DATA_TLB_MASK )
                               and not tlb_flags.d )			// Dirty bit must be set
                         {
@@ -3018,8 +2765,8 @@
                     } // end SC
                 } // end valid_req
-            }  // end if read/write/ll/sc request	
+            }  // end if read/write/ll/sc request
         } // end processor request
-        
-        // itlb miss request 
+
+        // itlb miss request
     	else if ( r_icache_tlb_miss_req.read() and not wbuf_write_miss )
         {
@@ -3030,14 +2777,14 @@
 
         // Computing requests for P1 stage : r_dcache_wbuf_req & r_dcache_updt_req
-        r_dcache_updt_req = updt_request; 
+        r_dcache_updt_req = updt_request;
         r_dcache_wbuf_req = wbuf_request or
                             (r_dcache_wbuf_req.read() and wbuf_write_miss);
         break;
-    } 
+    }
     /////////////////////
     case DCACHE_TLB_MISS: // This is the entry point for the sub-fsm handling all tlb miss.
                           // Input arguments are:
                           // - r_dcache_tlb_vaddr
-                          // - r_dcache_tlb_ins (true when itlb miss) 
+                          // - r_dcache_tlb_ins (true when itlb miss)
                           // The sub-fsm access the dcache to find the missing TLB entry,
                           // and activates the cache miss procedure in case of miss.
@@ -3045,5 +2792,5 @@
                           // It uses atomic access to update the R/L access bits
                           // in the page table if required.
-                          // It directly updates the itlb or dtlb, and writes into the 
+                          // It directly updates the itlb or dtlb, and writes into the
                           // r_mmu_ins_* or r_mmu_data* error reporting registers.
     {
@@ -3080,42 +2827,51 @@
 if ( m_debug_dcache_fsm )
 {
-    if ( r_dcache_tlb_ins.read() ) 
+    if ( r_dcache_tlb_ins.read() )
     {
         std::cout << "  <PROC " << name() << ".DCACHE_TLB_MISS> ITLB miss";
     }
     else
-    {                           
+    {
         std::cout << "  <PROC " << name() << ".DCACHE_TLB_MISS> DTLB miss";
     }
     std::cout << " / VADDR = " << std::hex << r_dcache_tlb_vaddr.read()
-              << " / BYPASS = " << bypass 
+              << " / BYPASS = " << bypass
               << " / PTE_ADR = " << pte_paddr << std::endl;
 }
 #endif
-  
-        break;
-    }
-    /////////////////////////  
+
+        break;
+    }
+    /////////////////////////
     case DCACHE_TLB_PTE1_GET:	// try to read a PT1 entry in dcache
     {
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         uint32_t 	entry;
         size_t		way;
         size_t		set;
         size_t		word;
-
-        bool     hit = r_dcache.read( r_dcache_tlb_paddr.read(),
-                                      &entry,
-                                      &way,
-                                      &set,
-                                      &word );
+        int         cache_state;
+        r_dcache.read( r_dcache_tlb_paddr.read(),
+                       &entry,
+                       &way,
+                       &set,
+                       &word,
+                       &cache_state );
 #ifdef INSTRUMENTATION
 m_cpt_dcache_data_read++;
 m_cpt_dcache_dir_read++;
 #endif
-        if ( hit )	//  hit in dcache 
+        if ( cache_state == CACHE_SLOT_STATE_VALID )   // hit in dcache
         {
             if ( not (entry & PTE_V_MASK) )	// unmapped
             {
-                if ( r_dcache_tlb_ins.read() ) 
+                if ( r_dcache_tlb_ins.read() )
                 {
                     r_mmu_ietr             = MMU_READ_PT1_UNMAPPED;
@@ -3144,5 +2900,5 @@
 }
 #endif
-  
+
             }
             else if( entry & PTE_T_MASK ) 	//  PTD : me must access PT2
@@ -3155,6 +2911,6 @@
                 {
                     r_itlb.set_bypass(r_dcache_tlb_vaddr.read(),
-                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1), 
-                                      r_dcache_tlb_paddr.read() / (m_icache_words<<2) ); 
+                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1),
+                                      r_dcache_tlb_paddr.read() / (m_icache_words<<2) );
                 }
                 else					// dtlb
@@ -3164,5 +2920,5 @@
                                       r_dcache_tlb_paddr.read() / (m_dcache_words<<2) );
                 }
-                r_dcache_tlb_paddr = 
+                r_dcache_tlb_paddr =
                     (paddr_t)(entry & ((1<<(m_paddr_nbits-PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
                     (paddr_t)(((r_dcache_tlb_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
@@ -3203,11 +2959,16 @@
             }
         }
+        else if ( cache_state == CACHE_SLOT_STATE_ZOMBI ) // pending cleanup
+        {
+            // stalled until cleanup is acknowledged
+            r_dcache_fsm   = DCACHE_TLB_PTE1_GET;
+        }
         else		// we must load the missing cache line in dcache
         {
-            r_dcache_vci_miss_req  = true;		
-            r_dcache_vci_paddr     = r_dcache_tlb_paddr.read(); 
-            r_dcache_save_paddr    = r_dcache_tlb_paddr.read(); 
+            r_dcache_vci_miss_req  = true;
+            r_dcache_vci_paddr     = r_dcache_tlb_paddr.read();
+            r_dcache_save_paddr    = r_dcache_tlb_paddr.read();
             r_dcache_miss_type     = PTE1_MISS;
-            r_dcache_fsm           = DCACHE_MISS_SELECT;	 
+            r_dcache_fsm           = DCACHE_MISS_SELECT;
 
 #if DEBUG_DCACHE
@@ -3222,5 +2983,5 @@
     }
     ////////////////////////////
-    case DCACHE_TLB_PTE1_SELECT:	// select a slot for PTE1 
+    case DCACHE_TLB_PTE1_SELECT:	// select a slot for PTE1
     {
         size_t 	way;
@@ -3230,5 +2991,5 @@
         {
             r_itlb.select( r_dcache_tlb_vaddr.read(),
-                           true,  // PTE1 
+                           true,  // PTE1
                            &way,
                            &set );
@@ -3240,5 +3001,5 @@
         {
             r_dtlb.select( r_dcache_tlb_vaddr.read(),
-                           true,  // PTE1 
+                           true,  // PTE1
                            &way,
                            &set );
@@ -3254,7 +3015,7 @@
 if ( m_debug_dcache_fsm )
 {
-    if ( r_dcache_tlb_ins.read() ) 
+    if ( r_dcache_tlb_ins.read() )
         std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE1_SELECT> Select a slot in ITLB:";
-    else                           
+    else
         std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE1_SELECT> Select a slot in DTLB:";
         std::cout << " way = " << std::dec << way
@@ -3271,13 +3032,13 @@
                                 //   the coherence mechanism.
     {
-        paddr_t	  nline    = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);   
+        paddr_t	  nline    = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);
         uint32_t  pte      = r_dcache_tlb_pte_flags.read();
         bool	  pt_updt  = false;
         bool	  local    = true;
 
-        // We should compute the access locality: 
+        // We should compute the access locality:
         // The PPN MSB bits define the destination cluster index.
-        // The m_srcid_d MSB bits define the source cluster index.
-        // The number of bits to compare depends on the number of clusters, 
+        // The m_srcid MSB bits define the source cluster index.
+        // The number of bits to compare depends on the number of clusters,
         // and can be obtained in the mapping table.
         // As long as this computation is not done, all access are local.
@@ -3308,11 +3069,11 @@
         if ( not pt_updt )					// update TLB and return
         {
-            if ( r_dcache_tlb_ins.read() )  
+            if ( r_dcache_tlb_ins.read() )
             {
                 r_itlb.write( true,		// 2M page
                               pte,
                               0,		// argument unused for a PTE1
-                              r_dcache_tlb_vaddr.read(),    
-                              r_dcache_tlb_way.read(), 
+                              r_dcache_tlb_vaddr.read(),
+                              r_dcache_tlb_way.read(),
                               r_dcache_tlb_set.read(),
                               nline );
@@ -3336,6 +3097,6 @@
                               pte,
                               0,		// argument unused for a PTE1
-                              r_dcache_tlb_vaddr.read(),    
-                              r_dcache_tlb_way.read(), 
+                              r_dcache_tlb_vaddr.read(),
+                              r_dcache_tlb_way.read(),
                               r_dcache_tlb_set.read(),
                               nline );
@@ -3358,5 +3119,5 @@
         else                            // update page table but not TLB
         {
-            r_dcache_fsm = DCACHE_TLB_LR_UPDT; 
+            r_dcache_fsm = DCACHE_TLB_LR_UPDT;
 
 #if DEBUG_DCACHE
@@ -3373,25 +3134,35 @@
     case DCACHE_TLB_PTE2_GET:	// Try to get a PTE2 (64 bits) in the dcache
     {
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         uint32_t 	pte_flags;
         uint32_t 	pte_ppn;
         size_t   	way;
         size_t   	set;
-        size_t		word; 
- 
-        bool     hit = r_dcache.read( r_dcache_tlb_paddr.read(),
-                                      &pte_flags,
-                                      &pte_ppn,
-                                      &way,
-                                      &set,
-                                      &word );
+        size_t		word;
+        int         cache_state;
+
+        r_dcache.read( r_dcache_tlb_paddr.read(),
+                       &pte_flags,
+                       &pte_ppn,
+                       &way,
+                       &set,
+                       &word,
+                       &cache_state );
 #ifdef INSTRUMENTATION
 m_cpt_dcache_data_read++;
 m_cpt_dcache_dir_read++;
 #endif
-        if ( hit )      // request hits in dcache 
+        if ( cache_state == CACHE_SLOT_STATE_VALID )   // hit in dcache
         {
             if ( not (pte_flags & PTE_V_MASK) )	// unmapped
             {
-                if ( r_dcache_tlb_ins.read() ) 
+                if ( r_dcache_tlb_ins.read() )
                 {
                     r_mmu_ietr             = MMU_READ_PT2_UNMAPPED;
@@ -3404,15 +3175,15 @@
                     r_mmu_detr             = MMU_READ_PT2_UNMAPPED;
                     r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
-                    m_drsp.valid             = true;
-                    m_drsp.error             = true;
+                    m_drsp.valid           = true;
+                    m_drsp.error           = true;
                 }
-                r_dcache_fsm          = DCACHE_IDLE;
+                r_dcache_fsm               = DCACHE_IDLE;
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_TLB_PTE2_GET> HIT in dcache, but PTE is unmapped"
-              << " PTE_FLAGS = " << std::hex << pte_flags 
+              << " PTE_FLAGS = " << std::hex << pte_flags
               << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
 }
@@ -3433,5 +3204,5 @@
 {
     std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE2_GET> HIT in dcache:"
-              << " PTE_FLAGS = " << std::hex << pte_flags 
+              << " PTE_FLAGS = " << std::hex << pte_flags
               << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
 }
@@ -3439,7 +3210,12 @@
              }
         }
+        else if ( cache_state == CACHE_SLOT_STATE_ZOMBI ) // pending cleanup
+        {
+            // stalled until cleanup is acknowledged
+            r_dcache_fsm   = DCACHE_TLB_PTE2_GET;
+        }
         else            // we must load the missing cache line in dcache
         {
-            r_dcache_fsm          = DCACHE_MISS_SELECT; 
+            r_dcache_fsm          = DCACHE_MISS_SELECT;
             r_dcache_vci_miss_req = true;
             r_dcache_vci_paddr    = r_dcache_tlb_paddr.read();
@@ -3450,5 +3226,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_TLB_PTE2_GET> MISS in dcache:"
               << " PTE address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
@@ -3467,5 +3243,5 @@
         {
             r_itlb.select( r_dcache_tlb_vaddr.read(),
-                           false,	// PTE2 
+                           false,	// PTE2
                            &way,
                            &set );
@@ -3477,5 +3253,5 @@
         {
             r_dtlb.select( r_dcache_tlb_vaddr.read(),
-                           false,	// PTE2 
+                           false,	// PTE2
                            &way,
                            &set );
@@ -3488,9 +3264,9 @@
 if ( m_debug_dcache_fsm )
 {
-    if ( r_dcache_tlb_ins.read() ) 
-        std::cout << "  <PROC " << name() 
+    if ( r_dcache_tlb_ins.read() )
+        std::cout << "  <PROC " << name()
                   << " DCACHE_TLB_PTE2_SELECT> Select a slot in ITLB:";
-    else                           
-        std::cout << "  <PROC " << name() 
+    else
+        std::cout << "  <PROC " << name()
                   << " DCACHE_TLB_PTE2_SELECT> Select a slot in DTLB:";
         std::cout << " way = " << std::dec << way
@@ -3510,5 +3286,5 @@
                                 //   the coherence mechanism.
     {
-        paddr_t	        nline     = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);   
+        paddr_t	        nline     = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);
         uint32_t        pte_flags = r_dcache_tlb_pte_flags.read();
         uint32_t        pte_ppn   = r_dcache_tlb_pte_ppn.read();
@@ -3516,8 +3292,8 @@
         bool            local     = true;
 
-        // We should compute the access locality: 
+        // We should compute the access locality:
         // The PPN MSB bits define the destination cluster index.
-        // The m_srcid_d MSB bits define the source cluster index.
-        // The number of bits to compare depends on the number of clusters, 
+        // The m_srcid MSB bits define the source cluster index.
+        // The number of bits to compare depends on the number of clusters,
         // and can be obtained in the mapping table.
         // As long as this computation is not done, all access are local.
@@ -3545,14 +3321,14 @@
             }
         }
-        
-        if ( not pt_updt )                       // update TLB 
-        {
-            if ( r_dcache_tlb_ins.read() )  
+
+        if ( not pt_updt )                       // update TLB
+        {
+            if ( r_dcache_tlb_ins.read() )
             {
                 r_itlb.write( false,	// 4K page
                               pte_flags,
                               pte_ppn,
-                              r_dcache_tlb_vaddr.read(),    
-                              r_dcache_tlb_way.read(), 
+                              r_dcache_tlb_vaddr.read(),
+                              r_dcache_tlb_way.read(),
                               r_dcache_tlb_set.read(),
                               nline );
@@ -3564,5 +3340,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_TLB_PTE2_UPDT> write PTE2 in ITLB"
               << " / set = " << std::dec << r_dcache_tlb_set.read()
@@ -3577,6 +3353,6 @@
                               pte_flags,
                               pte_ppn,
-                              r_dcache_tlb_vaddr.read(),    
-                              r_dcache_tlb_way.read(), 
+                              r_dcache_tlb_vaddr.read(),
+                              r_dcache_tlb_way.read(),
                               r_dcache_tlb_set.read(),
                               nline );
@@ -3588,5 +3364,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_TLB_PTE2_UPDT> write PTE2 in DTLB"
               << " / set = " << std::dec << r_dcache_tlb_set.read()
@@ -3606,5 +3382,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_TLB_PTE2_UPDT> L/R bit update required" << std::endl;
 }
@@ -3619,5 +3395,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_TLB_LR_UPDT> Update dcache: (L/R) bit" << std::endl;
 }
@@ -3637,5 +3413,5 @@
     ////////////////////////
     case DCACHE_TLB_LR_WAIT:		// Waiting the response to SC transaction for DIRTY bit.
-                                    // We consume the response in rsp FIFO, 
+                                    // We consume the response in rsp FIFO,
                                     // and exit the sub-fsm, but we don't
                                     // analyse the response, because we don't
@@ -3645,8 +3421,8 @@
 
     {
-        // external coherence request
-        if ( r_tgt_dcache_req )
-        {
-            r_dcache_fsm         = DCACHE_CC_CHECK;
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
             r_dcache_fsm_cc_save = r_dcache_fsm.read();
             break;
@@ -3664,9 +3440,9 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_TLB_LR_WAIT> SC response received" << std::endl;
 }
 #endif
-            vci_rsp_fifo_dcache_get = true;     
+            vci_rsp_fifo_dcache_get = true;
             r_dcache_fsm            = DCACHE_TLB_RETURN;
         }
@@ -3679,5 +3455,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_TLB_RETURN> TLB MISS completed" << std::endl;
 }
@@ -3690,5 +3466,5 @@
     case DCACHE_XTN_SWITCH:		// The r_ptpr registers must be written,
                                 // and both itlb and dtlb must be flushed.
-                                // Caution : the itlb miss requests must be taken 
+                                // Caution : the itlb miss requests must be taken
                                 // to avoid dead-lock in case of simultaneous ITLB miss
     {
@@ -3716,10 +3492,10 @@
                                 // as there is a risk of dead-lock
     {
-        // external coherence request 
-        if ( r_tgt_dcache_req.read() )   
-        {
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
             r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CHECK;
-        }        
+        }
 
         if ( r_wbuf.empty() )
@@ -3732,16 +3508,16 @@
     ////////////////////////
     case DCACHE_XTN_IC_FLUSH:		// Waiting completion of an XTN request to the ICACHE FSM
-    case DCACHE_XTN_IC_INVAL_VA:	// Caution : the itlb miss requests must be taken 
+    case DCACHE_XTN_IC_INVAL_VA:	// Caution : the itlb miss requests must be taken
     case DCACHE_XTN_IC_INVAL_PA:	// because the XTN_ICACHE_INVAL request to icache
     case DCACHE_XTN_IT_INVAL:		// can generate an itlb miss,
                                     // and because it can exist a simultaneous ITLB miss
     {
-        // external coherence request
-        if ( r_tgt_dcache_req )   
-        {
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
             r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CHECK;
             break;
-        }  
+        }
 
         // itlb miss request
@@ -3755,5 +3531,5 @@
 
         // test if XTN request to icache completed
-        if ( not r_dcache_xtn_req.read() ) 
+        if ( not r_dcache_xtn_req.read() )
         {
             r_dcache_fsm = DCACHE_IDLE;
@@ -3769,8 +3545,8 @@
                                 // We test here the slot state, and make the actual inval
                                 // (if line is valid) in DCACHE_XTN_DC_FLUSH_GO state.
-                                // A cleanup request is generated for each valid line. 
+                                // A cleanup request is generated for each valid line.
                                 // returns to IDLE and flush TLBs when last slot
     {
-        if ( not r_dcache_cleanup_req.read() ) // blocked until previous cleanup is sent
+        if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
         {
             int       state;
@@ -3790,7 +3566,8 @@
             {
                 // request cleanup
-                r_dcache_cleanup_req  = true;
-                r_dcache_cleanup_line = tag * m_icache_sets;
-                r_dcache_cleanup_way  = way;
+                r_dcache_cc_send_req   = true;
+                r_dcache_cc_send_nline = tag * m_dcache_sets;
+                r_dcache_cc_send_way   = way;
+                r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
 
                 // goes to DCACHE_XTN_DC_FLUSH_GO to inval directory
@@ -3799,9 +3576,9 @@
                 r_dcache_fsm          = DCACHE_XTN_DC_FLUSH_GO;
             }
-            else if ( r_dcache_flush_count.read() == 
+            else if ( r_dcache_flush_count.read() ==
                       (m_dcache_sets*m_dcache_ways - 1) )  // last slot
             {
-                r_dtlb.reset();    
-                r_itlb.reset(); 
+                r_dtlb.reset();
+                r_itlb.reset();
                 r_dcache_fsm = DCACHE_IDLE;
                 m_drsp.valid = true;
@@ -3809,5 +3586,5 @@
 
             // saturation counter
-            if ( r_dcache_flush_count.read() < (m_dcache_sets*m_dcache_ways - 1) )  
+            if ( r_dcache_flush_count.read() < (m_dcache_sets*m_dcache_ways - 1) )
                 r_dcache_flush_count = r_dcache_flush_count.read() + 1;
         }
@@ -3833,9 +3610,9 @@
                             CACHE_SLOT_STATE_ZOMBI );
 
-        if ( r_dcache_flush_count.read() == 
-             (m_dcache_sets*m_dcache_ways - 1) )  // last slot 
-        {
-            r_dtlb.reset();    
-            r_itlb.reset(); 
+        if ( r_dcache_flush_count.read() ==
+             (m_dcache_sets*m_dcache_ways - 1) )  // last slot
+        {
+            r_dtlb.reset();
+            r_itlb.reset();
             r_dcache_fsm = DCACHE_IDLE;
             m_drsp.valid = true;
@@ -3858,5 +3635,5 @@
     case DCACHE_XTN_DC_INVAL_VA:  // selective cache line invalidate with virtual address
                                   // requires 3 cycles: access tlb, read cache, inval cache
-                               	  // we compute the physical address in this state 
+                               	  // we compute the physical address in this state
     {
         paddr_t paddr;
@@ -3870,5 +3647,5 @@
 #endif
             hit = r_dtlb.translate( r_dcache_save_wdata.read(),
-                                    &paddr ); 
+                                    &paddr );
         }
         else 						// dtlb not activated
@@ -3891,11 +3668,11 @@
             r_dcache_tlb_ins    = false;		// dtlb
             r_dcache_tlb_vaddr  = r_dcache_save_wdata.read();
-            r_dcache_fsm        = DCACHE_TLB_MISS; 
-        } 
-  
+            r_dcache_fsm        = DCACHE_TLB_MISS;
+        }
+
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_XTN_DC_INVAL_VA> Compute physical address" << std::hex
               << " / VADDR = " << r_dcache_save_wdata.read()
@@ -3940,5 +3717,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_XTN_DC_INVAL_PA> Test hit in dcache" << std::hex
               << " / PADDR = " << r_dcache_save_paddr.read() << std::dec
@@ -3951,14 +3728,14 @@
     }
     ////////////////////////////
-    case DCACHE_XTN_DC_INVAL_GO:  // In this state, we invalidate the cache line 
+    case DCACHE_XTN_DC_INVAL_GO:  // In this state, we invalidate the cache line
         			              // Blocked if previous cleanup not completed
-                                  // Test if itlb or dtlb inval is required    
-    {
-        if ( not r_dcache_cleanup_req.read() )
+                                  // Test if itlb or dtlb inval is required
+    {
+        if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
         {
             size_t	way        = r_dcache_xtn_way.read();
             size_t	set        = r_dcache_xtn_set.read();
             paddr_t nline      = r_dcache_save_paddr.read() / (m_dcache_words<<2);
-   
+
 #ifdef INSTRUMENTATION
 m_cpt_dcache_dir_write++;
@@ -3970,12 +3747,13 @@
 
             // request cleanup
-            r_dcache_cleanup_req  = true;
-            r_dcache_cleanup_line = nline;
-            r_dcache_cleanup_way  = way;
-	    
-            // possible itlb & dtlb invalidate 
-            if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
-            {
-                r_dcache_tlb_inval_line = nline; 
+            r_dcache_cc_send_req   = true;
+            r_dcache_cc_send_nline = nline;
+            r_dcache_cc_send_way   = way;
+            r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
+
+            // possible itlb & dtlb invalidate
+            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
+            {
+                r_dcache_tlb_inval_line = nline;
                 r_dcache_tlb_inval_set  = 0;
                 r_dcache_fsm_scan_save  = DCACHE_XTN_DC_INVAL_END;
@@ -3983,5 +3761,5 @@
                 r_dcache_in_tlb[way*m_dcache_sets+set] = false;
             }
-            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
+            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
             {
                 r_itlb.reset();
@@ -4000,5 +3778,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_XTN_DC_INVAL_GO> Actual dcache inval" << std::hex
               << " / PADDR = " << r_dcache_save_paddr.read() << std::endl;
@@ -4019,5 +3797,5 @@
                                // if previous cleanup has been sent.
                                // Waiting in this state if no slot available
-                               // Set the r_dcache_cleanup_req flip-flop 
+                               // Set the r_dcache_cleanup_req flip-flop
                                // and the r_dcache_miss_clack flip-flop
                                // when a cleanup is required
@@ -4025,13 +3803,13 @@
         if ( m_dreq.valid) m_cost_data_miss_frz++;
 
-        // cleanup ack interrupt
-        if ( r_cleanup_dcache_req.read() )
-        {
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
             r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CLACK;
             break;
         }
 
-        if ( not r_dcache_cleanup_req.read() ) 
+        if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
         {
             bool     found;
@@ -4057,9 +3835,11 @@
                 if ( cleanup )
                 {
-                    r_dcache_cleanup_req  = true;
                     r_dcache_miss_clack   = true;
-                    r_dcache_cleanup_line = victim;
-                    r_dcache_cleanup_way  = way;
                     r_dcache_fsm          = DCACHE_MISS_CLEAN;
+                    // request cleanup
+                    r_dcache_cc_send_req   = true;
+                    r_dcache_cc_send_nline = victim;
+                    r_dcache_cc_send_way   = way;
+                    r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
                 }
                 else
@@ -4071,7 +3851,7 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_MISS_SELECT> Select a slot:" << std::dec
-              << " / WAY = "   << way 
+              << " / WAY = "   << way
               << " / SET = "   << set
               << " / PADDR = " << std::hex << r_dcache_save_paddr.read();
@@ -4090,9 +3870,9 @@
         if ( m_dreq.valid) m_cost_data_miss_frz++;
 
-        // cleanup ack interrupt
-        if ( r_cleanup_dcache_req.read() )
-        {
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
             r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CLACK;
             break;
         }
@@ -4101,5 +3881,5 @@
         size_t  set   = r_dcache_miss_set.read();
         paddr_t nline = r_dcache_save_paddr.read() / (m_dcache_words<<2);
-        
+
 #ifdef INSTRUMENTATION
 m_cpt_dcache_dir_read++;
@@ -4112,13 +3892,13 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_MISS_CLEAN> Switch to ZOMBI state" << std::dec
-              << " / way = "   << way 
-              << " / set = "   << set << std::endl; 
-}
-#endif
-        // if selective itlb & dtlb invalidate are required 
+              << " / way = "   << way
+              << " / set = "   << set << std::endl;
+}
+#endif
+        // if selective itlb & dtlb invalidate are required
         // the miss response is not handled before invalidate completed
-        if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
+        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
         {
             r_dcache_in_tlb[way*m_dcache_sets+set] = false;
@@ -4128,5 +3908,5 @@
             r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
         }
-        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
+        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
         {
             r_itlb.reset();
@@ -4148,27 +3928,30 @@
         if ( m_dreq.valid) m_cost_data_miss_frz++;
 
-        // coherence interrupt
-        if ( r_tgt_dcache_req ) 
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm;
-            r_dcache_fsm         = DCACHE_CC_CHECK;
+/**/
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+        std::cout << "  <PROC " << name()
+              << " r_cc_receive_dcache_req = " << r_cc_receive_dcache_req.read() << std::endl;
+        std::cout << "  <PROC " << name()
+              << " r_dcache_miss_inval = " << r_dcache_miss_inval.read() << std::endl;
+}
+#endif
+
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
             break;
         }
 
-        // cleanup ack interrupt
-        if ( r_cleanup_dcache_req.read() )
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CLACK;
-            break;
-        }
-
         if ( r_vci_rsp_data_error.read() ) 			// bus error
         {
             switch ( r_dcache_miss_type.read() )
             {
-                case PROC_MISS:  
-                {
-                    r_mmu_detr            = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                case PROC_MISS:
+                {
+                    r_mmu_detr            = MMU_READ_DATA_ILLEGAL_ACCESS;
                     r_mmu_dbvar           = r_dcache_save_vaddr.read();
                     m_drsp.valid            = true;
@@ -4196,5 +3979,5 @@
                     break;
                 }
-                case PTE2_MISS: 
+                case PTE2_MISS:
                 {
                     if ( r_dcache_tlb_ins.read() )
@@ -4222,5 +4005,5 @@
             r_dcache_miss_word = 0;
 	        r_dcache_fsm       = DCACHE_MISS_DATA_UPDT;
-        }	
+        }
         break;
     }
@@ -4230,12 +4013,15 @@
         if ( m_dreq.valid) m_cost_data_miss_frz++;
 
-        // cleanup ack interrupt
-        if ( r_cleanup_dcache_req.read() )
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CLACK;
-            break;
-        }
-        
+/**/
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+        std::cout << "  <PROC " << name()
+              << " r_cc_receive_dcache_req = " << r_cc_receive_dcache_req.read() << std::endl;
+        std::cout << "  <PROC " << name()
+              << " r_dcache_miss_inval = " << r_dcache_miss_inval.read() << std::endl;
+}
+#endif
+
         if ( r_vci_rsp_fifo_dcache.rok() )	// one word available
         {
@@ -4250,16 +4036,16 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_MISS_DATA_UPDT> Write one word:"
               << " / DATA = "  << r_vci_rsp_fifo_dcache.read()
-              << " / WAY = "   << std::dec << r_dcache_miss_way.read() 
+              << " / WAY = "   << std::dec << r_dcache_miss_way.read()
               << " / SET = "   << r_dcache_miss_set.read()
-              << " / WORD = "  << r_dcache_miss_word.read() << std::endl; 
+              << " / WORD = "  << r_dcache_miss_word.read() << std::endl;
 }
 #endif
             vci_rsp_fifo_dcache_get = true;
             r_dcache_miss_word = r_dcache_miss_word.read() + 1;
-               
-            if ( r_dcache_miss_word.read() == (m_dcache_words-1) ) // last word 
+
+            if ( r_dcache_miss_word.read() == (m_dcache_words-1) ) // last word
             {
                 r_dcache_fsm = DCACHE_MISS_DIR_UPDT;
@@ -4276,33 +4062,38 @@
                                 // - If matching coherence request, switch directory slot
                                 //   to ZOMBI state, and send a cleanup request.
-    { 
+    {
         if ( m_dreq.valid) m_cost_data_miss_frz++;
 
-        // coherence interrupt
-        if ( r_tgt_dcache_req ) 
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm;
-            r_dcache_fsm         = DCACHE_CC_CHECK;
+/**/
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+        std::cout << "  <PROC " << name()
+              << " r_cc_receive_dcache_req = " << r_cc_receive_dcache_req.read() << std::endl;
+        std::cout << "  <PROC " << name()
+              << " r_dcache_miss_inval = " << r_dcache_miss_inval.read() << std::endl;
+}
+#endif
+
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
             break;
         }
 
-        // cleanup ack interrupt
-        if ( r_cleanup_dcache_req.read() )
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CLACK;
-            break;
-        }
-
         if ( not r_dcache_miss_clack.read() )  // waiting cleanup acknowledge
         {
             if ( r_dcache_miss_inval.read() ) // switch slot to ZOMBI state, and new cleanup
             {
-                if ( not r_dcache_cleanup_req.read() )
-                {
-                    r_dcache_cleanup_req    = true;
-                    r_dcache_cleanup_line   = r_dcache_save_paddr.read()/(m_dcache_words<<2);
-                    r_dcache_cleanup_way    = r_dcache_miss_way.read();
+                if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
+                {
                     r_dcache_miss_inval     = false;
+                    // request cleanup
+                    r_dcache_cc_send_req   = true;
+                    r_dcache_cc_send_nline = r_dcache_save_paddr.read()/(m_dcache_words<<2);
+                    r_dcache_cc_send_way   = r_dcache_miss_way.read();
+                    r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
 
 #ifdef INSTRUMENTATION
@@ -4316,12 +4107,14 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_MISS_DIR_UPDT> Switch slot to ZOMBI state"
-              << " PADDR = " << std::hex << r_dcache_save_paddr.read() 
-              << " / WAY = "   << std::dec << r_dcache_miss_way.read() 
+              << " PADDR = " << std::hex << r_dcache_save_paddr.read()
+              << " / WAY = "   << std::dec << r_dcache_miss_way.read()
               << " / SET = "   << r_dcache_miss_set.read() << std::endl;
 }
 #endif
                 }
+                else
+                    break;
             }
             else                              // switch slot to VALID state
@@ -4339,8 +4132,8 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_MISS_DIR_UPDT> Switch slot to VALID state"
-              << " PADDR = " << std::hex << r_dcache_save_paddr.read() 
-              << " / WAY = "   << std::dec << r_dcache_miss_way.read() 
+              << " PADDR = " << std::hex << r_dcache_save_paddr.read()
+              << " / WAY = "   << std::dec << r_dcache_miss_way.read()
               << " / SET = "   << r_dcache_miss_set.read() << std::endl;
 
@@ -4356,6 +4149,5 @@
                 r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
             }
-                    
-            if      (r_dcache_miss_type.read()==PTE1_MISS) r_dcache_fsm = DCACHE_TLB_PTE1_GET; 
+            if      (r_dcache_miss_type.read()==PTE1_MISS) r_dcache_fsm = DCACHE_TLB_PTE1_GET;
             else if (r_dcache_miss_type.read()==PTE2_MISS) r_dcache_fsm = DCACHE_TLB_PTE2_GET;
             else                                           r_dcache_fsm = DCACHE_IDLE;
@@ -4366,23 +4158,15 @@
     case DCACHE_UNC_WAIT:  // waiting a response to an uncacheable read
     {
-        // coherence interrupt
-        if ( r_tgt_dcache_req.read() ) 
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm;
-            r_dcache_fsm         = DCACHE_CC_CHECK;
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
             break;
         }
 
-        // cleanup ack interrupt
-        if ( r_cleanup_dcache_req.read() )
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CLACK;
-            break;
-        }
-
         if ( r_vci_rsp_data_error.read() ) 	// bus error
         {
-            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
+            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS;
             r_mmu_dbvar          = m_dreq.addr;
             r_vci_rsp_data_error = false;
@@ -4394,6 +4178,6 @@
 	    else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
 	    {
-            // consume data 
-            vci_rsp_fifo_dcache_get = true;     
+            // consume data
+            vci_rsp_fifo_dcache_get = true;
             r_dcache_fsm            = DCACHE_IDLE;
 
@@ -4405,5 +4189,5 @@
 	            m_drsp.rdata        = r_vci_rsp_fifo_dcache.read();
             }
-	    }	
+	    }
         break;
     }
@@ -4411,23 +4195,15 @@
     case DCACHE_LL_WAIT:    // waiting VCI response to a LL transaction
     {
-        // coherence interrupt
-        if ( r_tgt_dcache_req.read() ) 
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm;
-            r_dcache_fsm         = DCACHE_CC_CHECK;
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
             break;
         }
 
-        // cleanup ack interrupt
-        if ( r_cleanup_dcache_req.read() )
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CLACK;
-            break;
-        }
-
         if ( r_vci_rsp_data_error.read() ) 	// bus error
         {
-            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
+            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS;
             r_mmu_dbvar          = m_dreq.addr;
             r_vci_rsp_data_error = false;
@@ -4439,5 +4215,5 @@
 	    else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
 	    {
-            // consume data 
+            // consume data
             vci_rsp_fifo_dcache_get = true;
 
@@ -4465,23 +4241,15 @@
     case DCACHE_SC_WAIT:	// waiting VCI response to a SC transaction
     {
-        // coherence interrupt
-        if ( r_tgt_dcache_req.read() ) 
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm;
-            r_dcache_fsm         = DCACHE_CC_CHECK;
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
             break;
         }
 
-        // cleanup ack interrupt
-        if ( r_cleanup_dcache_req.read() )
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CLACK;
-            break;
-        }
-
         if ( r_vci_rsp_data_error.read() ) 		// bus error
         {
-            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
+            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS;
             r_mmu_dbvar          = m_dreq.addr;
             r_vci_rsp_data_error = false;
@@ -4493,15 +4261,15 @@
 	    else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
 	    {
-            // consume response 
+            // consume response
             vci_rsp_fifo_dcache_get = true;
             m_drsp.valid            = true;
             m_drsp.rdata            = r_vci_rsp_fifo_dcache.read();
             r_dcache_fsm            = DCACHE_IDLE;
-	    }	
+	    }
         break;
     }
     //////////////////////////
-    case DCACHE_DIRTY_GET_PTE:		// This sub_fsm set the PTE Dirty bit in memory 
-                                    // before handling a processor WRITE or SC request  
+    case DCACHE_DIRTY_GET_PTE:		// This sub_fsm set the PTE Dirty bit in memory
+                                    // before handling a processor WRITE or SC request
                                     // Input argument is r_dcache_dirty_paddr
                                     // In this first state, we get PTE value in dcache
@@ -4526,10 +4294,10 @@
                        &state );
 
-        assert( (state == CACHE_SLOT_STATE_VALID) and 
+        assert( (state == CACHE_SLOT_STATE_VALID) and
         "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
 
         // request CAS transaction to CMD_FSM
-        r_dcache_dirty_way  = way; 
-        r_dcache_dirty_set  = set; 
+        r_dcache_dirty_way  = way;
+        r_dcache_dirty_set  = set;
 
         // check llsc reservation buffer
@@ -4547,8 +4315,8 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_DIRTY_GET_PTE> CAS request" << std::hex
-              << " / PTE_PADDR = " << r_dcache_dirty_paddr.read() 
-              << " / PTE_VALUE = " << pte << std::dec 
+              << " / PTE_PADDR = " << r_dcache_dirty_paddr.read()
+              << " / PTE_VALUE = " << pte << std::dec
               << " / SET = " << set
               << " / WAY = " << way << std::endl;
@@ -4565,17 +4333,9 @@
                                     // - if the CAS is a failure, we just retry the write.
     {
-        // coherence interrupt
-        if ( r_tgt_dcache_req ) 
-        {
-            r_dcache_fsm_cc_save = r_dcache_fsm;
-            r_dcache_fsm         = DCACHE_CC_CHECK;
-            break;
-        }
-
-        // cleanup ack interrupt
-        if ( r_cleanup_dcache_req.read() )
-        {
+        // coherence request (from CC_RECEIVE FSM)
+        if ( r_cc_receive_dcache_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
             r_dcache_fsm_cc_save = r_dcache_fsm.read();
-            r_dcache_fsm         = DCACHE_CC_CLACK;
             break;
         }
@@ -4595,44 +4355,9 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_DIRTY_WAIT> CAS completed" << std::endl;
 }
 #endif
         }
-        break;
-    }
-    /////////////////////
-    case DCACHE_CC_CLACK:   // This state is the entry point for the sub-FSM
-                            // handling cleanup ack requests for DCACHE.
-                            // We switch the directory slot to EMPTY state
-                            // and reset r_icache_miss_clack if the cleanup ack
-                            // is matching a pending miss.
-    {
-        if ( m_dreq.valid ) m_cost_data_miss_frz++;
-
-#ifdef INSTRUMENTATION
-m_cpt_dcache_dir_write++;
-#endif
-        r_dcache.write_dir( 0,
-                            r_cleanup_dcache_way.read(),
-                            r_cleanup_dcache_set.read(),
-                            CACHE_SLOT_STATE_EMPTY);
-
-        if ( (r_dcache_miss_set.read() == r_cleanup_dcache_set.read()) and
-             (r_dcache_miss_way.read() == r_cleanup_dcache_way.read()) )
-              r_dcache_miss_clack = false;
-
-        r_dcache_fsm = r_dcache_fsm_cc_save.read() ;
-        r_cleanup_dcache_req = false;
-#if DEBUG_DCACHE
-if ( m_debug_dcache_fsm )
-{
-    std::cout << "  <PROC " << name()
-              << " DCACHE_CC_CLACK> Switch slot to EMPTY state"
-              << " set = " << r_cleanup_dcache_set.read()
-              << " / way = " << r_cleanup_dcache_way.read() << std::endl;
-}
-#endif
-
         break;
     }
@@ -4640,5 +4365,5 @@
     case DCACHE_CC_CHECK:   // This state is the entry point for the sub-FSM
                             // handling coherence requests for DCACHE.
-                            // If there is a matching pending miss on the modified cache 
+                            // If there is a matching pending miss on the modified cache
                             // line this is signaled in the r_dcache_miss inval flip-flop.
                             // If the updated (or invalidated) cache line has copies in TLBs
@@ -4646,36 +4371,92 @@
                             // The return state is defined in r_dcache_fsm_cc_save
     {
-        paddr_t  paddr = r_tgt_paddr.read();
+        paddr_t  paddr = r_cc_receive_dcache_nline.read() * m_dcache_words * 4;
         paddr_t  mask = ~((m_dcache_words<<2)-1);
-
-
-        if( ((r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) or
-             (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT)) and
-            ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching 
-        {
-            // signaling matching
-            r_dcache_miss_inval = true;			
-
-            // coherence request completed, CC_ACK required if update
-            r_tgt_dcache_req      = false;
-            r_dcache_tgt_need_rsp = (r_tgt_cc_type.read() == CC_TYPE_UPDT_DATA);
-            r_dcache_fsm          = r_dcache_fsm_cc_save.read();
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
+              << " DCACHE_CC_CHECK> paddr = " << paddr
+              << " r_dcache_vci_paddr = " << r_dcache_vci_paddr.read()
+              << " mask = " << mask 
+              << " (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) = " << (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT)
+              << " (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT) = " << (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT)
+              << " ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) = " << ((r_dcache_vci_paddr.read() & mask) == (paddr & mask))
+              <<std::endl;
+}
+#endif
+
+        if (r_cc_receive_dcache_type.read() == CC_TYPE_CLACK)
+                            // We switch the directory slot to EMPTY state
+                            // and reset r_icache_miss_clack if the cleanup ack
+                            // is matching a pending miss.
+        {
+
+            if ( m_dreq.valid ) m_cost_data_miss_frz++;
+
+#ifdef INSTRUMENTATION
+m_cpt_dcache_dir_write++;
+#endif
+            r_dcache.write_dir( 0,
+                                r_cc_receive_dcache_way.read(),
+                                r_cc_receive_dcache_set.read(),
+                                CACHE_SLOT_STATE_EMPTY);
+
+            if ( (r_dcache_miss_set.read() == r_cc_receive_dcache_set.read()) and
+                 (r_dcache_miss_way.read() == r_cc_receive_dcache_way.read()) )
+                  r_dcache_miss_clack = false;
+
+            r_dcache_fsm = r_dcache_fsm_cc_save.read() ;
+            r_cc_receive_dcache_req = false;
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC " << name()
+              << " DCACHE_CC_CHECK> CC_TYPE_CLACK Switch slot to EMPTY state"
+              << " set = " << r_cc_receive_dcache_set.read()
+              << " / way = " << r_cc_receive_dcache_way.read() << std::endl;
+}
+#endif
+        }
+        else if( ((r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) or
+                  (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT)) and
+                  ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching
+        {
+            // signaling matching
+            r_dcache_miss_inval = true;
+
+            // in case of update, go to CC_UPDT
+            // JUST TO POP THE FIFO
+            if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)
+            {
+                r_dcache_fsm        = DCACHE_CC_UPDT;
+                r_dcache_cc_word    = r_cc_receive_word_idx.read();
+                // just pop the fifo , don't write in icache
+                r_dcache_cc_need_write = false;
+            }
+            // the request is dealt with
+            else
+            {
+                r_cc_receive_dcache_req = false;
+                r_dcache_fsm          = r_dcache_fsm_cc_save.read();
+            }
+
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC " << name()
               << " DCACHE_CC_CHECK> Coherence request matching a pending miss:"
               << " PADDR = " << std::hex << paddr << std::endl;
 }
 #endif
-  
-        }
-        else                                                    // no match 
+
+        }
+        else                                                    // no match
 	    {
             int        state;
             size_t 	   way;
             size_t 	   set;
-            size_t	   word;  
+            size_t	   word;
 
 #ifdef INSTRUMENTATION
@@ -4684,5 +4465,5 @@
             r_dcache.read_dir( paddr,
                                &state,
-                               &way, 
+                               &way,
                                &set,
                                &word );	// unused
@@ -4691,16 +4472,18 @@
             r_dcache_cc_set = set;
 
-            if ( state == CACHE_SLOT_STATE_VALID)            // hit  
-            {
-                if (r_tgt_cc_type.read() == CC_TYPE_UPDT_DATA)  // hit update
+            if ( state == CACHE_SLOT_STATE_VALID)            // hit
+            {
+                // need to update the cache state
+                r_dcache_cc_need_write = true;
+                if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)  // hit update
                 {
                     r_dcache_fsm          = DCACHE_CC_UPDT;
-                    r_dcache_cc_word      = r_tgt_word_min.read();
+                    r_dcache_cc_word      = r_cc_receive_word_idx.read();
                 }
-                else if (r_tgt_cc_type == CC_TYPE_INVAL_DATA)   // hit inval
+                else if (r_cc_receive_dcache_type.read() == CC_TYPE_INVAL)   // hit inval
                 {
                     r_dcache_fsm          = DCACHE_CC_INVAL;
                 }
-                else if ( r_tgt_cc_type == CC_TYPE_BROADCAST)  // hit broadcast
+                else if ( r_cc_receive_dcache_type.read() == CC_TYPE_BRDCAST)  // hit broadcast
                 {
                     r_dcache_fsm          = DCACHE_CC_BROADCAST;
@@ -4709,8 +4492,17 @@
             else                                      // miss
             {
-                // coherence request completed, CC_ACK required if update only 
-                r_tgt_dcache_req      = false;
-                r_dcache_tgt_need_rsp = (r_tgt_cc_type.read() == CC_TYPE_UPDT_DATA);
-                r_dcache_fsm          = r_dcache_fsm_cc_save.read();
+                // multicast acknowledgement required in case of update
+                if(r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)
+                {
+                    r_dcache_fsm          = DCACHE_CC_UPDT;
+                    r_dcache_cc_word      = r_cc_receive_word_idx.read();
+                    // just pop the fifo , don't write in icache
+                    r_dcache_cc_need_write = false;
+                }
+                else // No response needed
+                {
+                    r_cc_receive_dcache_req = false;
+                    r_dcache_fsm          = r_dcache_fsm_cc_save.read();
+                }
             }
 
@@ -4718,8 +4510,8 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_CC_CHECK> Coherence request received:"
-              << " PADDR = " << std::hex << paddr 
-              << " / TYPE = " << std::dec << r_tgt_cc_type.read()
+              << " PADDR = " << std::hex << paddr
+              << " / TYPE = " << std::dec << r_cc_receive_dcache_type.read()
               << " / HIT = " << (state == CACHE_SLOT_STATE_VALID) << std::endl;
 }
@@ -4729,5 +4521,5 @@
     }
     /////////////////////
-    case DCACHE_CC_INVAL:   	// hit inval: switch slot to EMPTY state, 
+    case DCACHE_CC_INVAL:   	// hit inval: switch slot to EMPTY state,
                                 // after possible invalidation of copies in TLBs
     {
@@ -4735,53 +4527,68 @@
         size_t	 set    = r_dcache_cc_set.read();
 
-        if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 			// selective TLB inval
-        {
-            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
-            r_dcache_tlb_inval_line  = r_tgt_paddr.read() / (m_dcache_words<<2);
-            r_dcache_tlb_inval_set   = 0;
-            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
-            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
-        }
-        else 
-        {
-            if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// TLB flush
-            {
-                r_itlb.reset();
-                r_dtlb.reset();
-                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+        if (r_dcache_cc_need_write.read())
+        {
+            if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 			// selective TLB inval
+            {
+                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+                r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
+                r_dcache_tlb_inval_set   = 0;
+                r_dcache_fsm_scan_save   = r_dcache_fsm.read();
+                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+                break;
+            }
+            else
+            {
+                if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// TLB flush
+                {
+                    r_itlb.reset();
+                    r_dtlb.reset();
+                    r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_CC_INVAL> Flush DTLB & ITLB" << std::endl;
 }
 #endif
-            }
- 
-            r_dcache.write_dir( 0,
-                                way, 
-                                set,
-                                CACHE_SLOT_STATE_EMPTY );
-        
-            // coherence request completed, CC_ACK required if hit inval
-            r_tgt_dcache_req      = false;
-            r_dcache_tgt_need_rsp = true;
-            r_dcache_fsm          = r_dcache_fsm_cc_save.read();
+                }
+
+                r_dcache.write_dir( 0,
+                                    way,
+                                    set,
+                                    CACHE_SLOT_STATE_EMPTY );
+
+                r_dcache_cc_need_write = false;
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_CC_INVAL> Switch slot to EMPTY state:" << std::dec
-	          << " / WAY = " << way
-	          << " / SET = " << set << std::endl;
-}
-#endif
-        }
+              << " / WAY = " << way
+              << " / SET = " << set << std::endl;
+}
+#endif
+            }
+        }
+        // multicast acknowledgement
+        // send a request to cc_send_fsm
+        if(not r_dcache_cc_send_req.read()) // cc_send is available
+        {
+            // coherence request completed
+            r_cc_receive_dcache_req = false;
+            // request multicast acknowledgement
+            r_dcache_cc_send_req = true;
+            r_dcache_cc_send_updt_tab_idx = r_cc_receive_dcache_updt_tab_idx.read();
+            r_dcache_cc_send_type = CC_TYPE_MULTI_ACK;
+
+            r_dcache_fsm          = r_dcache_fsm_cc_save.read();
+        }
+        //else wait for previous cc_send request to be sent
         break;
     }
     ///////////////////
-    case DCACHE_CC_UPDT:    	// hit update: write one word per cycle,  
+    case DCACHE_CC_UPDT:    	// hit update: write one word per cycle,
                                 // after possible invalidation of copies in TLBs
     {
@@ -4790,58 +4597,85 @@
         size_t	 set        = r_dcache_cc_set.read();
 
-        if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 			// selective TLB inval
-        {
-            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
-            r_dcache_tlb_inval_line  = r_tgt_paddr.read() / (m_dcache_words<<2);
-            r_dcache_tlb_inval_set   = 0;
-            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
-            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
-        }
-        else 
-        {
-            if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// TLB flush
-            {
-                r_itlb.reset();
-                r_dtlb.reset();
-                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+        if (r_cc_receive_updt_fifo_be.rok())
+        {
+            if (r_dcache_cc_need_write.read())
+            {
+                if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 			// selective TLB inval
+                {
+                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+                    r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
+                    r_dcache_tlb_inval_set   = 0;
+                    r_dcache_fsm_scan_save   = r_dcache_fsm.read();
+                    r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+                    break;
+                }
+
+                if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// TLB flush
+                {
+                    r_itlb.reset();
+                    r_dtlb.reset();
+                    r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_CC_UPDT> Flush DTLB & ITLB" << std::endl;
 }
 #endif
-            } 
+                }
 
 #ifdef INSTRUMENTATION
 m_cpt_dcache_data_write++;
 #endif
-            r_dcache.write( way,
-                            set,
-                            word,
-                            r_tgt_buf[word],
-                            r_tgt_be[word] );
-
-            r_dcache_cc_word = word + 1;
-
-            if ( word == r_tgt_word_max.read() )	// last word
-            {
-                r_tgt_dcache_req      = false;
-                r_dcache_tgt_need_rsp = true;
-                r_dcache_fsm          = r_dcache_fsm_cc_save.read();
-            }
+                r_dcache.write( way,
+                                set,
+                                word,
+                                r_cc_receive_updt_fifo_data.read(),
+                                r_cc_receive_updt_fifo_be.read() );
+
+                r_dcache_cc_word = word + 1;
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_CC_UPDT> Write one word" << std::dec
-	          << " / WAY = " << way
-	          << " / SET = " << set 
+              << " / WAY = " << way
+              << " / SET = " << set
               << " / WORD = " << word
-              << " / VALUE = " << std::hex << r_tgt_buf[word] << std::endl;
-}
-#endif
+              << " / VALUE = " << std::hex << r_cc_receive_updt_fifo_data.read() << std::endl;
+}
+#endif
+            }
+
+            if ( r_cc_receive_updt_fifo_eop.read() )	// last word
+            {
+                // no need to write in the cache anymore
+                r_dcache_cc_need_write = false;
+
+                // wait to send a request to cc_send_fsm
+                if(not r_icache_cc_send_req.read())
+                // cc_send is available
+                {
+                    //consume last fifo flit if eop and request to cc_send possible
+                    cc_receive_updt_fifo_get  = true;
+
+                    // coherence request completed
+                    r_cc_receive_dcache_req = false;
+
+                    // request multicast acknowledgement
+                    r_dcache_cc_send_req = true;
+                    r_dcache_cc_send_updt_tab_idx = r_cc_receive_dcache_updt_tab_idx.read();
+                    r_dcache_cc_send_type = CC_TYPE_MULTI_ACK;
+
+                    r_dcache_fsm          = r_dcache_fsm_cc_save.read();
+                }
+            }
+            else
+            {
+                //consume fifo if not eop
+                cc_receive_updt_fifo_get  = true;
+            }
         }
         break;
@@ -4854,38 +4688,43 @@
         size_t	 way   = r_dcache_cc_way.read();
         size_t	 set   = r_dcache_cc_set.read();
-        paddr_t  nline = r_tgt_paddr.read() / (m_dcache_words<<2);
-
-        if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 			// selective TLB inval
-        {
-            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
-            r_dcache_tlb_inval_line  = nline;
-            r_dcache_tlb_inval_set   = 0;
-            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
-            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
-        }
-        else 						
-        {
-            if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// TLB flush
-            {
-                r_itlb.reset();
-                r_dtlb.reset();
-                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+        paddr_t  nline = r_cc_receive_dcache_nline.read();
+
+        if (r_dcache_cc_need_write.read())
+        {
+            if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 			// selective TLB inval
+            {
+                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+                r_dcache_tlb_inval_line  = nline;
+                r_dcache_tlb_inval_set   = 0;
+                r_dcache_fsm_scan_save   = r_dcache_fsm.read();
+                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+                break;
+            }
+            else
+            {
+                if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// TLB flush
+                {
+                    r_itlb.reset();
+                    r_dtlb.reset();
+                    r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() 
+    std::cout << "  <PROC " << name()
               << " DCACHE_CC_BROADCAST> Flush DTLB & ITLB" << std::endl;
 }
 #endif
-            } 
+                }
 
 #ifdef INSTRUMENTATION
 m_cpt_dcache_dir_write++;
 #endif
-            r_dcache.write_dir( 0,
-                                way,
-                                set,
-                                CACHE_SLOT_STATE_ZOMBI );
+                r_dcache.write_dir( 0,
+                                    way,
+                                    set,
+                                    CACHE_SLOT_STATE_ZOMBI );
+
+                r_dcache_cc_need_write = false;
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
@@ -4897,13 +4736,21 @@
 }
 #endif
-
-            // coherence operation completed, no CC_ACK for hit broadcast
-            r_dcache_tgt_need_rsp = false;
-            r_tgt_dcache_req      = false;
-            r_dcache_cleanup_req  = true;
-            r_dcache_cleanup_line = nline;
-            r_dcache_cleanup_way  = way;
+            }
+        }
+        // cleanup
+        // send a request to cc_send_fsm
+        if(not r_dcache_cc_send_req.read()) // cc_send is available
+        {
+            // coherence request completed
+            r_cc_receive_dcache_req = false;
+            // request cleanup
+            r_dcache_cc_send_req = true;
+            r_dcache_cc_send_nline = r_cc_receive_dcache_nline.read();
+            r_dcache_cc_send_way   = r_dcache_cc_way.read();
+            r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
+
             r_dcache_fsm          = r_dcache_fsm_cc_save.read();
         }
+        //else wait for previous cc_send request to be sent
         break;
     }
@@ -4914,8 +4761,8 @@
                                         // We enter this state when a DCACHE line is modified,
                                         // and there is a copy in itlb or dtlb.
-                                        // It can be caused by: 
-                                        // - a coherence inval or updt transaction, 
+                                        // It can be caused by:
+                                        // - a coherence inval or updt transaction,
                                         // - a line inval caused by a cache miss
-                                        // - a processor XTN inval request, 
+                                        // - a processor XTN inval request,
                                         // - a WRITE hit,
                                         // - a Dirty bit update
@@ -4925,6 +4772,6 @@
                                         // - r_dcache_fsm_scan_save
     {
-        paddr_t	line = r_dcache_tlb_inval_line.read(); 
-        size_t  set  = r_dcache_tlb_inval_set.read();	
+        paddr_t	line = r_dcache_tlb_inval_line.read();
+        size_t  set  = r_dcache_tlb_inval_set.read();
         size_t  way;
         bool    ok;
@@ -4937,13 +4784,13 @@
 if ( m_debug_dcache_fsm and ok )
 {
-    std::cout << "  <PROC " << name() 
-              << ".DCACHE_INVAL_TLB_SCAN> Invalidate ITLB entry:" << std::hex 
+    std::cout << "  <PROC " << name()
+              << ".DCACHE_INVAL_TLB_SCAN> Invalidate ITLB entry:" << std::hex
               << " line = " << line << std::dec
-              << " / set = " << set 
+              << " / set = " << set
               << " / way = " << way << std::endl;
 }
 #endif
         }
-         
+
         for ( way = 0 ; way < m_dtlb_ways ; way++ )
         {
@@ -4953,8 +4800,8 @@
 if ( m_debug_dcache_fsm and ok )
 {
-    std::cout << "  <PROC " << name() 
-              << ".DCACHE_INVAL_TLB_SCAN> Invalidate DTLB entry:" << std::hex 
+    std::cout << "  <PROC " << name()
+              << ".DCACHE_INVAL_TLB_SCAN> Invalidate DTLB entry:" << std::hex
               << " line = " << line << std::dec
-              << " / set = " << set 
+              << " / set = " << set
               << " / way = " << way << std::endl;
 }
@@ -4969,5 +4816,5 @@
         r_dcache_tlb_inval_set = r_dcache_tlb_inval_set.read() + 1;
         break;
-    }   
+    }
     } // end switch r_dcache_fsm
 
@@ -4982,5 +4829,5 @@
     // The simulation exit if the number of consecutive frozen cycles
     // is larger than the m_max_frozen_cycles (constructor parameter)
-    if ( (m_ireq.valid and not m_irsp.valid) or (m_dreq.valid and not m_drsp.valid) )       
+    if ( (m_ireq.valid and not m_irsp.valid) or (m_dreq.valid and not m_drsp.valid) )
     {
         m_cpt_frz_cycles++; 		// used for instrumentation
@@ -4990,5 +4837,5 @@
             std::cout << std::dec << "ERROR in CC_VCACHE_WRAPPER " << name() << std::endl
                       << " stop at cycle " << m_cpt_total_cycles << std::endl
-                      << " frozen since cycle " << m_cpt_total_cycles - m_max_frozen_cycles 
+                      << " frozen since cycle " << m_cpt_total_cycles - m_max_frozen_cycles
                       << std::endl;
                       r_iss.dump();
@@ -5025,20 +4872,20 @@
     //
     // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
-    // There are 8 request types, with the following priorities : 
+    // There are 8 request types, with the following priorities :
     // 1 - Data Read Miss         : r_dcache_vci_miss_req and miss in the write buffer
-    // 2 - Data Read Uncachable   : r_dcache_vci_unc_req  
+    // 2 - Data Read Uncachable   : r_dcache_vci_unc_req
     // 3 - Instruction Miss       : r_icache_miss_req and miss in the write buffer
-    // 4 - Instruction Uncachable : r_icache_unc_req 
-    // 5 - Data Write             : r_wbuf.rok()      
+    // 4 - Instruction Uncachable : r_icache_unc_req
+    // 5 - Data Write             : r_wbuf.rok()
     // 6 - Data Linked Load       : r_dcache_vci_ll_req
     // 7 - Data Store Conditionnal: r_dcache_vci_sc_req
     // 8 - Compare And Swap       : r_dcache_vci_cas_req
     //
-    // As we want to support several simultaneous VCI transactions, the VCI_CMD_FSM 
+    // As we want to support several simultaneous VCI transactions, the VCI_CMD_FSM
     // and the VCI_RSP_FSM are fully desynchronized.
     //
     // VCI formats:
-    // According to the VCI advanced specification, all read requests packets 
-    // (data Uncached, Miss data, instruction Uncached, Miss instruction) 
+    // According to the VCI advanced specification, all read requests packets
+    // (data Uncached, Miss data, instruction Uncached, Miss instruction)
     // are one word packets.
     // For write burst packets, all words are in the same cache line,
@@ -5048,5 +4895,5 @@
     ////////////////////////////////////////////////////////////////////////////////////
 
-    switch ( r_vci_cmd_fsm.read() ) 
+    switch ( r_vci_cmd_fsm.read() )
     {
         //////////////
@@ -5054,8 +4901,8 @@
         {
             // DDACHE read requests (r_dcache_vci_miss_req or r_dcache_vci_ll_req), and
-            // ICACHE read requests (r_icache_miss_req) require both a write_buffer access 
-            // to check a possible pending write on the same cache line. 
-            // As there is only one possible access per cycle to write buffer, we implement 
-            // a round-robin priority between DCACHE and ICACHE for this access, 
+            // ICACHE read requests (r_icache_miss_req) require both a write_buffer access
+            // to check a possible pending write on the same cache line.
+            // As there is only one possible access per cycle to write buffer, we implement
+            // a round-robin priority between DCACHE and ICACHE for this access,
             // using the r_vci_cmd_imiss_prio flip-flop.
 
@@ -5146,5 +4993,5 @@
         case CMD_DATA_WRITE:
         {
-            if ( p_vci_ini_d.cmdack.read() )
+            if ( p_vci.cmdack.read() )
             {
                 r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
@@ -5162,5 +5009,5 @@
         {
             // The CAS and SC VCI commands contain two flits
-            if ( p_vci_ini_d.cmdack.read() )
+            if ( p_vci.cmdack.read() )
             {
                r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
@@ -5177,5 +5024,5 @@
         {
             // all read VCI commands contain one single flit
-            if ( p_vci_ini_d.cmdack.read() )  r_vci_cmd_fsm = CMD_IDLE;
+            if ( p_vci.cmdack.read() )  r_vci_cmd_fsm = CMD_IDLE;
             break;
         }
@@ -5194,58 +5041,58 @@
     //
     // As the VCI_RSP and VCI_CMD are fully desynchronized to support several
-    // simultaneous VCI transactions, this FSM uses the VCI RPKTID field 
+    // simultaneous VCI transactions, this FSM uses the VCI RPKTID field
     // to identify the transactions.
     //
     // VCI vormat:
     // This component checks the response packet length and accepts only
-    // single word packets for write response packets. 
+    // single word packets for write response packets.
     //
     // Error handling:
-    // This FSM analyzes the VCI error code and signals directly the Write Bus Error. 
-    // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error 
-    // flip_flop and the error is signaled by the DCACHE FSM.  
-    // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 
-    // flip_flop and the error is signaled by the ICACHE FSM.  
+    // This FSM analyzes the VCI error code and signals directly the Write Bus Error.
+    // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error
+    // flip_flop and the error is signaled by the DCACHE FSM.
+    // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
+    // flip_flop and the error is signaled by the ICACHE FSM.
     // In case of Cleanup Error, the simulation stops with an error message...
     //////////////////////////////////////////////////////////////////////////
 
-    switch ( r_vci_rsp_fsm.read() ) 
+    switch ( r_vci_rsp_fsm.read() )
     {
     //////////////
     case RSP_IDLE:
     {
-        if ( p_vci_ini_d.rspval.read() )
+        if ( p_vci.rspval.read() )
         {
             r_vci_rsp_cpt = 0;
 
-            if      ( (p_vci_ini_d.rpktid.read() & 0x7) ==  TYPE_READ_DATA_UNC  ) 
+            if      ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_DATA_UNC  )
             {
                 r_vci_rsp_fsm = RSP_DATA_UNC;
             }
-            else if ( (p_vci_ini_d.rpktid.read() & 0x7) ==  TYPE_READ_DATA_MISS ) 
+            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_DATA_MISS )
             {
                 r_vci_rsp_fsm = RSP_DATA_MISS;
             }
-            else if ( (p_vci_ini_d.rpktid.read() & 0x7) ==  TYPE_READ_INS_UNC   ) 
+            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_INS_UNC   )
             {
                 r_vci_rsp_fsm = RSP_INS_UNC;
             }
-            else if ( (p_vci_ini_d.rpktid.read() & 0x7) ==  TYPE_READ_INS_MISS  ) 
+            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_INS_MISS  )
             {
                 r_vci_rsp_fsm = RSP_INS_MISS;
             }
-            else if ( (p_vci_ini_d.rpktid.read() & 0x7) ==  TYPE_WRITE          )
-            {
-                r_vci_rsp_fsm = RSP_DATA_WRITE; 
-            }
-            else if ( (p_vci_ini_d.rpktid.read() & 0x7) ==  TYPE_CAS            ) 
+            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_WRITE          )
+            {
+                r_vci_rsp_fsm = RSP_DATA_WRITE;
+            }
+            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_CAS            )
             {
                 r_vci_rsp_fsm = RSP_DATA_UNC;
             }
-            else if ( (p_vci_ini_d.rpktid.read() & 0x7) ==  TYPE_LL             ) 
+            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_LL             )
             {
                 r_vci_rsp_fsm = RSP_DATA_LL;
             }
-            else if ( (p_vci_ini_d.rpktid.read() & 0x7) == TYPE_SC             ) 
+            else if ( (p_vci.rpktid.read() & 0x7) == TYPE_SC             )
             {
                 r_vci_rsp_fsm = RSP_DATA_UNC;
@@ -5261,10 +5108,10 @@
         case RSP_INS_MISS:
         {
-            if ( p_vci_ini_d.rspval.read() )
-            {
-                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
+            if ( p_vci.rspval.read() )
+            {
+                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
                 {
                     r_vci_rsp_ins_error = true;
-                    if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
+                    if ( p_vci.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
                 }
                 else                                        // no error reported
@@ -5277,6 +5124,6 @@
                         r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
                         vci_rsp_fifo_icache_put       = true,
-                        vci_rsp_fifo_icache_data      = p_vci_ini_d.rdata.read();
-                        if ( p_vci_ini_d.reop.read() )
+                        vci_rsp_fifo_icache_data      = p_vci.rdata.read();
+                        if ( p_vci.reop.read() )
                         {
                             assert( (r_vci_rsp_cpt.read() == m_icache_words - 1) and
@@ -5293,10 +5140,10 @@
         case RSP_INS_UNC:
         {
-            if (p_vci_ini_d.rspval.read() )
-            {
-                assert( p_vci_ini_d.reop.read() and
+            if (p_vci.rspval.read() )
+            {
+                assert( p_vci.reop.read() and
                 "illegal VCI response packet for uncachable instruction");
 
-                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
+                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
                 {
                     r_vci_rsp_ins_error = true;
@@ -5308,5 +5155,5 @@
                     {
                         vci_rsp_fifo_icache_put       = true;
-                        vci_rsp_fifo_icache_data      = p_vci_ini_d.rdata.read();
+                        vci_rsp_fifo_icache_data      = p_vci.rdata.read();
                         r_vci_rsp_fsm = RSP_IDLE;
                     }
@@ -5318,10 +5165,10 @@
         case RSP_DATA_MISS:
         {
-            if ( p_vci_ini_d.rspval.read() )
-            {
-                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
+            if ( p_vci.rspval.read() )
+            {
+                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
                 {
                     r_vci_rsp_data_error = true;
-                    if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
+                    if ( p_vci.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
                 }
                 else                                        // no error reported
@@ -5334,6 +5181,6 @@
                         r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
                         vci_rsp_fifo_dcache_put       = true,
-                        vci_rsp_fifo_dcache_data      = p_vci_ini_d.rdata.read();
-                        if ( p_vci_ini_d.reop.read() )
+                        vci_rsp_fifo_dcache_data      = p_vci.rdata.read();
+                        if ( p_vci.reop.read() )
                         {
                             assert( (r_vci_rsp_cpt.read() == m_dcache_words - 1) and
@@ -5350,10 +5197,10 @@
         case RSP_DATA_UNC:
         {
-            if (p_vci_ini_d.rspval.read() )
-            {
-                assert( p_vci_ini_d.reop.read() and
+            if (p_vci.rspval.read() )
+            {
+                assert( p_vci.reop.read() and
                 "illegal VCI response packet for uncachable read data");
 
-                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
+                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
                 {
                     r_vci_rsp_data_error = true;
@@ -5365,5 +5212,5 @@
                     {
                         vci_rsp_fifo_dcache_put       = true;
-                        vci_rsp_fifo_dcache_data      = p_vci_ini_d.rdata.read();
+                        vci_rsp_fifo_dcache_data      = p_vci.rdata.read();
                         r_vci_rsp_fsm = RSP_IDLE;
                     }
@@ -5375,7 +5222,7 @@
         case RSP_DATA_LL:
         {
-            if ( p_vci_ini_d.rspval.read() )
-            {
-                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
+            if ( p_vci.rspval.read() )
+            {
+                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
                 {
                     r_vci_rsp_data_error = true;
@@ -5386,8 +5233,8 @@
                     if(r_vci_rsp_fifo_dcache.wok())
                     {
-                        assert(!p_vci_ini_d.reop.read() &&
+                        assert(!p_vci.reop.read() &&
                             "illegal VCI response packet for LL");
                         vci_rsp_fifo_dcache_put  = true;
-                        vci_rsp_fifo_dcache_data = p_vci_ini_d.rdata.read();
+                        vci_rsp_fifo_dcache_data = p_vci.rdata.read();
                         r_vci_rsp_cpt            = r_vci_rsp_cpt.read() + 1;
                     }
@@ -5398,8 +5245,8 @@
                     if(r_vci_rsp_fifo_dcache.wok())
                     {
-                        assert(p_vci_ini_d.reop.read() &&
+                        assert(p_vci.reop.read() &&
                             "illegal VCI response packet for LL");
                         vci_rsp_fifo_dcache_put  = true;
-                        vci_rsp_fifo_dcache_data = p_vci_ini_d.rdata.read();
+                        vci_rsp_fifo_dcache_data = p_vci.rdata.read();
                         r_vci_rsp_fsm            = RSP_IDLE;
                     }
@@ -5412,14 +5259,14 @@
         case RSP_DATA_WRITE:
         {
-            if (p_vci_ini_d.rspval.read())
-            {
-                assert( p_vci_ini_d.reop.read() and
+            if (p_vci.rspval.read())
+            {
+                assert( p_vci.reop.read() and
                 "a VCI response packet must contain one flit for a write transaction");
 
                 r_vci_rsp_fsm = RSP_IDLE;
-                uint32_t   wbuf_index = p_vci_ini_d.rtrdid.read();
+                uint32_t   wbuf_index = p_vci.rtrdid.read();
                 bool       cacheable  = r_wbuf.completed(wbuf_index);
                 if ( not cacheable ) r_dcache_pending_unc_write = false;
-                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 ) r_iss.setWriteBerr();
+                if ( (p_vci.rerror.read()&0x1) != 0 ) r_iss.setWriteBerr();
             }
             break;
@@ -5428,148 +5275,392 @@
 
     /////////////////////////////////////////////////////////////////////////////////////
-    // The CLEANUP_CMD FSM is in charge to send the cleanup commands on the coherence 
-    // network. It has two clients (DCACHE FSM and ICACHE FSM) that are served
-    // with a round-robin priority. All cleanup commands are registered in the 
-    // r_cleanup_buffer, because we must avoid to send a Read Miss command 
-    // for line (X) if there is a pending cleanup for line (X): the r_cleanup_buffer 
-    // is tested by the ICACHE FSM and DCACHE FSM before posting a miss request.
-    // The CLEANUP FSM resets the r_*cache_cleanup request flip-flops as soon as 
-    // the request has been sent and registered in the buffer.
-    // The buffer itself is cleared when the cleanup response is received.
-    // We use an assocative registration buffer (CAM) in order to support several
-    // simultaneous cleanup transactions (up to 4 simultaneous clenups).
-    // The VCI TRDID field is used to distinguish data/instruction cleanups and to
-    // transmit the way :
-    // - if data cleanup        : TRDID = 2*way + 0
-    // - if instruction cleanup : TRDID = 2*way + 1
+    // The CC_SEND FSM is in charge of sending cleanups and the multicast
+    // acknowledgements on the coherence network. It has two clients (DCACHE FSM
+    // and ICACHE FSM) that are served with a round-robin priority.
+    // The CC_SEND FSM resets the r_*cache_cc_send_req request flip-flops as
+    // soon as the request has been sent.
     /////////////////////////////////////////////////////////////////////////////////////
-
-    switch ( r_cleanup_cmd_fsm.read() ) 
+    switch ( r_cc_send_fsm.read() )
     {
         ///////////////////////////
-        case CLEANUP_CMD_DATA_IDLE:     // dcache has highest priority
-        {
-            if ( r_dcache_cleanup_req.read() )      // dcache request
-            {
-                r_cleanup_cmd_fsm   = CLEANUP_CMD_DATA_GO; 
-                r_cleanup_cmd_trdid = r_dcache_cleanup_way.read()<<1;
-            }
-            else if ( r_icache_cleanup_req.read() ) // icache request
-            {
-                r_cleanup_cmd_fsm   = CLEANUP_CMD_INS_GO; 
-                r_cleanup_cmd_trdid = (r_icache_cleanup_way.read()<<1) + 1;
+        case CC_SEND_IDLE:
+        {
+            ///////////////////////////////////////////////////////
+            // handling round robin between icache and dcache :  //
+            // we first check for the last client and listen for //
+            // a request of the other, then update the client    //
+            ///////////////////////////////////////////////////////
+            // r_cc_send_last_client : 0 dcache / 1 icache
+            bool update_last_client = r_cc_send_last_client.read();
+            if ( r_cc_send_last_client.read() == 0 ) // last client was dcache
+            {
+                if (r_icache_cc_send_req.read()) // request from icache
+                    update_last_client = 1; // update last client to icache
+            }
+            else // last client was icache
+            {
+                if (r_dcache_cc_send_req.read()) // request from dcache
+                    update_last_client = 0; // update last client to dcache
+            }
+            r_cc_send_last_client = update_last_client;
+
+            // if there is an actual request
+            if (r_dcache_cc_send_req.read() or r_icache_cc_send_req.read())
+            {
+                // test if the new client is dcache and has a cleanup request
+                if ( (update_last_client == 0) and (r_dcache_cc_send_type.read() == CC_TYPE_CLEANUP))
+                    r_cc_send_fsm = CC_SEND_CLEANUP_1;
+                // test if the new client is dcache and has a multi acknowledgement request
+                else if ( (update_last_client == 0) and (r_dcache_cc_send_type.read() == CC_TYPE_MULTI_ACK))
+                    r_cc_send_fsm = CC_SEND_MULTI_ACK;
+                // test if the new client is icache and has a cleanup request
+                else if ( (update_last_client == 1) and (r_icache_cc_send_type.read() == CC_TYPE_CLEANUP))
+                    r_cc_send_fsm = CC_SEND_CLEANUP_1;
+                // test if the new client is icache and has a multi acknowledgement request
+                else if ( (update_last_client == 1) and (r_icache_cc_send_type.read() == CC_TYPE_MULTI_ACK))
+                    r_cc_send_fsm = CC_SEND_MULTI_ACK;
             }
             break;
         }
+        ///////////////////////////
+        case CC_SEND_CLEANUP_1:
+        {
+/**/
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+        std::cout << "  <PROC " << name()
+              << " r_dcache_cc_send_nline = " << r_dcache_cc_send_nline.read() << std::endl;
+}
+#endif
+            // wait for the first flit to be consumed
+            if (p_dspin_out.read.read())
+                r_cc_send_fsm = CC_SEND_CLEANUP_2;
+
+            break;
+        }
+        ///////////////////////////
+        case CC_SEND_CLEANUP_2:
+/**/
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+        std::cout << "  <PROC " << name()
+              << " r_dcache_cc_send_nline = " << r_dcache_cc_send_nline.read() << std::endl;
+}
+#endif
+        {
+            assert( p_dspin_out.read.read() and
+                    "The interconnect should accept the second cleanup flit instantly" );
+
+            // wait for the second flit to be consumed
+            if (p_dspin_out.read.read())
+            {
+                if (r_cc_send_last_client.read() == 0) // dcache active request
+                    r_dcache_cc_send_req = false; // reset dcache request
+                else // icache active request
+                    r_icache_cc_send_req = false; // reset icache request
+
+                // go back to idle state
+                r_cc_send_fsm = CC_SEND_IDLE;
+            }
+            break;
+        }
+        ///////////////////////////
+        case CC_SEND_MULTI_ACK:
+        {
+            // wait for the flit to be consumed
+            if(p_dspin_out.read.read())
+            {
+                if(r_cc_send_last_client.read() == 0) // dcache active request
+                    r_dcache_cc_send_req = false; // reset dcache request
+                else // icache active request
+                    r_icache_cc_send_req = false; // reset icache request
+                // go back to idle state
+                r_cc_send_fsm = CC_SEND_IDLE;
+            }
+            break;
+        }
+    } // end switch CC_SEND FSM
+
+    ///////////////////////////////////////////////////////////////////////////////
+    //   C_RECEIVE  FSM
+    // This FSM receive all coherence packets on a DSPIN40 port.
+    // There is 4 packet types:
+    // - CC_DATA_INVAL : DCACHE invalidate request
+    // - CC_DATA_UPDT  : DCACHE update request (multi-words)
+    // - CC_INST_INVAL : ICACHE invalidate request
+    // - CC_INST_UPDT  : ICACHE update request (multi-words)
+    // - CC_BROADCAST  : Broadcast invalidate request (both DCACHE & ICACHE)
+    // - CC_DATA_CLACK : DCACHE cleanup acknowledge
+    // - CC_INST_CLACK : ICACHE cleanup acknowledge
+    //////////////////////////////////////////////////////////////////////////////
+    switch( r_cc_receive_fsm.read() )
+    {
+        /////////////////////
+        case CC_RECEIVE_IDLE:
+        {
+/**/
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+        std::cout << "  <PROC " << name()
+              << " r_cc_receive_dcache_req = " << r_cc_receive_dcache_req.read() << std::endl;
+        std::cout << "  <PROC " << name()
+              << " r_dcache_miss_inval = " << r_dcache_miss_inval.read() << std::endl;
+}
+#endif
+            // a coherence request has arrived
+            if (p_dspin_in.write.read())
+            {
+                // initialize dspin received data
+                uint64_t receive_data = p_dspin_in.data.read();
+                // initialize coherence packet type
+                uint64_t receive_type = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::FROM_MC_TYPE);
+                // initialize data/ins flip_flop (0 data / 1 ins)
+                r_cc_receive_data_ins = (bool)(receive_type & 0x1);
+                // test for a broadcast
+                if (DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::FROM_MC_BC))
+                {
+                    r_cc_receive_fsm = CC_RECEIVE_BRDCAST_HEADER;
+                }
+                // test for a CLACK
+                else if ((receive_type == DspinDhccpParam::TYPE_CLEANUP_ACK_DATA) or
+                         (receive_type == DspinDhccpParam::TYPE_CLEANUP_ACK_INST))
+                {
+                    r_cc_receive_fsm = CC_RECEIVE_CLACK;
+                }
+                // test for a multi updt
+                else if ((receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_DATA) or
+                         (receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_INST))
+                {
+                    r_cc_receive_fsm = CC_RECEIVE_UPDT_HEADER;
+                }
+                // test for a multi inval
+                else
+                {
+                    r_cc_receive_fsm = CC_RECEIVE_INVAL_HEADER;
+                }
+            }
+            break;
+        }
+        //////////////////////
+        case CC_RECEIVE_CLACK:
+        {
+            // initialize dspin received data
+            uint64_t receive_data = p_dspin_in.data.read();
+
+            // for data CLACK, wait for dcache to take the request
+            if ((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read()))
+            {
+                // request dcache to handle the CLACK
+                r_cc_receive_dcache_req  = true;
+                r_cc_receive_dcache_set  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::CLEANUP_ACK_SET) & ((1ULL<<(uint32_log2(m_dcache_sets)))-1);
+                r_cc_receive_dcache_way  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::CLEANUP_ACK_WAY) & ((1ULL<<(uint32_log2(m_dcache_ways)))-1);
+                r_cc_receive_dcache_type = CC_TYPE_CLACK;
+                // get back to idle state
+                r_cc_receive_fsm = CC_RECEIVE_IDLE;
+                break;
+            }
+            // for ins CLACK, wait for icache to take the request
+            if ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read()))
+            {
+                // request icache to handle the CLACK
+                r_cc_receive_icache_req  = true;
+                r_cc_receive_icache_set  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::CLEANUP_ACK_SET) & ((1ULL<<(uint32_log2(m_icache_sets)))-1);
+                r_cc_receive_icache_way  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::CLEANUP_ACK_WAY) & ((1ULL<<(uint32_log2(m_icache_ways)))-1);
+                r_cc_receive_icache_type = CC_TYPE_CLACK;
+                // get back to idle state
+                r_cc_receive_fsm = CC_RECEIVE_IDLE;
+                break;
+            }
+            // keep waiting for the correct cache to accept the request
+            break;
+        }
+        ///////////////////////////////
+        case CC_RECEIVE_BRDCAST_HEADER:
+        {
+/**/
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+        std::cout << "  <PROC " << name()
+              << " r_cc_receive_dcache_req = " << r_cc_receive_dcache_req.read() << std::endl;
+        std::cout << "  <PROC " << name()
+              << " r_dcache_miss_inval = " << r_dcache_miss_inval.read() << std::endl;
+}
+#endif
+            // no actual data in the HEADER, just skip to second flit
+            r_cc_receive_fsm = CC_RECEIVE_BRDCAST_NLINE;
+            break;
+        }
+        //////////////////////////////
+        case CC_RECEIVE_BRDCAST_NLINE:
+        {
+/**/
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+        std::cout << "  <PROC " << name()
+              << " r_cc_receive_dcache_req = " << r_cc_receive_dcache_req.read() << std::endl;
+        std::cout << "  <PROC " << name()
+              << " r_dcache_miss_inval = " << r_dcache_miss_inval.read() << std::endl;
+}
+#endif
+            // initialize dspin received data
+            uint64_t receive_data = p_dspin_in.data.read();
+            // wait for both dcache and icache to take the request
+            // TODO maybe we need to wait for both only to leave the state, but
+            // not to actually post a request to an available cache => need a
+            // flip_flop to check that ?
+            if (not (r_cc_receive_icache_req.read()) and not (r_cc_receive_dcache_req.read()))
+            {
+                // request dcache to handle the BROADCAST
+                r_cc_receive_dcache_req  = true;
+                r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::BROADCAST_NLINE);
+                r_cc_receive_dcache_type = CC_TYPE_BRDCAST;
+                // request icache to handle the BROADCAST
+                r_cc_receive_icache_req  = true;
+                r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::BROADCAST_NLINE);
+                r_cc_receive_icache_type = CC_TYPE_BRDCAST;
+                // get back to idle state
+                r_cc_receive_fsm = CC_RECEIVE_IDLE;
+                break;
+            }
+            // keep waiting for the caches to accept the request
+            break;
+        }
+        /////////////////////////////
+        case CC_RECEIVE_INVAL_HEADER:
+        {
+            // sample updt tab index in the HEADER, then skip to second flit
+            uint64_t receive_data = p_dspin_in.data.read();
+            // for data INVAL, wait for dcache to take the request
+            if ((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read()))
+            {
+                r_cc_receive_dcache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_UPDT_INDEX);
+                r_cc_receive_fsm = CC_RECEIVE_INVAL_NLINE;
+                break;
+            }
+            // for ins INVAL, wait for icache to take the request
+            if ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read()))
+            {
+                r_cc_receive_icache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_UPDT_INDEX);
+                r_cc_receive_fsm = CC_RECEIVE_INVAL_NLINE;
+                break;
+            }
+            // keep waiting for the correct cache to accept the request
+            break;
+        }
+        ////////////////////////////
+        case CC_RECEIVE_INVAL_NLINE:
+        {
+            // sample nline in the second flit
+            uint64_t receive_data = p_dspin_in.data.read();
+            // for data INVAL, wait for dcache to take the request
+            if ((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read()))
+            {
+                // request dcache to handle the INVAL
+                r_cc_receive_dcache_req  = true;
+                r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
+                r_cc_receive_dcache_type = CC_TYPE_INVAL;
+                // get back to idle state
+                r_cc_receive_fsm = CC_RECEIVE_IDLE;
+                break;
+            }
+            // for ins INVAL, wait for icache to take the request
+            if ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read()))
+            {
+                // request icache to handle the INVAL
+                r_cc_receive_icache_req  = true;
+                r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
+                r_cc_receive_icache_type = CC_TYPE_INVAL;
+                // get back to idle state
+                r_cc_receive_fsm = CC_RECEIVE_IDLE;
+                break;
+            }
+            // we should never get there
+            assert ( false && "CC_RECEIVE_INVAL_NLINE : incoherent handling of either r_cc_receive_data_ins or r_cc_receive_*cache_req\n");
+        }
+        ////////////////////////////
+        case CC_RECEIVE_UPDT_HEADER:
+        {
+            // sample updt tab index in the HEADER, than skip to second flit
+            uint64_t receive_data = p_dspin_in.data.read();
+            // for data INVAL, wait for dcache to take the request and fifo to
+            // be empty
+            if ((r_cc_receive_data_ins.read() == 0) and not r_cc_receive_dcache_req.read() and r_cc_receive_updt_fifo_be.empty())
+            {
+                r_cc_receive_dcache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
+                r_cc_receive_fsm = CC_RECEIVE_UPDT_NLINE;
+                break;
+            }
+            // for ins INVAL, wait for icache to take the request and fifo to be
+            // empty
+            if ((r_cc_receive_data_ins.read() == 1) and not r_cc_receive_icache_req.read() and r_cc_receive_updt_fifo_be.empty())
+            {
+                r_cc_receive_icache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
+                r_cc_receive_fsm = CC_RECEIVE_UPDT_NLINE;
+                break;
+            }
+            // keep waiting for the correct cache to accept the request
+            break;
+        }
+        ///////////////////////////
+        case CC_RECEIVE_UPDT_NLINE:
+        {
+            // sample nline and word index in the second flit
+            uint64_t receive_data = p_dspin_in.data.read();
+            // for data INVAL, wait for dcache to take the request and fifo to
+            // be empty
+            if ((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read()) and r_cc_receive_updt_fifo_be.empty())
+            {
+                r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_NLINE);
+                r_cc_receive_word_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
+                r_cc_receive_dcache_type = CC_TYPE_UPDT;
+                // get back to idle state
+                r_cc_receive_fsm = CC_RECEIVE_UPDT_DATA;
+                break;
+            }
+            // for ins INVAL, wait for icache to take the request and fifo to be
+            // empty
+            if ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read()) and r_cc_receive_updt_fifo_be.empty())
+            {
+                r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_NLINE);
+                r_cc_receive_word_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
+                r_cc_receive_icache_type = CC_TYPE_UPDT;
+                // get back to idle state
+                r_cc_receive_fsm = CC_RECEIVE_UPDT_DATA;
+                break;
+            }
+            // we should never get there
+            assert ( false && "CC_RECEIVE_UPDT_NLINE : incoherent handling of either r_cc_receive_data_ins or r_cc_receive_*cache_req or r_cc_receive_fifo\n");
+            break;
+        }
         //////////////////////////
-        case CLEANUP_CMD_INS_IDLE:     // icache has highest priority
-        {
-            if ( r_icache_cleanup_req.read() )      // icache request
-            {
-                r_cleanup_cmd_fsm   = CLEANUP_CMD_INS_GO;
-                r_cleanup_cmd_trdid = (r_icache_cleanup_way.read()<<1) + 1;
-            }
-            else if ( r_dcache_cleanup_req.read() ) // dcache request
-            {
-                r_cleanup_cmd_fsm   = CLEANUP_CMD_DATA_GO;
-                r_cleanup_cmd_trdid = r_dcache_cleanup_way.read()<<1;
+        case CC_RECEIVE_UPDT_DATA:
+        {
+            if ((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read()))
+                r_cc_receive_dcache_req = true;
+            if ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read()))
+                r_cc_receive_icache_req = true;
+
+            // sample data, be and eop
+            uint64_t receive_data = p_dspin_in.data.read();
+            // wait for the fifo
+            if (r_cc_receive_updt_fifo_be.wok())
+            {
+                cc_receive_updt_fifo_be = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_BE);
+                cc_receive_updt_fifo_data = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_DATA);
+                // sample eop to test for state exit
+                bool flit_eop = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::FROM_MC_EOP);
+                cc_receive_updt_fifo_eop = flit_eop;
+                cc_receive_updt_fifo_put  = true;
+                if(flit_eop)
+                    r_cc_receive_fsm = CC_RECEIVE_IDLE;
             }
             break;
         }
-        /////////////////////////
-        case CLEANUP_CMD_DATA_GO:
-        {
-            if ( p_vci_ini_c.cmdack.read() )
-            {
-                r_cleanup_cmd_fsm    = CLEANUP_CMD_INS_IDLE;
-                r_dcache_cleanup_req = false;
-
-#if DEBUG_CLEANUP
-if ( m_debug_cleanup_fsm )
-{
-    std::cout << "  <PROC " << name() 
-              << " CLEANUP_CMD_DATA_GO> Cleanup request for icache:" << std::hex
-              << " PADDR = " << (r_dcache_cleanup_line.read()*m_dcache_words*4)
-              << " / TRDID = " << std::dec << r_cleanup_cmd_trdid.read() << std::endl;
-}
-#endif
-            }
-            break;
-        }
-        ////////////////////////
-        case CLEANUP_CMD_INS_GO:
-        {
-            if ( p_vci_ini_c.cmdack.read() )
-            {
-                r_cleanup_cmd_fsm    = CLEANUP_CMD_DATA_IDLE;
-                r_icache_cleanup_req = false;
-
-#if DEBUG_CLEANUP
-if ( m_debug_cleanup_fsm )
-{
-    std::cout << "  <PROC " << name() 
-              << " CLEANUP_CMD_INS_GO> Cleanup request for dcache:" << std::hex
-              << " PADDR = " << (r_icache_cleanup_line.read()*m_icache_words*4)
-              << " / TRDID = " << std::dec << r_cleanup_cmd_trdid.read() << std::endl;
-}
-#endif
-            }
-            break;
-        }
-    } // end switch CLEANUP FSM
-
-    /////////////////////////////////////////////////////////////////////////////////////
-    // The CLEANUP_RSP FSM is in charge to dispatch the cleanup responses to the
-    // ICACHE and DCACHE FSMs. The response arguments (set and way) are writen
-    // in dedicated buffers for ICACHE FSM and DCACHE FSM.
-    // These buffers are protected by two SET/RESET flip-flops, that are set 
-    // by the CLEANUP_RSP FSM, and reset by the selected FSM when the response 
-    // has been processed.
-    /////////////////////////////////////////////////////////////////////////////////////
-
-    switch( r_cleanup_rsp_fsm.read() )
-    {
-        //////////////////////
-        case CLEANUP_RSP_IDLE:
-        {
-            if ( p_vci_ini_c.rspval.read() )   
-            {
-                if((p_vci_ini_c.rtrdid.read() & 0x1) == 0x1)  // ICACHE
-                {
-                    r_cleanup_rsp_fsm = CLEANUP_RSP_INS;
-                }
-                else                                          // DCACHE
-                {
-                    r_cleanup_rsp_fsm = CLEANUP_RSP_DATA;
-                }
-            }
-            break;
-        }
-        /////////////////////
-        case CLEANUP_RSP_INS:
-        {
-            if ( not r_cleanup_icache_req.read() )    // buffer empty
-            {
-                r_cleanup_icache_req = true;
-                r_cleanup_icache_way   = p_vci_ini_c.rtrdid.read() >> 1;
-                r_cleanup_icache_set   = p_vci_ini_c.rdata.read() & (m_icache_sets-1);
-                r_cleanup_rsp_fsm      = CLEANUP_RSP_IDLE;
-            }
-            break;
-        }
-        //////////////////////
-        case CLEANUP_RSP_DATA:
-        {
-            if ( not r_cleanup_dcache_req.read() )    // buffer empty
-            {
-                r_cleanup_dcache_req = true;
-                r_cleanup_dcache_way   = p_vci_ini_c.rtrdid.read() >> 1;
-                r_cleanup_dcache_set   = p_vci_ini_c.rdata.read() & (m_dcache_sets-1);
-                r_cleanup_rsp_fsm      = CLEANUP_RSP_IDLE;
-            }
-            break;
-        }
-    } // end switch CLEANUP_RSP
-
+    } // end switch CC_RECEIVE FSM
 
     ///////////////// Response FIFOs update  //////////////////////
@@ -5582,4 +5673,16 @@
                                  vci_rsp_fifo_dcache_data);
 
+    ///////////////// updt FIFO update  //////////////////////
+    //TODO check this
+    r_cc_receive_updt_fifo_be.update(cc_receive_updt_fifo_get,
+                                 cc_receive_updt_fifo_put,
+                                 cc_receive_updt_fifo_be);
+    r_cc_receive_updt_fifo_data.update(cc_receive_updt_fifo_get,
+                                 cc_receive_updt_fifo_put,
+                                 cc_receive_updt_fifo_data);
+    r_cc_receive_updt_fifo_eop.update(cc_receive_updt_fifo_get,
+                                 cc_receive_updt_fifo_put,
+                                 cc_receive_updt_fifo_eop);
+
 } // end transition()
 
@@ -5588,64 +5691,4 @@
 ///////////////////////
 {
-    // VCI initiator command on the coherence network (cleanup)
-    // it depends on the CLEANUP_CMD FSM state
-
-    paddr_t  cleanup_nline;
-    paddr_t  address;
-
-    if ( r_cleanup_cmd_fsm.read() == CLEANUP_CMD_DATA_GO )
-    {
-        cleanup_nline = r_dcache_cleanup_line.read();
-        address       = (m_x_width + m_y_width) ? (cleanup_nline * m_dcache_words * 4    ) >>
-                                                  (vci_param::N  - m_x_width - m_y_width ) : 0;
-    }
-    else if ( r_cleanup_cmd_fsm.read() == CLEANUP_CMD_INS_GO )
-    {
-        cleanup_nline = r_icache_cleanup_line.read();
-        address       = (m_x_width + m_y_width) ? (cleanup_nline * m_icache_words * 4    ) >>
-                                                  (vci_param::N  - m_x_width - m_y_width ) : 0;
-    }
-    else
-    {
-        cleanup_nline = 0;
-        address       = 0;
-    }
-
-    address           <<= vci_param::S - m_x_width - m_y_width;
-    address            |= m_memory_cache_local_id;
-    address           <<= vci_param::N - vci_param::S;
-
-    p_vci_ini_c.cmdval  = ( (r_cleanup_cmd_fsm.read() == CLEANUP_CMD_DATA_GO) or
-                            (r_cleanup_cmd_fsm.read() == CLEANUP_CMD_INS_GO) );
-    p_vci_ini_c.address = address;
-    p_vci_ini_c.wdata   = (uint32_t) cleanup_nline;
-    p_vci_ini_c.be      = (cleanup_nline >> 32) & 0x3;
-    p_vci_ini_c.plen    = 4;
-    p_vci_ini_c.cmd     = vci_param::CMD_WRITE;
-    p_vci_ini_c.trdid   = r_cleanup_cmd_trdid.read();
-    p_vci_ini_c.pktid   = 0;
-    p_vci_ini_c.srcid   = m_srcid_c;
-    p_vci_ini_c.cons    = false;
-    p_vci_ini_c.wrap    = false;
-    p_vci_ini_c.contig  = false;
-    p_vci_ini_c.clen    = 0;
-    p_vci_ini_c.cfixed  = false;
-    p_vci_ini_c.eop     = true;
-
-    // VCI initiator response on the coherence network (cleanup)
-    // it depends on the CLEANUP_RSP FSM
-
-    if ( r_cleanup_rsp_fsm.read() == CLEANUP_RSP_IDLE )
-    {
-        p_vci_ini_c.rspack  = true;
-    }
-    else if ( r_cleanup_rsp_fsm.read() == CLEANUP_RSP_DATA )
-    {
-        p_vci_ini_c.rspack  = not r_cleanup_dcache_req.read();
-    }
-    else if ( r_cleanup_rsp_fsm.read() == CLEANUP_RSP_INS )
-    {
-        p_vci_ini_c.rspack  = not r_cleanup_icache_req.read();
-    }
 
     // VCI initiator command on the direct network
@@ -5655,180 +5698,386 @@
                          (r_vci_cmd_fsm.read() == CMD_DATA_SC );
 
-    p_vci_ini_d.pktid  = 0;
-    p_vci_ini_d.srcid  = m_srcid_d;
-    p_vci_ini_d.cons   = is_sc_or_cas; 
-    p_vci_ini_d.contig = not is_sc_or_cas; 
-    p_vci_ini_d.wrap   = false;
-    p_vci_ini_d.clen   = 0;
-    p_vci_ini_d.cfixed = false;
+    p_vci.pktid  = 0;
+    p_vci.srcid  = m_srcid;
+    p_vci.cons   = is_sc_or_cas; 
+    p_vci.contig = not is_sc_or_cas; 
+    p_vci.wrap   = false;
+    p_vci.clen   = 0;
+    p_vci.cfixed = false;
 
     switch ( r_vci_cmd_fsm.read() ) {
 
     case CMD_IDLE:
-        p_vci_ini_d.cmdval  = false;
-        p_vci_ini_d.address = 0;
-        p_vci_ini_d.wdata   = 0;
-        p_vci_ini_d.be      = 0;
-        p_vci_ini_d.trdid   = 0;
-        p_vci_ini_d.pktid   = 0;
-        p_vci_ini_d.plen    = 0;
-        p_vci_ini_d.cmd     = vci_param::CMD_NOP;
-        p_vci_ini_d.eop     = false;
+        p_vci.cmdval  = false;
+        p_vci.address = 0;
+        p_vci.wdata   = 0;
+        p_vci.be      = 0;
+        p_vci.trdid   = 0;
+        p_vci.pktid   = 0;
+        p_vci.plen    = 0;
+        p_vci.cmd     = vci_param::CMD_NOP;
+        p_vci.eop     = false;
         break;
 
     case CMD_INS_MISS:
-        p_vci_ini_d.cmdval  = true;
-        p_vci_ini_d.address = r_icache_vci_paddr.read() & m_icache_yzmask;
-        p_vci_ini_d.wdata   = 0;
-        p_vci_ini_d.be      = 0xF;
-        p_vci_ini_d.trdid   = 0;
-        p_vci_ini_d.pktid   = TYPE_READ_INS_MISS;
-        p_vci_ini_d.plen    = m_icache_words<<2;
-        p_vci_ini_d.cmd     = vci_param::CMD_READ;
-        p_vci_ini_d.eop     = true;
+        p_vci.cmdval  = true;
+        p_vci.address = r_icache_vci_paddr.read() & m_icache_yzmask;
+        p_vci.wdata   = 0;
+        p_vci.be      = 0xF;
+        p_vci.trdid   = 0;
+        p_vci.pktid   = TYPE_READ_INS_MISS;
+        p_vci.plen    = m_icache_words<<2;
+        p_vci.cmd     = vci_param::CMD_READ;
+        p_vci.eop     = true;
         break;
 
     case CMD_INS_UNC:
-        p_vci_ini_d.cmdval  = true;
-        p_vci_ini_d.address = r_icache_vci_paddr.read() & ~0x3;
-        p_vci_ini_d.wdata   = 0;
-        p_vci_ini_d.be      = 0xF;
-        p_vci_ini_d.trdid   = 0;
-        p_vci_ini_d.pktid   = TYPE_READ_INS_UNC;
-        p_vci_ini_d.plen    = 4;
-        p_vci_ini_d.cmd     = vci_param::CMD_READ;
-        p_vci_ini_d.eop     = true;
+        p_vci.cmdval  = true;
+        p_vci.address = r_icache_vci_paddr.read() & ~0x3;
+        p_vci.wdata   = 0;
+        p_vci.be      = 0xF;
+        p_vci.trdid   = 0;
+        p_vci.pktid   = TYPE_READ_INS_UNC;
+        p_vci.plen    = 4;
+        p_vci.cmd     = vci_param::CMD_READ;
+        p_vci.eop     = true;
         break;
 
     case CMD_DATA_MISS:
-        p_vci_ini_d.cmdval  = true;
-        p_vci_ini_d.address = r_dcache_vci_paddr.read() & m_dcache_yzmask;
-        p_vci_ini_d.wdata   = 0;
-        p_vci_ini_d.be      = 0xF;
-        p_vci_ini_d.trdid   = 0;
-        p_vci_ini_d.pktid   = TYPE_READ_DATA_MISS;
-        p_vci_ini_d.plen    = m_dcache_words << 2;
-        p_vci_ini_d.cmd     = vci_param::CMD_READ;
-        p_vci_ini_d.eop     = true;
+        p_vci.cmdval  = true;
+        p_vci.address = r_dcache_vci_paddr.read() & m_dcache_yzmask;
+        p_vci.wdata   = 0;
+        p_vci.be      = 0xF;
+        p_vci.trdid   = 0;
+        p_vci.pktid   = TYPE_READ_DATA_MISS;
+        p_vci.plen    = m_dcache_words << 2;
+        p_vci.cmd     = vci_param::CMD_READ;
+        p_vci.eop     = true;
         break;
 
     case CMD_DATA_UNC:
-        p_vci_ini_d.cmdval  = true;
-        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
-        p_vci_ini_d.wdata   = 0;
-        p_vci_ini_d.be      = r_dcache_vci_unc_be.read();
-        p_vci_ini_d.trdid   = 0;
-        p_vci_ini_d.pktid   = TYPE_READ_DATA_UNC;
-        p_vci_ini_d.plen    = 4;
-        p_vci_ini_d.cmd     = vci_param::CMD_READ;
-        p_vci_ini_d.eop     = true;
+        p_vci.cmdval  = true;
+        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
+        p_vci.wdata   = 0;
+        p_vci.be      = r_dcache_vci_unc_be.read();
+        p_vci.trdid   = 0;
+        p_vci.pktid   = TYPE_READ_DATA_UNC;
+        p_vci.plen    = 4;
+        p_vci.cmd     = vci_param::CMD_READ;
+        p_vci.eop     = true;
         break;
 
     case CMD_DATA_WRITE:
-        p_vci_ini_d.cmdval  = true;
-        p_vci_ini_d.address = r_wbuf.getAddress(r_vci_cmd_cpt.read()) & ~0x3;
-        p_vci_ini_d.wdata   = r_wbuf.getData(r_vci_cmd_cpt.read());
-        p_vci_ini_d.be      = r_wbuf.getBe(r_vci_cmd_cpt.read());
-        p_vci_ini_d.trdid   = r_wbuf.getIndex();
-        p_vci_ini_d.pktid   = TYPE_WRITE;
-        p_vci_ini_d.plen    = (r_vci_cmd_max.read() - r_vci_cmd_min.read() + 1) << 2;
-        p_vci_ini_d.cmd     = vci_param::CMD_WRITE;
-        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
+        p_vci.cmdval  = true;
+        p_vci.address = r_wbuf.getAddress(r_vci_cmd_cpt.read()) & ~0x3;
+        p_vci.wdata   = r_wbuf.getData(r_vci_cmd_cpt.read());
+        p_vci.be      = r_wbuf.getBe(r_vci_cmd_cpt.read());
+        p_vci.trdid   = r_wbuf.getIndex();
+        p_vci.pktid   = TYPE_WRITE;
+        p_vci.plen    = (r_vci_cmd_max.read() - r_vci_cmd_min.read() + 1) << 2;
+        p_vci.cmd     = vci_param::CMD_WRITE;
+        p_vci.eop     = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
         break;
 
     case CMD_DATA_LL:
-        p_vci_ini_d.cmdval  = true;
-        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
-        p_vci_ini_d.wdata   = 0;
-        p_vci_ini_d.be      = 0xF;
-        p_vci_ini_d.trdid   = 0;
-        p_vci_ini_d.pktid   = TYPE_LL;
-        p_vci_ini_d.plen    = 8;
-        p_vci_ini_d.cmd     = vci_param::CMD_LOCKED_READ;
-        p_vci_ini_d.eop     = true;
+        p_vci.cmdval  = true;
+        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
+        p_vci.wdata   = 0;
+        p_vci.be      = 0xF;
+        p_vci.trdid   = 0;
+        p_vci.pktid   = TYPE_LL;
+        p_vci.plen    = 8;
+        p_vci.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci.eop     = true;
         break;
 
     case CMD_DATA_SC:
-        p_vci_ini_d.cmdval  = true;
-        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
-        if ( r_vci_cmd_cpt.read() == 0 ) p_vci_ini_d.wdata = r_dcache_llsc_key.read();
-        else                             p_vci_ini_d.wdata = r_dcache_vci_sc_data.read();
-        p_vci_ini_d.be      = 0xF;
-        p_vci_ini_d.trdid   = 0;
-        p_vci_ini_d.pktid   = TYPE_SC;
-        p_vci_ini_d.plen    = 8;
-        p_vci_ini_d.cmd     = vci_param::CMD_NOP;
-        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == 1);
-        break;      
+        p_vci.cmdval  = true;
+        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
+        if ( r_vci_cmd_cpt.read() == 0 ) p_vci.wdata = r_dcache_llsc_key.read();
+        else                             p_vci.wdata = r_dcache_vci_sc_data.read();
+        p_vci.be      = 0xF;
+        p_vci.trdid   = 0;
+        p_vci.pktid   = TYPE_SC;
+        p_vci.plen    = 8;
+        p_vci.cmd     = vci_param::CMD_NOP;
+        p_vci.eop     = (r_vci_cmd_cpt.read() == 1);
+        break;
 
     case CMD_DATA_CAS:
-        p_vci_ini_d.cmdval  = true;
-        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
-        if ( r_vci_cmd_cpt.read() == 0 ) p_vci_ini_d.wdata = r_dcache_vci_cas_old.read();
-        else                             p_vci_ini_d.wdata = r_dcache_vci_cas_new.read();
-        p_vci_ini_d.be      = 0xF;
-        p_vci_ini_d.trdid   = 0;
-        p_vci_ini_d.pktid   = TYPE_CAS;
-        p_vci_ini_d.plen    = 8;
-        p_vci_ini_d.cmd     = vci_param::CMD_NOP;
-        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == 1);
-        break;      
+        p_vci.cmdval  = true;
+        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
+        if ( r_vci_cmd_cpt.read() == 0 ) p_vci.wdata = r_dcache_vci_cas_old.read();
+        else                             p_vci.wdata = r_dcache_vci_cas_new.read();
+        p_vci.be      = 0xF;
+        p_vci.trdid   = 0;
+        p_vci.pktid   = TYPE_CAS;
+        p_vci.plen    = 8;
+        p_vci.cmd     = vci_param::CMD_NOP;
+        p_vci.eop     = (r_vci_cmd_cpt.read() == 1);
+        break;
     } // end switch r_vci_cmd_fsm
 
     // VCI initiator response on the direct network
-    // it depends on the VCI RSP state
+    // it depends on the VCI_RSP FSM
 
     switch (r_vci_rsp_fsm.read() )
     {
-        case RSP_DATA_WRITE : p_vci_ini_d.rspack = true; break;
-        case RSP_INS_MISS   : p_vci_ini_d.rspack = r_vci_rsp_fifo_icache.wok(); break;
-        case RSP_INS_UNC    : p_vci_ini_d.rspack = r_vci_rsp_fifo_icache.wok(); break;
-        case RSP_DATA_MISS  : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
-        case RSP_DATA_UNC   : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
-        case RSP_DATA_LL    : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
-        case RSP_IDLE       : p_vci_ini_d.rspack = false; break;
+        case RSP_DATA_WRITE : p_vci.rspack = true; break;
+        case RSP_INS_MISS   : p_vci.rspack = r_vci_rsp_fifo_icache.wok(); break;
+        case RSP_INS_UNC    : p_vci.rspack = r_vci_rsp_fifo_icache.wok(); break;
+        case RSP_DATA_MISS  : p_vci.rspack = r_vci_rsp_fifo_dcache.wok(); break;
+        case RSP_DATA_UNC   : p_vci.rspack = r_vci_rsp_fifo_dcache.wok(); break;
+        case RSP_DATA_LL    : p_vci.rspack = r_vci_rsp_fifo_dcache.wok(); break;
+        case RSP_IDLE       : p_vci.rspack = false; break;
     } // end switch r_vci_rsp_fsm
 
-    // VCI target command and response on the coherence network
-    switch ( r_tgt_fsm.read() ) 
-    {
-    case TGT_IDLE:
-    case TGT_UPDT_WORD:
-    case TGT_UPDT_DATA:
-        p_vci_tgt_c.cmdack  = true;
-        p_vci_tgt_c.rspval  = false;
-        break;
-
-    case TGT_RSP_ICACHE:
-        p_vci_tgt_c.cmdack  = false;
-        p_vci_tgt_c.rspval  = not r_tgt_icache_req.read() and r_icache_tgt_need_rsp.read();
-        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
-        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
-        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
-        p_vci_tgt_c.rdata   = 0;
-        p_vci_tgt_c.rerror  = 0;
-        p_vci_tgt_c.reop    = true;
-        break;
-
-    case TGT_RSP_DCACHE:
-        p_vci_tgt_c.cmdack  = false;
-        p_vci_tgt_c.rspval  = not r_tgt_dcache_req.read() and r_dcache_tgt_need_rsp.read();
-        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
-        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
-        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
-        p_vci_tgt_c.rdata   = 0;
-        p_vci_tgt_c.rerror  = 0;
-        p_vci_tgt_c.reop    = true;
-        break;
-
-    case TGT_RSP_BROADCAST:     // no response for broadcast...
-    case TGT_REQ_BROADCAST:
-    case TGT_REQ_ICACHE:
-    case TGT_REQ_DCACHE:
-        p_vci_tgt_c.cmdack  = false;
-        p_vci_tgt_c.rspval  = false;
-        break;
-
-    } // end switch TGT_FSM
+    
+    // Send coherence packets on DSPIN L2M 
+    // it depends on the CC_SEND FSM 
+
+    uint64_t dspin_send_data = 0;
+    switch ( r_cc_send_fsm.read() )
+    {
+        //////////////////
+        case CC_SEND_IDLE:
+        {
+            p_dspin_out.write = false;
+            break;
+        }
+        ///////////////////////
+        case CC_SEND_CLEANUP_1:
+        {
+            // initialize dspin send data
+            DspinDhccpParam::dspin_set(dspin_send_data,
+                                       0,
+                                       DspinDhccpParam::FROM_L1_EOP);
+            DspinDhccpParam::dspin_set(dspin_send_data,
+                                       m_cc_global_id,
+                                       DspinDhccpParam::CLEANUP_SRCID);
+            DspinDhccpParam::dspin_set(dspin_send_data,
+                                       0,
+                                       DspinDhccpParam::FROM_L1_BC);
+
+            if(r_cc_send_last_client.read() == 0) // dcache active request
+            {
+                uint64_t dest = (uint64_t)r_dcache_cc_send_nline.read() 
+                                >> (m_nline_width - m_x_width - m_y_width) 
+                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
+ 
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           dest,
+                                           DspinDhccpParam::CLEANUP_DEST);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           r_dcache_cc_send_nline.read() & 0x300000000ULL,
+                                           DspinDhccpParam::CLEANUP_NLINE_MSB);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           r_dcache_cc_send_way.read(),
+                                           DspinDhccpParam::CLEANUP_WAY_INDEX);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           DspinDhccpParam::TYPE_CLEANUP_DATA,
+                                           DspinDhccpParam::FROM_L1_TYPE);
+            }
+            else                                // icache active request
+            {
+                uint64_t dest = (uint64_t)r_icache_cc_send_nline.read() 
+                                >> (m_nline_width - m_x_width - m_y_width) 
+                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           dest,
+                                           DspinDhccpParam::CLEANUP_DEST);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           r_icache_cc_send_nline.read() & 0x300000000ULL,
+                                           DspinDhccpParam::CLEANUP_NLINE_MSB);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           r_icache_cc_send_way.read(),
+                                           DspinDhccpParam::CLEANUP_WAY_INDEX);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           DspinDhccpParam::TYPE_CLEANUP_INST,
+                                           DspinDhccpParam::FROM_L1_TYPE);
+            }
+            // send flit
+            p_dspin_out.data  = dspin_send_data;
+            p_dspin_out.write = true;
+            break;
+        }
+        ///////////////////////
+        case CC_SEND_CLEANUP_2:
+        {
+            // initialize dspin send data
+            DspinDhccpParam::dspin_set(dspin_send_data,
+                                       1,
+                                       DspinDhccpParam::FROM_L1_EOP);
+
+            if(r_cc_send_last_client.read() == 0) // dcache active request
+            {
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           r_dcache_cc_send_nline.read() & 0xFFFFFFFFULL,
+                                           DspinDhccpParam::CLEANUP_NLINE_LSB);
+            }
+            else                                  // icache active request
+            {
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           r_icache_cc_send_nline.read() & 0xFFFFFFFFULL,
+                                           DspinDhccpParam::CLEANUP_NLINE_LSB);
+            }
+            // send flit
+            p_dspin_out.data  = dspin_send_data;
+            p_dspin_out.write = true;
+            break;
+        }
+        ///////////////////////
+        case CC_SEND_MULTI_ACK:
+        {
+            // initialize dspin send data
+            DspinDhccpParam::dspin_set(dspin_send_data,
+                                       1,
+                                       DspinDhccpParam::FROM_L1_EOP);
+            DspinDhccpParam::dspin_set(dspin_send_data,
+                                       0,
+                                       DspinDhccpParam::FROM_L1_BC);
+            DspinDhccpParam::dspin_set(dspin_send_data,
+                                       DspinDhccpParam::TYPE_MULTI_ACK,
+                                       DspinDhccpParam::FROM_L1_TYPE);
+
+            if(r_cc_send_last_client.read() == 0) // dcache active request
+            {
+                uint64_t dest = (uint64_t)r_dcache_cc_send_nline.read() 
+                                >> (m_nline_width - m_x_width - m_y_width) 
+                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
+ 
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           dest,
+                                           DspinDhccpParam::MULTI_ACK_DEST);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           r_dcache_cc_send_updt_tab_idx.read(),
+                                           DspinDhccpParam::MULTI_ACK_UPDT_INDEX);
+            }
+            else                                    // icache active request
+            {
+                uint64_t dest = (uint64_t)r_icache_cc_send_nline.read() 
+                                >> (m_nline_width - m_x_width - m_y_width) 
+                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
+ 
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           dest,
+                                           DspinDhccpParam::MULTI_ACK_DEST);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           r_icache_cc_send_updt_tab_idx.read(),
+                                           DspinDhccpParam::MULTI_ACK_UPDT_INDEX);
+            }
+            // send flit
+            p_dspin_out.data  = dspin_send_data;
+            p_dspin_out.write = true;
+            break;
+        }
+    } // end switch CC_SEND FSM
+
+    // Receive coherence packets
+    // It depends on the CC_RECEIVE FSM 
+
+    switch( r_cc_receive_fsm.read() )
+    {
+        /////////////////////
+        case CC_RECEIVE_IDLE:
+        {
+            p_dspin_in.read = false;
+            break;
+        }
+        //////////////////////
+        case CC_RECEIVE_CLACK:
+        {
+            if (((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read())) or
+                ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read())))
+                p_dspin_in.read = true;
+            else
+                p_dspin_in.read = false;
+            break;
+        }
+        ///////////////////////////////
+        case CC_RECEIVE_BRDCAST_HEADER:
+        {
+            p_dspin_in.read = true;
+            break;
+        }
+        //////////////////////////////
+        case CC_RECEIVE_BRDCAST_NLINE:
+        {
+            // TODO maybe we need to wait for both only to leave the state, but
+            // not to actually post a request to an available cache => need a
+            // flip_flop to check that ?
+            if (not (r_cc_receive_icache_req.read()) and not (r_cc_receive_dcache_req.read()))
+                p_dspin_in.read = true;
+            else
+                p_dspin_in.read = false;
+            break;
+        }
+        /////////////////////////////
+        case CC_RECEIVE_INVAL_HEADER:
+        {
+            if (((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read())) or
+                ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read())))
+                p_dspin_in.read = true;
+            else
+                p_dspin_in.read = false;
+            break;
+        }
+        ////////////////////////////
+        case CC_RECEIVE_INVAL_NLINE:
+        {
+            p_dspin_in.read = true;
+            break;
+        }
+        ////////////////////////////
+        case CC_RECEIVE_UPDT_HEADER:
+        {
+            if (((r_cc_receive_data_ins.read() == 0) and
+                not r_cc_receive_dcache_req.read() and
+                r_cc_receive_updt_fifo_be.empty())
+                or
+                ((r_cc_receive_data_ins.read() == 1) and
+                not r_cc_receive_icache_req.read()) and
+                r_cc_receive_updt_fifo_be.empty())
+                p_dspin_in.read = true;
+            else
+                p_dspin_in.read = false;
+            break;
+        }
+        ///////////////////////////
+        case CC_RECEIVE_UPDT_NLINE:
+        {
+            if (((r_cc_receive_data_ins.read() == 0) and
+                not (r_cc_receive_dcache_req.read()) and
+                r_cc_receive_updt_fifo_be.empty())
+                or
+                ((r_cc_receive_data_ins.read() == 1) and
+                not (r_cc_receive_icache_req.read()) and
+                r_cc_receive_updt_fifo_be.empty()))
+                p_dspin_in.read = true;
+            else
+                p_dspin_in.read = false;
+            break;
+        }
+        //////////////////////////
+        case CC_RECEIVE_UPDT_DATA:
+        {
+            if (r_cc_receive_updt_fifo_be.wok())
+                p_dspin_in.read = true;
+            else
+                p_dspin_in.read = false;
+            break;
+        }
+    } // end switch CC_RECEIVE FSM
+
 } // end genMoore
 
Index: branches/v5/modules/vci_mem_cache/caba/metadata/vci_mem_cache.sd
===================================================================
--- branches/v5/modules/vci_mem_cache/caba/metadata/vci_mem_cache.sd	(revision 346)
+++ branches/v5/modules/vci_mem_cache/caba/metadata/vci_mem_cache.sd	(revision 351)
@@ -2,11 +2,13 @@
 # -*- python -*-
 
-__id__ = "$Id$"
-__version__ = "$Revision$"
+__id__ = "$Id: vci_mem_cache.sd 295 2013-02-14 15:05:05Z cfuguet $"
+__version__ = "$Revision: 295 $"
 
 Module('caba:vci_mem_cache',
         classname = 'soclib::caba::VciMemCache',
 
-        tmpl_parameters = [ parameter.Module('vci_param', default = 'caba:vci_param') ],
+        tmpl_parameters = [
+			parameter.Module('vci_param'  , default = 'caba:vci_param')
+		],
 
         header_files = [
@@ -25,10 +27,19 @@
             Uses('caba:generic_fifo'),
             Uses('caba:generic_llsc_global_table'),
+			Uses('caba:dspin_dhccp_param')
         ],
 
         ports = [
             Port( 'caba:vci_target'   , 'p_vci_tgt' ),
-            Port( 'caba:vci_target'   , 'p_vci_tgt_cleanup' ),
-            Port( 'caba:vci_initiator', 'p_vci_ini' ),
+            Port(
+				'caba:dspin_input',
+				'p_dspin_in',
+				dspin_data_size = 33,
+			),
+			Port(
+				'caba:dspin_output',
+				'p_dspin_out',
+				dspin_data_size = 40,
+			),
             Port( 'caba:vci_initiator', 'p_vci_ixr' ),
             Port( 'caba:bit_in'       , 'p_resetn'  , auto = 'resetn' ),
Index: branches/v5/modules/vci_mem_cache/caba/source/include/vci_mem_cache.h
===================================================================
--- branches/v5/modules/vci_mem_cache/caba/source/include/vci_mem_cache.h	(revision 346)
+++ branches/v5/modules/vci_mem_cache/caba/source/include/vci_mem_cache.h	(revision 351)
@@ -28,13 +28,4 @@
  *              cesar.fuguet-tortolero@lip6.fr
  *              alexandre.joannou@lip6.fr
- *
- * Modifications done by Christophe Choichillon on the 7/04/2009:
- * - Adding new states in the CLEANUP FSM : CLEANUP_UPT_LOCK and CLEANUP_UPT_WRITE
- * - Adding a new VCI target port for the CLEANUP network
- * - Adding new state in the ALLOC_UPT_FSM : ALLOC_UPT_CLEANUP
- *
- * Modifications to do :
- * - Adding new variables used by the CLEANUP FSM
- *
  */
 
@@ -58,4 +49,6 @@
 #include "xram_transaction.h"
 #include "update_tab.h"
+#include "dspin_interface.h"
+#include "dspin_dhccp_param.h"
 
 #define TRANSACTION_TAB_LINES 4 // Number of lines in the transaction tab
@@ -101,28 +94,41 @@
       };
 
-      /* States of the INIT_CMD fsm */
-      enum init_cmd_fsm_state_e{
-        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_CAS_UPDT_IDLE,
-        INIT_CMD_CAS_BRDCAST,
-        INIT_CMD_CAS_UPDT_NLINE,
-        INIT_CMD_CAS_UPDT_INDEX,
-        INIT_CMD_CAS_UPDT_DATA,
-        INIT_CMD_CAS_UPDT_DATA_HIGH
-      };
-
-      /* States of the INIT_RSP fsm */
-      enum init_rsp_fsm_state_e{
-        INIT_RSP_IDLE,
-        INIT_RSP_UPT_LOCK,
-        INIT_RSP_UPT_CLEAR,
-        INIT_RSP_END
+      /* States of the DSPIN_TGT fsm */
+      enum cc_receive_fsm_state_e{
+        CC_RECEIVE_IDLE,
+        CC_RECEIVE_CLEANUP,
+        CC_RECEIVE_MULTI_ACK
+      };
+
+      /* States of the CC_SEND fsm */
+      enum cc_send_fsm_state_e{
+        CC_SEND_XRAM_RSP_IDLE,
+        CC_SEND_WRITE_IDLE,
+        CC_SEND_CAS_IDLE,
+        CC_SEND_CLEANUP_IDLE,
+        CC_SEND_CLEANUP_ACK,
+        CC_SEND_XRAM_RSP_BRDCAST_HEADER,
+        CC_SEND_XRAM_RSP_BRDCAST_NLINE,
+        CC_SEND_XRAM_RSP_INVAL_HEADER,
+        CC_SEND_XRAM_RSP_INVAL_NLINE,
+        CC_SEND_WRITE_BRDCAST_HEADER,
+        CC_SEND_WRITE_BRDCAST_NLINE,
+        CC_SEND_WRITE_UPDT_HEADER,
+        CC_SEND_WRITE_UPDT_NLINE,
+        CC_SEND_WRITE_UPDT_DATA,
+        CC_SEND_CAS_BRDCAST_HEADER,
+        CC_SEND_CAS_BRDCAST_NLINE,
+        CC_SEND_CAS_UPDT_HEADER,
+        CC_SEND_CAS_UPDT_NLINE,
+        CC_SEND_CAS_UPDT_DATA,
+        CC_SEND_CAS_UPDT_DATA_HIGH
+      };
+
+      /* States of the MULTI_ACK fsm */
+      enum multi_ack_fsm_state_e{
+        MULTI_ACK_IDLE,
+        MULTI_ACK_UPT_LOCK,
+        MULTI_ACK_UPT_CLEAR,
+        MULTI_ACK_WRITE_RSP
       };
 
@@ -237,4 +243,5 @@
       enum cleanup_fsm_state_e{
         CLEANUP_IDLE,
+        CLEANUP_GET_NLINE,
         CLEANUP_DIR_REQ,
         CLEANUP_DIR_LOCK,
@@ -246,7 +253,8 @@
         CLEANUP_HEAP_FREE,
         CLEANUP_UPT_LOCK,
-        CLEANUP_UPT_WRITE,
+        CLEANUP_UPT_DECREMENT,
+        CLEANUP_UPT_CLEAR,
         CLEANUP_WRITE_RSP,
-        CLEANUP_RSP
+        CLEANUP_SEND_ACK
       };
 
@@ -274,5 +282,5 @@
         ALLOC_UPT_WRITE,
         ALLOC_UPT_XRAM_RSP,
-        ALLOC_UPT_INIT_RSP,
+        ALLOC_UPT_MULTI_ACK,
         ALLOC_UPT_CLEANUP,
         ALLOC_UPT_CAS
@@ -318,11 +326,10 @@
 
       // 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_cc_send_fsm;
+      bool         m_debug_cc_receive_fsm;
+      bool         m_debug_multi_ack_fsm;
       bool         m_debug_read_fsm;
       bool         m_debug_write_fsm;
@@ -369,25 +376,24 @@
       sc_in<bool>                           p_resetn;
       soclib::caba::VciTarget<vci_param>    p_vci_tgt;
-      soclib::caba::VciTarget<vci_param>    p_vci_tgt_cleanup;
-      soclib::caba::VciInitiator<vci_param> p_vci_ini;
       soclib::caba::VciInitiator<vci_param> p_vci_ixr;
+      soclib::caba::DspinInput<33>          p_dspin_in;
+      soclib::caba::DspinOutput<40>         p_dspin_out;
 
       VciMemCache(
           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);
+          const soclib::common::MappingTable &mtp,            // Mapping table for direct network
+          const soclib::common::MappingTable &mtx,            // Mapping table for external network
+          const soclib::common::IntTab       &srcid_x,        // global index on external network
+          const soclib::common::IntTab       &tgtid_d,        // global index on direct network
+          const size_t                       cc_global_id,    // global index on cc network
+          const size_t                       nways,           // Number of ways per set
+          const size_t                       nsets,           // Number of sets
+          const size_t                       nwords,          // Number of words per line
+          const size_t                       max_copies,      // max number of copies in heap
+          const size_t                       heap_size=1024,  // number of heap entries
+          const size_t                       trt_lines=TRANSACTION_TAB_LINES, 
+          const size_t                       upt_lines=UPDATE_TAB_LINES,       
+          const size_t                       debug_start_cycle=0,
+          const bool                         debug_ok=false );
 
       ~VciMemCache();
@@ -404,47 +410,42 @@
       void genMoore();
       void check_monitor( const char *buf, vci_addr_t addr, data_t data);
+      void check_monitor_read( const char *buf, vci_addr_t addr);
 
       // Component attributes
-      std::list<soclib::common::Segment> m_seglist;  // memory cached into the cache
-      std::list<soclib::common::Segment> m_cseglist; // coherence segment for the cache
-
-      const size_t    m_initiators; // Number of initiators
-      const size_t    m_heap_size;  // Size of the heap
-      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
-
-      uint32_t        m_transaction_tab_lines;
-      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
-      CacheData       m_cache_data;       // data array[set][way][word]
-      HeapDirectory   m_heap;             // heap for copies
+      std::list<soclib::common::Segment> m_seglist;          // segments allocated to memcache
+      size_t                             m_nseg;             // number of segments
+      soclib::common::Segment            **m_seg;            // array of segments pointers
+      const size_t                       m_srcid_x;          // global index on external network
+      const size_t                       m_initiators;       // Number of initiators
+      const size_t                       m_heap_size;        // Size of the heap
+      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_cc_global_id;     // global_index on cc network
+      size_t                             m_debug_start_cycle;
+      bool                               m_debug_ok;
+      uint32_t                           m_trt_lines;
+      TransactionTab                     m_trt;              // xram transaction table
+      uint32_t                           m_upt_lines;
+      UpdateTab                          m_upt;              // pending update & invalidate
+      CacheDirectory                     m_cache_directory;  // data cache directory
+      CacheData                          m_cache_data;       // data array[set][way][word]
+      HeapDirectory                      m_heap;             // heap for copies
+      size_t                             m_max_copies;       // max number of copies in heap
       GenericLLSCGlobalTable
-      <
-        32  ,   // desired number of slots
-        4096,   // number of processors in the system
-        8000,   // registratioÃ§n life span (in # of LL operations)
-        typename vci_param::fast_addr_t // address type
-      >
-      m_llsc_table;       // ll/sc global registration table
+      < 32  ,                              // number of slots
+        4096,                              // number of processors in the system
+        8000,                              // registratioÃ§n life span (in # of LL operations)
+        typename vci_param::fast_addr_t >  // address type
+                                         m_llsc_table;       // ll/sc global registration table
 
       // adress masks
-      const soclib::common::AddressMaskingTable<vci_addr_t> m_x;
-      const soclib::common::AddressMaskingTable<vci_addr_t> m_y;
-      const soclib::common::AddressMaskingTable<vci_addr_t> m_z;
-      const soclib::common::AddressMaskingTable<vci_addr_t> m_nline;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_x;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_y;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_z;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_nline;
 
       // broadcast address
-      vci_addr_t m_broadcast_address;
-
-      //////////////////////////////////////////////////
-      // Others registers
-      //////////////////////////////////////////////////
-      sc_signal<size_t> r_copies_limit; // Limit of the number of copies for one line
-      sc_signal<size_t> xxx_count;
+      uint32_t                                                m_broadcast_address;
 
       //////////////////////////////////////////////////
@@ -476,10 +477,12 @@
       GenericFifo<data_t>    m_cmd_cas_wdata_fifo;
 
+      // Fifo between INIT_RSP fsm and CLEANUP fsm
+      GenericFifo<uint64_t>  m_cc_receive_to_cleanup_fifo;
+      
+      // Fifo between INIT_RSP fsm and MULTI_ACK fsm
+      GenericFifo<uint64_t>  m_cc_receive_to_multi_ack_fifo;
+
       sc_signal<int>         r_tgt_cmd_fsm;
 
-      size_t                   m_nseg;
-      size_t                   m_ncseg;
-      soclib::common::Segment  **m_seg;
-      soclib::common::Segment  **m_cseg;
       ///////////////////////////////////////////////////////
       // Registers controlled by the READ fsm
@@ -548,5 +551,5 @@
       sc_signal<size_t>   r_write_upt_index;  // index in Update Table
       sc_signal<bool>     r_write_sc_fail;    // sc command failed
-      sc_signal<bool>     r_write_pending_sc; // sc command pending in WRITE fsm
+      sc_signal<bool>     r_write_pending_sc; // sc command pending
 
       // Buffer between WRITE fsm and TGT_RSP fsm (acknowledge a write command from L1)
@@ -564,39 +567,39 @@
       sc_signal<size_t>   r_write_to_ixr_cmd_trdid; // index in Transaction Table
 
-      // Buffer between WRITE fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
-      sc_signal<bool>     r_write_to_init_cmd_multi_req;     // valid multicast request
-      sc_signal<bool>     r_write_to_init_cmd_brdcast_req;   // valid brdcast request
-      sc_signal<addr_t>   r_write_to_init_cmd_nline;         // cache line index
-      sc_signal<size_t>   r_write_to_init_cmd_trdid;         // index in Update Table
-      sc_signal<data_t> * r_write_to_init_cmd_data;          // data (one cache line)
-      sc_signal<be_t>   * r_write_to_init_cmd_be;            // word enable
-      sc_signal<size_t>   r_write_to_init_cmd_count;         // number of words in line
-      sc_signal<size_t>   r_write_to_init_cmd_index;         // index of first word in line
-      GenericFifo<bool>   m_write_to_init_cmd_inst_fifo;     // fifo for the L1 type
-      GenericFifo<size_t> m_write_to_init_cmd_srcid_fifo;    // fifo for srcids
+      // Buffer between WRITE fsm and CC_SEND fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>     r_write_to_cc_send_multi_req;     // valid multicast request
+      sc_signal<bool>     r_write_to_cc_send_brdcast_req;   // valid brdcast request
+      sc_signal<addr_t>   r_write_to_cc_send_nline;         // cache line index
+      sc_signal<size_t>   r_write_to_cc_send_trdid;         // index in Update Table
+      sc_signal<data_t> * r_write_to_cc_send_data;          // data (one cache line)
+      sc_signal<be_t>   * r_write_to_cc_send_be;            // word enable
+      sc_signal<size_t>   r_write_to_cc_send_count;         // number of words in line
+      sc_signal<size_t>   r_write_to_cc_send_index;         // index of first word in line
+      GenericFifo<bool>   m_write_to_cc_send_inst_fifo;     // fifo for the L1 type
+      GenericFifo<size_t> m_write_to_cc_send_srcid_fifo;    // fifo for srcids
 #if L1_MULTI_CACHE
-      GenericFifo<size_t> m_write_to_init_cmd_cache_id_fifo; // fifo for srcids
+      GenericFifo<size_t> m_write_to_cc_send_cache_id_fifo; // fifo for srcids
 #endif
 
-      // Buffer between WRITE fsm and INIT_RSP fsm (Decrement UPT entry)
-      sc_signal<bool>     r_write_to_init_rsp_req;       // valid request
-      sc_signal<size_t>   r_write_to_init_rsp_upt_index; // index in update table
+      // Buffer between WRITE fsm and MULTI_ACK fsm (Decrement UPT entry)
+      sc_signal<bool>     r_write_to_multi_ack_req;       // valid request
+      sc_signal<size_t>   r_write_to_multi_ack_upt_index; // index in update table
 
       /////////////////////////////////////////////////////////
-      // Registers controlled by INIT_RSP fsm
+      // Registers controlled by MULTI_ACK fsm
       //////////////////////////////////////////////////////////
 
-      sc_signal<int>      r_init_rsp_fsm;       // FSM state
-      sc_signal<size_t>   r_init_rsp_upt_index; // index in the Update Table
-      sc_signal<size_t>   r_init_rsp_srcid;     // pending write srcid
-      sc_signal<size_t>   r_init_rsp_trdid;     // pending write trdid
-      sc_signal<size_t>   r_init_rsp_pktid;     // pending write pktid
-      sc_signal<addr_t>   r_init_rsp_nline;     // pending write nline
-
-      // Buffer between INIT_RSP fsm and TGT_RSP fsm (complete write/update transaction)
-      sc_signal<bool>     r_init_rsp_to_tgt_rsp_req;   // valid request
-      sc_signal<size_t>   r_init_rsp_to_tgt_rsp_srcid; // Transaction srcid
-      sc_signal<size_t>   r_init_rsp_to_tgt_rsp_trdid; // Transaction trdid
-      sc_signal<size_t>   r_init_rsp_to_tgt_rsp_pktid; // Transaction pktid
+      sc_signal<int>      r_multi_ack_fsm;       // FSM state
+      sc_signal<size_t>   r_multi_ack_upt_index; // index in the Update Table
+      sc_signal<size_t>   r_multi_ack_srcid;     // pending write srcid
+      sc_signal<size_t>   r_multi_ack_trdid;     // pending write trdid
+      sc_signal<size_t>   r_multi_ack_pktid;     // pending write pktid
+      sc_signal<addr_t>   r_multi_ack_nline;     // pending write nline
+
+      // Buffer between MULTI_ACK fsm and TGT_RSP fsm (complete write/update transaction)
+      sc_signal<bool>     r_multi_ack_to_tgt_rsp_req;   // valid request
+      sc_signal<size_t>   r_multi_ack_to_tgt_rsp_srcid; // Transaction srcid
+      sc_signal<size_t>   r_multi_ack_to_tgt_rsp_trdid; // Transaction trdid
+      sc_signal<size_t>   r_multi_ack_to_tgt_rsp_pktid; // Transaction pktid
 
       ///////////////////////////////////////////////////////
@@ -606,7 +609,11 @@
       sc_signal<int>      r_cleanup_fsm;           // FSM state
       sc_signal<size_t>   r_cleanup_srcid;         // transaction srcid
-      sc_signal<size_t>   r_cleanup_trdid;         // transaction trdid
+      sc_signal<bool>     r_cleanup_inst;          // Instruction or Data ?
+      sc_signal<size_t>   r_cleanup_way_index;     // L1 Cache Way index
+      sc_signal<addr_t>   r_cleanup_nline;         // cache line index
+
+#if L1_MULTI_CACHE
       sc_signal<size_t>   r_cleanup_pktid;         // transaction pktid
-      sc_signal<addr_t>   r_cleanup_nline;         // cache line index
+#endif
 
       sc_signal<copy_t>   r_cleanup_copy;          // first copy
@@ -629,5 +636,5 @@
       sc_signal<size_t>   r_cleanup_write_trdid;   // trdid of write rsp
       sc_signal<size_t>   r_cleanup_write_pktid;   // pktid of write rsp
-      sc_signal<bool>     r_cleanup_need_rsp;      // needs a write rsp
+      sc_signal<bool>     r_cleanup_write_need_rsp;// needs a write rsp
 
       sc_signal<size_t>   r_cleanup_index;         // index of the INVAL line (in the UPT)
@@ -638,4 +645,11 @@
       sc_signal<size_t>   r_cleanup_to_tgt_rsp_trdid; // transaction trdid
       sc_signal<size_t>   r_cleanup_to_tgt_rsp_pktid; // transaction pktid
+
+      // Buffer between CLEANUP fsm and CC_SEND fsm (acknowledge a cleanup command from L1)
+      sc_signal<bool>     r_cleanup_to_cc_send_req;       // valid request
+      sc_signal<size_t>   r_cleanup_to_cc_send_srcid;     // L1 srcid
+      sc_signal<size_t>   r_cleanup_to_cc_send_set_index; // L1 set index
+      sc_signal<size_t>   r_cleanup_to_cc_send_way_index; // L1 way index
+      sc_signal<bool>     r_cleanup_to_cc_send_inst;      // Instruction Cleanup Ack
 
       ///////////////////////////////////////////////////////
@@ -663,5 +677,5 @@
       sc_signal<data_t> * r_cas_data;       // cache line data
 
-      // Buffer between CAS fsm and INIT_CMD fsm (XRAM read)
+      // Buffer between CAS fsm and IXR_CMD fsm (XRAM write)
       sc_signal<bool>     r_cas_to_ixr_cmd_req;   // valid request
       sc_signal<addr_t>   r_cas_to_ixr_cmd_nline; // cache line index
@@ -678,22 +692,18 @@
       sc_signal<size_t>   r_cas_to_tgt_rsp_pktid; // Transaction pktid
 
-      // Buffer between CAS fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
-      sc_signal<bool>     r_cas_to_init_cmd_multi_req;     // valid request
-      sc_signal<bool>     r_cas_to_init_cmd_brdcast_req;   // brdcast request
-      sc_signal<addr_t>   r_cas_to_init_cmd_nline;         // cache line index
-      sc_signal<size_t>   r_cas_to_init_cmd_trdid;         // index in Update Table
-      sc_signal<data_t>   r_cas_to_init_cmd_wdata;         // data (one word)
-      sc_signal<bool>     r_cas_to_init_cmd_is_long;       // it is a 64 bits CAS
-      sc_signal<data_t>   r_cas_to_init_cmd_wdata_high;    // data high (one word)
-      sc_signal<size_t>   r_cas_to_init_cmd_index;         // index of the word in line
-      GenericFifo<bool>   m_cas_to_init_cmd_inst_fifo;     // fifo for the L1 type
-      GenericFifo<size_t> m_cas_to_init_cmd_srcid_fifo;    // fifo for srcids
+      // Buffer between CAS fsm and CC_SEND fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>     r_cas_to_cc_send_multi_req;     // valid request
+      sc_signal<bool>     r_cas_to_cc_send_brdcast_req;   // brdcast request
+      sc_signal<addr_t>   r_cas_to_cc_send_nline;         // cache line index
+      sc_signal<size_t>   r_cas_to_cc_send_trdid;         // index in Update Table
+      sc_signal<data_t>   r_cas_to_cc_send_wdata;         // data (one word)
+      sc_signal<bool>     r_cas_to_cc_send_is_long;       // it is a 64 bits CAS
+      sc_signal<data_t>   r_cas_to_cc_send_wdata_high;    // data high (one word)
+      sc_signal<size_t>   r_cas_to_cc_send_index;         // index of the word in line
+      GenericFifo<bool>   m_cas_to_cc_send_inst_fifo;     // fifo for the L1 type
+      GenericFifo<size_t> m_cas_to_cc_send_srcid_fifo;    // fifo for srcids
 #if L1_MULTI_CACHE
-      GenericFifo<size_t> m_cas_to_init_cmd_cache_id_fifo; // fifo for srcids
+      GenericFifo<size_t> m_cas_to_cc_send_cache_id_fifo; // fifo for srcids
 #endif
-
-      // Buffer between CAS fsm and INIT_RSP fsm (Decrement UPT entry)
-      sc_signal<bool>     r_cas_to_init_rsp_req;       // valid request
-      sc_signal<size_t>   r_cas_to_init_rsp_upt_index; // index in update table
 
       ////////////////////////////////////////////////////
@@ -742,13 +752,13 @@
                           r_xram_rsp_to_tgt_rsp_ll_key; // LL key returned by the llsc_global_table
 
-      // Buffer between XRAM_RSP fsm and INIT_CMD fsm (Inval L1 Caches)
-      sc_signal<bool>     r_xram_rsp_to_init_cmd_multi_req;     // Valid request
-      sc_signal<bool>     r_xram_rsp_to_init_cmd_brdcast_req;   // Broadcast request
-      sc_signal<addr_t>   r_xram_rsp_to_init_cmd_nline;         // cache line index;
-      sc_signal<size_t>   r_xram_rsp_to_init_cmd_trdid;         // index of UPT entry
-      GenericFifo<bool>   m_xram_rsp_to_init_cmd_inst_fifo;     // fifo for the L1 type
-      GenericFifo<size_t> m_xram_rsp_to_init_cmd_srcid_fifo;    // fifo for srcids
+      // Buffer between XRAM_RSP fsm and CC_SEND fsm (Inval L1 Caches)
+      sc_signal<bool>     r_xram_rsp_to_cc_send_multi_req;     // Valid request
+      sc_signal<bool>     r_xram_rsp_to_cc_send_brdcast_req;   // Broadcast request
+      sc_signal<addr_t>   r_xram_rsp_to_cc_send_nline;         // cache line index;
+      sc_signal<size_t>   r_xram_rsp_to_cc_send_trdid;         // index of UPT entry
+      GenericFifo<bool>   m_xram_rsp_to_cc_send_inst_fifo;     // fifo for the L1 type
+      GenericFifo<size_t> m_xram_rsp_to_cc_send_srcid_fifo;    // fifo for srcids
 #if L1_MULTI_CACHE
-      GenericFifo<size_t> m_xram_rsp_to_init_cmd_cache_id_fifo; // fifo for srcids
+      GenericFifo<size_t> m_xram_rsp_to_cc_send_cache_id_fifo; // fifo for srcids
 #endif
 
@@ -774,10 +784,16 @@
 
       ////////////////////////////////////////////////////
-      // Registers controlled by INIT_CMD fsm
-      ////////////////////////////////////////////////////
-
-      sc_signal<int>      r_init_cmd_fsm;
-      sc_signal<size_t>   r_init_cmd_cpt;
-      sc_signal<bool>     r_init_cmd_inst;
+      // Registers controlled by CC_SEND fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int>      r_cc_send_fsm;
+      sc_signal<size_t>   r_cc_send_cpt;
+      sc_signal<bool>     r_cc_send_inst;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by CC_RECEIVE fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int>      r_cc_receive_fsm;
 
       ////////////////////////////////////////////////////
Index: branches/v5/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp
===================================================================
--- branches/v5/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 346)
+++ branches/v5/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 351)
@@ -1,32 +1,33 @@
- /* -*- c++ -*-
- * File       : vci_mem_cache.cpp
- * Date       : 30/10/2008
- * Copyright  : UPMC / LIP6
- * Authors    : Alain Greiner / Eric Guthmuller
- *
- * SOCLIB_LGPL_HEADER_BEGIN
- *
- * This file is part of SoCLib, GNU LGPLv2.1.
- *
- * SoCLib is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; version 2.1 of the License.
- *
- * SoCLib is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with SoCLib; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- * SOCLIB_LGPL_HEADER_END
- *
- * Maintainers: alain eric.guthmuller@polytechnique.edu
- *              cesar.fuguet-tortolero@lip6.fr
- *              alexandre.joannou@lip6.fr
- */
+/* -*- c++ -*-
+*
+* File       : vci_mem_cache.cpp
+* Date       : 30/10/2008
+* Copyright  : UPMC / LIP6
+* Authors    : Alain Greiner / Eric Guthmuller
+*
+* SOCLIB_LGPL_HEADER_BEGIN
+*
+* This file is part of SoCLib, GNU LGPLv2.1.
+*
+* SoCLib is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as published
+* by the Free Software Foundation; version 2.1 of the License.
+*
+* SoCLib is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with SoCLib; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*
+* SOCLIB_LGPL_HEADER_END
+*
+* Maintainers: alain eric.guthmuller@polytechnique.edu
+*              cesar.fuguet-tortolero@lip6.fr
+*              alexandre.joannou@lip6.fr
+*/
 
 #include "../include/vci_mem_cache.h"
@@ -46,6 +47,6 @@
 #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 1 // detailed trace of INIT_CMD FSM
-#define DEBUG_MEMC_INIT_RSP 1 // detailed trace of INIT_RSP FSM
+#define DEBUG_MEMC_CC_SEND 1 // detailed trace of CC_SEND FSM
+#define DEBUG_MEMC_MULTI_ACK 1 // detailed trace of MULTI_ACK FSM
 #define DEBUG_MEMC_TGT_CMD  1 // detailed trace of TGT_CMD FSM
 #define DEBUG_MEMC_TGT_RSP  1 // detailed trace of TGT_RSP FSM
@@ -54,230 +55,260 @@
 #define RANDOMIZE_CAS       1
 
-namespace soclib { namespace caba {
-
-  const char *tgt_cmd_fsm_str[] = {
-    "TGT_CMD_IDLE",
-    "TGT_CMD_READ",
-    "TGT_CMD_WRITE",
-    "TGT_CMD_CAS"
-  };
-  const char *tgt_rsp_fsm_str[] = {
-    "TGT_RSP_READ_IDLE",
-    "TGT_RSP_WRITE_IDLE",
-    "TGT_RSP_CAS_IDLE",
-    "TGT_RSP_XRAM_IDLE",
-    "TGT_RSP_INIT_IDLE",
-    "TGT_RSP_CLEANUP_IDLE",
-    "TGT_RSP_READ",
-    "TGT_RSP_WRITE",
-    "TGT_RSP_CAS",
-    "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_CAS_UPDT_IDLE",
-    "INIT_CMD_CAS_BRDCAST",
-    "INIT_CMD_CAS_UPDT_NLINE",
-    "INIT_CMD_CAS_UPDT_INDEX",
-    "INIT_CMD_CAS_UPDT_DATA",
-    "INIT_CMD_CAS_UPDT_DATA_HIGH"
-  };
-  const char *init_rsp_fsm_str[] = {
-    "INIT_RSP_IDLE",
-    "INIT_RSP_UPT_LOCK",
-    "INIT_RSP_UPT_CLEAR",
-    "INIT_RSP_END"
-  };
-  const char *read_fsm_str[] = {
-    "READ_IDLE",
-    "READ_DIR_REQ",
-    "READ_DIR_LOCK",
-    "READ_DIR_HIT",
-    "READ_HEAP_REQ",
-    "READ_HEAP_LOCK",
-    "READ_HEAP_WRITE",
-    "READ_HEAP_ERASE",
-    "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_REQ",
-    "WRITE_DIR_LOCK",
-    "WRITE_DIR_READ",
-    "WRITE_DIR_HIT",
-    "WRITE_UPT_LOCK",
-    "WRITE_UPT_HEAP_LOCK",
-    "WRITE_UPT_REQ",
-    "WRITE_UPT_NEXT",
-    "WRITE_UPT_DEC",
-    "WRITE_RSP",
-    "WRITE_MISS_TRT_LOCK",
-    "WRITE_MISS_TRT_DATA",
-    "WRITE_MISS_TRT_SET",
-    "WRITE_MISS_XRAM_REQ",
-    "WRITE_BC_TRT_LOCK",
-    "WRITE_BC_UPT_LOCK",
-    "WRITE_BC_DIR_INVAL",
-    "WRITE_BC_CC_SEND",
-    "WRITE_BC_XRAM_REQ",
-    "WRITE_WAIT"
-  };
-  const char *ixr_rsp_fsm_str[] = {
-    "IXR_RSP_IDLE",
-    "IXR_RSP_ACK",
-    "IXR_RSP_TRT_ERASE",
-    "IXR_RSP_TRT_READ"
-  };
-  const char *xram_rsp_fsm_str[] = {
-    "XRAM_RSP_IDLE",
-    "XRAM_RSP_TRT_COPY",
-    "XRAM_RSP_TRT_DIRTY",
-    "XRAM_RSP_DIR_LOCK",
-    "XRAM_RSP_DIR_UPDT",
-    "XRAM_RSP_DIR_RSP",
-    "XRAM_RSP_INVAL_LOCK",
-    "XRAM_RSP_INVAL_WAIT",
-    "XRAM_RSP_INVAL",
-    "XRAM_RSP_WRITE_DIRTY",
-    "XRAM_RSP_HEAP_REQ",
-    "XRAM_RSP_HEAP_ERASE",
-    "XRAM_RSP_HEAP_LAST",
-    "XRAM_RSP_ERROR_ERASE",
-    "XRAM_RSP_ERROR_RSP"
-  };
-  const char *ixr_cmd_fsm_str[] = {
-    "IXR_CMD_READ_IDLE",
-    "IXR_CMD_WRITE_IDLE",
-    "IXR_CMD_CAS_IDLE",
-    "IXR_CMD_XRAM_IDLE",
-    "IXR_CMD_READ_NLINE",
-    "IXR_CMD_WRITE_NLINE",
-    "IXR_CMD_CAS_NLINE",
-    "IXR_CMD_XRAM_DATA"
-  };
-  const char *cas_fsm_str[] = {
-    "CAS_IDLE",
-    "CAS_DIR_REQ",
-    "CAS_DIR_LOCK",
-    "CAS_DIR_HIT_READ",
-    "CAS_DIR_HIT_COMPARE",
-    "CAS_DIR_HIT_WRITE",
-    "CAS_UPT_LOCK",
-    "CAS_UPT_HEAP_LOCK",
-    "CAS_UPT_REQ",
-    "CAS_UPT_NEXT",
-    "CAS_BC_TRT_LOCK",
-    "CAS_BC_UPT_LOCK",
-    "CAS_BC_DIR_INVAL",
-    "CAS_BC_CC_SEND",
-    "CAS_BC_XRAM_REQ",
-    "CAS_RSP_FAIL",
-    "CAS_RSP_SUCCESS",
-    "CAS_MISS_TRT_LOCK",
-    "CAS_MISS_TRT_SET",
-    "CAS_MISS_XRAM_REQ",
-    "CAS_WAIT"
-  };
-  const char *cleanup_fsm_str[] = {
-    "CLEANUP_IDLE",
-    "CLEANUP_DIR_REQ",
-    "CLEANUP_DIR_LOCK",
-    "CLEANUP_DIR_WRITE",
-    "CLEANUP_HEAP_REQ",
-    "CLEANUP_HEAP_LOCK",
-    "CLEANUP_HEAP_SEARCH",
-    "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_RESET",
-    "ALLOC_DIR_READ",
-    "ALLOC_DIR_WRITE",
-    "ALLOC_DIR_CAS",
-    "ALLOC_DIR_CLEANUP",
-    "ALLOC_DIR_XRAM_RSP"
-  };
-  const char *alloc_trt_fsm_str[] = {
-    "ALLOC_TRT_READ",
-    "ALLOC_TRT_WRITE",
-    "ALLOC_TRT_CAS",
-    "ALLOC_TRT_XRAM_RSP",
-    "ALLOC_TRT_IXR_RSP"
-  };
-  const char *alloc_upt_fsm_str[] = {
-    "ALLOC_UPT_WRITE",
-    "ALLOC_UPT_XRAM_RSP",
-    "ALLOC_UPT_INIT_RSP",
-    "ALLOC_UPT_CLEANUP",
-    "ALLOC_UPT_CAS"
-  };
-  const char *alloc_heap_fsm_str[] = {
-    "ALLOC_HEAP_RESET",
-    "ALLOC_HEAP_READ",
-    "ALLOC_HEAP_WRITE",
-    "ALLOC_HEAP_CAS",
-    "ALLOC_HEAP_CLEANUP",
-    "ALLOC_HEAP_XRAM_RSP"
-  };
-
-#define tmpl(x) template<typename vci_param> x VciMemCache<vci_param>
-
-  using soclib::common::uint32_log2;
-
-  ////////////////////////////////
-  //  Constructor
-  ////////////////////////////////
-
-  tmpl(/**/)::VciMemCache(
-      sc_module_name name,
-      const soclib::common::MappingTable &mtp,
-      const soclib::common::MappingTable &mtc,
-      const soclib::common::MappingTable &mtx,
-      const soclib::common::IntTab &vci_ixr_index,
-      const soclib::common::IntTab &vci_ini_index,
-      const soclib::common::IntTab &vci_tgt_index,
-      const soclib::common::IntTab &vci_tgt_index_cleanup,
-      size_t nways,                 // 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"),
-    p_resetn("resetn"),
-    p_vci_tgt("vci_tgt"),
-    p_vci_tgt_cleanup("vci_tgt_cleanup"),
-    p_vci_ini("vci_ini"),
-    p_vci_ixr("vci_ixr"),
-
-    m_seglist(mtp.getSegmentList(vci_tgt_index)),
-    m_cseglist(mtc.getSegmentList(vci_tgt_index_cleanup)),
-
+namespace soclib
+{
+namespace caba
+{
+
+const char *tgt_cmd_fsm_str[] =
+{
+  "TGT_CMD_IDLE",
+  "TGT_CMD_READ",
+  "TGT_CMD_WRITE",
+  "TGT_CMD_CAS"
+};
+const char *tgt_rsp_fsm_str[] =
+{
+  "TGT_RSP_READ_IDLE",
+  "TGT_RSP_WRITE_IDLE",
+  "TGT_RSP_CAS_IDLE",
+  "TGT_RSP_XRAM_IDLE",
+  "TGT_RSP_INIT_IDLE",
+  "TGT_RSP_CLEANUP_IDLE",
+  "TGT_RSP_READ",
+  "TGT_RSP_WRITE",
+  "TGT_RSP_CAS",
+  "TGT_RSP_XRAM",
+  "TGT_RSP_INIT",
+  "TGT_RSP_CLEANUP"
+};
+const char *cc_receive_fsm_str[] =
+{
+  "CC_RECEIVE_IDLE",
+  "CC_RECEIVE_CLEANUP",
+  "CC_RECEIVE_MULTI_ACK"
+};
+const char *cc_send_fsm_str[] =
+{
+  "CC_SEND_XRAM_RSP_IDLE",
+  "CC_SEND_WRITE_IDLE",
+  "CC_SEND_CAS_IDLE",
+  "CC_SEND_CLEANUP_IDLE",
+  "CC_SEND_CLEANUP_ACK",
+  "CC_SEND_XRAM_RSP_BRDCAST_HEADER",
+  "CC_SEND_XRAM_RSP_BRDCAST_NLINE",
+  "CC_SEND_XRAM_RSP_INVAL_HEADER",
+  "CC_SEND_XRAM_RSP_INVAL_NLINE",
+  "CC_SEND_WRITE_BRDCAST_HEADER",
+  "CC_SEND_WRITE_BRDCAST_NLINE",
+  "CC_SEND_WRITE_UPDT_HEADER",
+  "CC_SEND_WRITE_UPDT_NLINE",
+  "CC_SEND_WRITE_UPDT_DATA",
+  "CC_SEND_CAS_BRDCAST_HEADER",
+  "CC_SEND_CAS_BRDCAST_NLINE",
+  "CC_SEND_CAS_UPDT_HEADER",
+  "CC_SEND_CAS_UPDT_NLINE",
+  "CC_SEND_CAS_UPDT_DATA",
+  "CC_SEND_CAS_UPDT_DATA_HIGH"
+};
+const char *multi_ack_fsm_str[] =
+{
+  "MULTI_ACK_IDLE",
+  "MULTI_ACK_UPT_LOCK",
+  "MULTI_ACK_UPT_CLEAR",
+  "MULTI_ACK_WRITE_RSP"
+};
+const char *read_fsm_str[] =
+{
+  "READ_IDLE",
+  "READ_DIR_REQ",
+  "READ_DIR_LOCK",
+  "READ_DIR_HIT",
+  "READ_HEAP_REQ",
+  "READ_HEAP_LOCK",
+  "READ_HEAP_WRITE",
+  "READ_HEAP_ERASE",
+  "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_REQ",
+  "WRITE_DIR_LOCK",
+  "WRITE_DIR_READ",
+  "WRITE_DIR_HIT",
+  "WRITE_UPT_LOCK",
+  "WRITE_UPT_HEAP_LOCK",
+  "WRITE_UPT_REQ",
+  "WRITE_UPT_NEXT",
+  "WRITE_UPT_DEC",
+  "WRITE_RSP",
+  "WRITE_MISS_TRT_LOCK",
+  "WRITE_MISS_TRT_DATA",
+  "WRITE_MISS_TRT_SET",
+  "WRITE_MISS_XRAM_REQ",
+  "WRITE_BC_TRT_LOCK",
+  "WRITE_BC_UPT_LOCK",
+  "WRITE_BC_DIR_INVAL",
+  "WRITE_BC_CC_SEND",
+  "WRITE_BC_XRAM_REQ",
+  "WRITE_WAIT"
+};
+const char *ixr_rsp_fsm_str[] =
+{
+  "IXR_RSP_IDLE",
+  "IXR_RSP_ACK",
+  "IXR_RSP_TRT_ERASE",
+  "IXR_RSP_TRT_READ"
+};
+const char *xram_rsp_fsm_str[] =
+{
+  "XRAM_RSP_IDLE",
+  "XRAM_RSP_TRT_COPY",
+  "XRAM_RSP_TRT_DIRTY",
+  "XRAM_RSP_DIR_LOCK",
+  "XRAM_RSP_DIR_UPDT",
+  "XRAM_RSP_DIR_RSP",
+  "XRAM_RSP_INVAL_LOCK",
+  "XRAM_RSP_INVAL_WAIT",
+  "XRAM_RSP_INVAL",
+  "XRAM_RSP_WRITE_DIRTY",
+  "XRAM_RSP_HEAP_REQ",
+  "XRAM_RSP_HEAP_ERASE",
+  "XRAM_RSP_HEAP_LAST",
+  "XRAM_RSP_ERROR_ERASE",
+  "XRAM_RSP_ERROR_RSP"
+};
+const char *ixr_cmd_fsm_str[] =
+{
+  "IXR_CMD_READ_IDLE",
+  "IXR_CMD_WRITE_IDLE",
+  "IXR_CMD_CAS_IDLE",
+  "IXR_CMD_XRAM_IDLE",
+  "IXR_CMD_READ_NLINE",
+  "IXR_CMD_WRITE_NLINE",
+  "IXR_CMD_CAS_NLINE",
+  "IXR_CMD_XRAM_DATA"
+};
+const char *cas_fsm_str[] =
+{
+  "CAS_IDLE",
+  "CAS_DIR_REQ",
+  "CAS_DIR_LOCK",
+  "CAS_DIR_HIT_READ",
+  "CAS_DIR_HIT_COMPARE",
+  "CAS_DIR_HIT_WRITE",
+  "CAS_UPT_LOCK",
+  "CAS_UPT_HEAP_LOCK",
+  "CAS_UPT_REQ",
+  "CAS_UPT_NEXT",
+  "CAS_BC_TRT_LOCK",
+  "CAS_BC_UPT_LOCK",
+  "CAS_BC_DIR_INVAL",
+  "CAS_BC_CC_SEND",
+  "CAS_BC_XRAM_REQ",
+  "CAS_RSP_FAIL",
+  "CAS_RSP_SUCCESS",
+  "CAS_MISS_TRT_LOCK",
+  "CAS_MISS_TRT_SET",
+  "CAS_MISS_XRAM_REQ",
+  "CAS_WAIT"
+};
+const char *cleanup_fsm_str[] =
+{
+  "CLEANUP_IDLE",
+  "CLEANUP_GET_NLINE",
+  "CLEANUP_DIR_REQ",
+  "CLEANUP_DIR_LOCK",
+  "CLEANUP_DIR_WRITE",
+  "CLEANUP_HEAP_REQ",
+  "CLEANUP_HEAP_LOCK",
+  "CLEANUP_HEAP_SEARCH",
+  "CLEANUP_HEAP_CLEAN",
+  "CLEANUP_HEAP_FREE",
+  "CLEANUP_UPT_LOCK",
+  "CLEANUP_UPT_DECREMENT",
+  "CLEANUP_UPT_CLEAR",
+  "CLEANUP_WRITE_RSP",
+  "CLEANUP_SEND_ACK"
+};
+const char *alloc_dir_fsm_str[] =
+{
+  "ALLOC_DIR_RESET",
+  "ALLOC_DIR_READ",
+  "ALLOC_DIR_WRITE",
+  "ALLOC_DIR_CAS",
+  "ALLOC_DIR_CLEANUP",
+  "ALLOC_DIR_XRAM_RSP"
+};
+const char *alloc_trt_fsm_str[] =
+{
+  "ALLOC_TRT_READ",
+  "ALLOC_TRT_WRITE",
+  "ALLOC_TRT_CAS",
+  "ALLOC_TRT_XRAM_RSP",
+  "ALLOC_TRT_IXR_RSP"
+};
+const char *alloc_upt_fsm_str[] =
+{
+  "ALLOC_UPT_WRITE",
+  "ALLOC_UPT_XRAM_RSP",
+  "ALLOC_UPT_MULTI_ACK",
+  "ALLOC_UPT_CLEANUP",
+  "ALLOC_UPT_CAS"
+};
+const char *alloc_heap_fsm_str[] =
+{
+  "ALLOC_HEAP_RESET",
+  "ALLOC_HEAP_READ",
+  "ALLOC_HEAP_WRITE",
+  "ALLOC_HEAP_CAS",
+  "ALLOC_HEAP_CLEANUP",
+  "ALLOC_HEAP_XRAM_RSP"
+};
+
+#define tmpl(x) \
+  template<typename vci_param> x \
+  VciMemCache<vci_param>
+
+using namespace soclib::common;
+
+////////////////////////////////
+//  Constructor
+////////////////////////////////
+
+tmpl(/**/) ::VciMemCache(
+  sc_module_name      name,
+  const MappingTable  &mtp,              // mapping table for direct network
+  const MappingTable  &mtx,              // mapping table for external network
+  const IntTab        &srcid_x,          // global index on external network
+  const IntTab        &tgtid_d,          // global index on direct network
+  const size_t        cc_global_id,      // global index on cc network 
+  const size_t        nways,             // number of ways per set
+  const size_t        nsets,             // number of associative sets 
+  const size_t        nwords,            // number of words in cache line
+  const size_t        max_copies,        // max number of copies in heap
+  const size_t        heap_size,         // number of heap entries
+  const size_t        trt_lines,         // number of TRT entries
+  const size_t        upt_lines,         // number of UPT entries
+  const size_t        debug_start_cycle,
+  const bool          debug_ok)
+
+  : soclib::caba::BaseModule(name),
+
+    p_clk( "p_clk" ),
+    p_resetn( "p_resetn" ),
+    p_vci_tgt( "p_vci_tgt" ),
+    p_vci_ixr( "p_vci_ixr" ),
+    p_dspin_in( "p_dspin_in" ),
+    p_dspin_out( "p_dspin_out" ),
+
+    m_seglist( mtp.getSegmentList(tgtid_d) ),
+    m_nseg( 0 ),
+    m_srcid_x( mtx.indexForId(srcid_x) ),
     m_initiators( 1 << vci_param::S ),
     m_heap_size( heap_size ),
@@ -285,24 +316,29 @@
     m_sets( nsets ),
     m_words( nwords ),
-    m_srcid_ixr( mtx.indexForId(vci_ixr_index) ),
-    m_srcid_ini( mtc.indexForId(vci_ini_index) ),
-    m_transaction_tab_lines(transaction_tab_lines),
-    m_transaction_tab( transaction_tab_lines, nwords ),
-    m_update_tab_lines( update_tab_lines),
-    m_update_tab( update_tab_lines ),
-    m_cache_directory( nways, nsets, nwords, vci_param::N ),
-    m_cache_data( nways, nsets, nwords ),
-    m_heap( m_heap_size ),
+    m_cc_global_id( cc_global_id ),
+    m_debug_start_cycle( debug_start_cycle ),
+    m_debug_ok( debug_ok ),
+    m_trt_lines(trt_lines),
+    m_trt(trt_lines, nwords),
+    m_upt_lines(upt_lines),
+    m_upt(upt_lines),
+    m_cache_directory(nways, nsets, nwords, vci_param::N),
+    m_cache_data(nways, nsets, nwords),
+    m_heap(m_heap_size),
+    m_max_copies( max_copies ),
     m_llsc_table(),
 
 #define L2 soclib::common::uint32_log2
-    m_x( L2(m_words), 2),
-    m_y( L2(m_sets), L2(m_words) + 2),
-    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
-    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
+    m_x(L2(m_words), 2),
+    m_y(L2(m_sets), L2(m_words) + 2),
+    m_z(vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
+    m_nline(vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
 #undef L2
 
+    // XMIN(5 bits) / XMAX(5 bits) / YMIN(5 bits) / YMAX(5 bits)
+    //   0b00000    /   0b11111    /   0b00000    /   0b11111
+    m_broadcast_address(0x7C1F),
+
     //  FIFOs
-
     m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
     m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
@@ -326,28 +362,29 @@
     m_cmd_cas_wdata_fifo("m_cmd_cas_wdata_fifo",4),
 
+    m_cc_receive_to_cleanup_fifo("m_cc_receive_to_cleanup_fifo", 4),
+    m_cc_receive_to_multi_ack_fifo("m_cc_receive_to_multi_ack_fifo", 4),
+
     r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
 
-    m_nseg(0),
-    m_ncseg(0),
-
     r_read_fsm("r_read_fsm"),
 
     r_write_fsm("r_write_fsm"),
 
-    m_write_to_init_cmd_inst_fifo("m_write_to_init_cmd_inst_fifo",8),
-    m_write_to_init_cmd_srcid_fifo("m_write_to_init_cmd_srcid_fifo",8),
+    m_write_to_cc_send_inst_fifo("m_write_to_cc_send_inst_fifo",8),
+    m_write_to_cc_send_srcid_fifo("m_write_to_cc_send_srcid_fifo",8),
 #if L1_MULTI_CACHE
-    m_write_to_init_cmd_cache_id_fifo("m_write_to_init_cmd_cache_id_fifo",8),
-#endif
-
-    r_init_rsp_fsm("r_init_rsp_fsm"),
+    m_write_to_cc_send_cache_id_fifo("m_write_to_cc_send_cache_id_fifo",8),
+#endif
+
+    r_multi_ack_fsm("r_multi_ack_fsm"),
+
     r_cleanup_fsm("r_cleanup_fsm"),
 
     r_cas_fsm("r_cas_fsm"),
 
-    m_cas_to_init_cmd_inst_fifo("m_cas_to_init_cmd_inst_fifo",8),
-    m_cas_to_init_cmd_srcid_fifo("m_cas_to_init_cmd_srcid_fifo",8),
+    m_cas_to_cc_send_inst_fifo("m_cas_to_cc_send_inst_fifo",8),
+    m_cas_to_cc_send_srcid_fifo("m_cas_to_cc_send_srcid_fifo",8),
 #if L1_MULTI_CACHE
-    m_cas_to_init_cmd_cache_id_fifo("m_cas_to_init_cmd_cache_id_fifo",8),
+    m_cas_to_cc_send_cache_id_fifo("m_cas_to_cc_send_cache_id_fifo",8),
 #endif
 
@@ -355,8 +392,8 @@
     r_xram_rsp_fsm("r_xram_rsp_fsm"),
 
-    m_xram_rsp_to_init_cmd_inst_fifo("m_xram_rsp_to_init_cmd_inst_fifo",8),
-    m_xram_rsp_to_init_cmd_srcid_fifo("m_xram_rsp_to_init_cmd_srcid_fifo",8),
+    m_xram_rsp_to_cc_send_inst_fifo("m_xram_rsp_to_cc_send_inst_fifo",8),
+    m_xram_rsp_to_cc_send_srcid_fifo("m_xram_rsp_to_cc_send_srcid_fifo",8),
 #if L1_MULTI_CACHE
-    m_xram_rsp_to_init_cmd_cache_id_fifo("m_xram_rsp_to_init_cmd_cache_id_fifo",8),
+    m_xram_rsp_to_cc_send_cache_id_fifo("m_xram_rsp_to_cc_send_cache_id_fifo",8),
 #endif
 
@@ -365,5 +402,6 @@
     r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
 
-    r_init_cmd_fsm("r_init_cmd_fsm"),
+    r_cc_send_fsm("r_cc_send_fsm"),
+    r_cc_receive_fsm("r_cc_receive_fsm"),
 
     r_alloc_dir_fsm("r_alloc_dir_fsm"),
@@ -373,118 +411,115 @@
     r_alloc_heap_fsm("r_alloc_heap_fsm"),
     r_alloc_heap_reset_cpt("r_alloc_heap_reset_cpt")
-    {
-      assert(IS_POW_OF_2(nsets));
-      assert(IS_POW_OF_2(nwords));
-      assert(IS_POW_OF_2(nways));
-      assert(nsets);
-      assert(nwords);
-      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));
-
-      // Get the segments associated to the MemCache
-      std::list<soclib::common::Segment>::iterator seg;
-      size_t i;
-
-      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
+{
+    assert(IS_POW_OF_2(nsets));
+    assert(IS_POW_OF_2(nwords));
+    assert(IS_POW_OF_2(nways));
+    assert(nsets);
+    assert(nwords);
+    assert(nways);
+
+    // check Transaction table size
+    assert((uint32_log2(trt_lines) <= vci_param::T) and
+         "Need more bits for VCI TRDID field");
+
+    // Get the segments associated to the MemCache
+    std::list<soclib::common::Segment>::iterator seg;
+    size_t i = 0;
+
+    for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++)
+    {
         m_nseg++;
-      }
-      for(seg = m_cseglist.begin(); seg != m_cseglist.end() ; seg++) {
-        m_ncseg++;
-      }
-
-      m_seg = new soclib::common::Segment*[m_nseg];
-
-      i = 0;
-      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) {
-        m_seg[i] = &(*seg);
+    }
+
+    m_seg = new soclib::common::Segment*[m_nseg];
+
+    for(seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++)
+    {
+        m_seg[i] = & (*seg);
         i++;
-      }
-
-      m_cseg = new soclib::common::Segment*[m_ncseg];
-
-      i = 0;
-      for ( seg = m_cseglist.begin() ; seg != m_cseglist.end() ; seg++ ) {
-          m_cseg[i] = &(*seg);
-          i++;
-      }
-
-      // Allocation for IXR_RSP FSM
-      r_ixr_rsp_to_xram_rsp_rok   = new sc_signal<bool>[m_transaction_tab_lines];
-
-      // Allocation for XRAM_RSP FSM
-      r_xram_rsp_victim_data      = new sc_signal<data_t>[nwords];
-      r_xram_rsp_to_tgt_rsp_data  = new sc_signal<data_t>[nwords];
-      r_xram_rsp_to_ixr_cmd_data  = new sc_signal<data_t>[nwords];
-
-      // Allocation for READ FSM
-      r_read_data                 = new sc_signal<data_t>[nwords];
-      r_read_to_tgt_rsp_data      = new sc_signal<data_t>[nwords];
-
-      // Allocation for WRITE FSM
-      r_write_data                = new sc_signal<data_t>[nwords];
-      r_write_be                  = new sc_signal<be_t>[nwords];
-      r_write_to_init_cmd_data    = new sc_signal<data_t>[nwords];
-      r_write_to_init_cmd_be      = new sc_signal<be_t>[nwords];
-      r_write_to_ixr_cmd_data     = new sc_signal<data_t>[nwords];
-
-      // Allocation for CAS FSM
-      r_cas_to_ixr_cmd_data       = new sc_signal<data_t>[nwords];
-      r_cas_data                  = new sc_signal<data_t>[nwords];
-      r_cas_rdata                 = new sc_signal<data_t>[2];
-
-      // Simulation
-
-      SC_METHOD(transition);
-      dont_initialize();
-      sensitive << p_clk.pos();
-
-      SC_METHOD(genMoore);
-      dont_initialize();
-      sensitive << p_clk.neg();
-
-    } // end constructor
+    }
+
+    // Allocation for IXR_RSP FSM
+    r_ixr_rsp_to_xram_rsp_rok  = new sc_signal<bool>[m_trt_lines];
+
+    // Allocation for XRAM_RSP FSM
+    r_xram_rsp_victim_data     = new sc_signal<data_t>[nwords];
+    r_xram_rsp_to_tgt_rsp_data = new sc_signal<data_t>[nwords];
+    r_xram_rsp_to_ixr_cmd_data = new sc_signal<data_t>[nwords];
+
+    // Allocation for READ FSM
+    r_read_data                = new sc_signal<data_t>[nwords];
+    r_read_to_tgt_rsp_data     = new sc_signal<data_t>[nwords];
+
+    // Allocation for WRITE FSM
+    r_write_data               = new sc_signal<data_t>[nwords];
+    r_write_be                 = new sc_signal<be_t>[nwords];
+    r_write_to_cc_send_data    = new sc_signal<data_t>[nwords];
+    r_write_to_cc_send_be      = new sc_signal<be_t>[nwords];
+    r_write_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
+
+    // Allocation for CAS FSM
+    r_cas_to_ixr_cmd_data      = new sc_signal<data_t>[nwords];
+    r_cas_data                 = new sc_signal<data_t>[nwords];
+    r_cas_rdata                = new sc_signal<data_t>[2];
+
+
+    SC_METHOD(transition);
+    dont_initialize();
+    sensitive << p_clk.pos();
+
+    SC_METHOD(genMoore);
+    dont_initialize();
+    sensitive << p_clk.neg();
+} // end constructor
 
 ///////////////////////////////////////////////////////////////////////
-tmpl(void)::start_monitor( vci_addr_t addr, vci_addr_t length )
+tmpl(void) ::start_monitor(vci_addr_t addr, vci_addr_t length)
 ///////////////////////////////////////////////////////////////////////
 {
-    m_monitor_ok        = true;
-    m_monitor_base      = addr;
-    m_monitor_length    = length;
+  m_monitor_ok        = true;
+  m_monitor_base      = addr;
+  m_monitor_length    = length;
 }
 
 ///////////////////////////////////////////////////////////////////////
-tmpl(void)::stop_monitor()
+tmpl(void) ::stop_monitor()
 ///////////////////////////////////////////////////////////////////////
 {
-    m_monitor_ok        = false;
+  m_monitor_ok        = false;
 }
 
 ///////////////////////////////////////////////////////////////////////
-tmpl(void)::check_monitor( const char *buf, vci_addr_t addr, data_t data )
+tmpl(void) ::check_monitor(const char *buf, vci_addr_t addr, data_t data)
 ///////////////////////////////////////////////////////////////////////
 {
-    if ( (addr >= m_monitor_base) and
-         (addr < m_monitor_base + m_monitor_length) )
-    {
-        std::cout << " MEMC Write Monitor : " << buf << " Address = " << std::hex << addr
-                  << " / Data = " << data << std::endl;
-    }
+  if((addr >= m_monitor_base) and
+      (addr < m_monitor_base + m_monitor_length))
+  {
+    std::cout << " MEMC Write Monitor : " << buf << " Address = " << std::hex << addr
+              << " / Data = " << data << " at cycle " << std::dec << m_cpt_cycles << std::endl;
+  }
 }
 
+///////////////////////////////////////////////////////////////////////
+tmpl(void) ::check_monitor_read(const char *buf, vci_addr_t addr)
+///////////////////////////////////////////////////////////////////////
+{
+  if((addr >= m_monitor_base) and
+      (addr < m_monitor_base + m_monitor_length))
+  {
+    std::cout << " MEMC Read Monitor : " << buf << " Address = " << std::hex << addr
+              << std::endl;
+  }
+}
+
 /////////////////////////////////////////////////////
-tmpl(void)::copies_monitor( vci_addr_t addr )
+tmpl(void) ::copies_monitor(vci_addr_t addr)
 /////////////////////////////////////////////////////
 {
-    DirectoryEntry entry = m_cache_directory.read_neutral(addr);
-    if ( (entry.count != m_debug_previous_count) or
-         (entry.valid != m_debug_previous_hit) )
-    {
+  DirectoryEntry entry = m_cache_directory.read_neutral(addr);
+  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
@@ -492,79 +527,80 @@
               << " / HIT = " << entry.valid
               << " / COUNT = " << std::dec << entry.count << std::endl;
-    }
-    m_debug_previous_count = entry.count;
-    m_debug_previous_hit = entry.valid;
+  }
+  m_debug_previous_count = entry.count;
+  m_debug_previous_hit = entry.valid;
 }
 
 //////////////////////////////////////////////////
-tmpl(void)::print_trace()
+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]
-              << " | " << cas_fsm_str[r_cas_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;
-
-              //m_llsc_table.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]
+            << " | " << cas_fsm_str[r_cas_fsm]
+            << " | " << cleanup_fsm_str[r_cleanup_fsm] << std::endl;
+  std::cout << "  "  << cc_send_fsm_str[r_cc_send_fsm]
+            << " | " << cc_receive_fsm_str[r_cc_receive_fsm]
+            << " | " << multi_ack_fsm_str[r_multi_ack_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;
+
+  //m_llsc_table.print_trace();
 
 }
 
 /////////////////////////////////////////
-tmpl(void)::print_stats()
+tmpl(void) ::print_stats()
 /////////////////////////////////////////
 {
   std::cout << "----------------------------------" << std::dec << std::endl;
   std::cout
-    << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
-    << "- READ RATE            = " << (double) m_cpt_read/m_cpt_cycles << std::endl
-    << "- READ TOTAL           = " << m_cpt_read << std::endl
-    << "- READ MISS RATE       = " << (double) m_cpt_read_miss/m_cpt_read << std::endl
-    << "- WRITE RATE           = " << (double) m_cpt_write/m_cpt_cycles << std::endl
-    << "- WRITE TOTAL          = " << m_cpt_write << std::endl
-    << "- WRITE MISS RATE      = " << (double) m_cpt_write_miss/m_cpt_write << std::endl
-    << "- WRITE BURST LENGTH   = " << (double) m_cpt_write_cells/m_cpt_write << std::endl
-    << "- WRITE BURST TOTAL    = " << m_cpt_write_cells << std::endl
-    << "- REQUESTS TRT FULL    = " << m_cpt_trt_full << std::endl
-    << "- READ TRT BLOKED HIT  = " << m_cpt_trt_rb << std::endl
-    << "- UPDATE RATE          = " << (double) m_cpt_update/m_cpt_cycles << std::endl
-    << "- UPDATE ARITY         = " << (double) m_cpt_update_mult/m_cpt_update << std::endl
-    << "- INVAL MULTICAST RATE = " << (double) (m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
-    << "- INVAL MULTICAST ARITY= " << (double) m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
-    << "- INVAL BROADCAST RATE = " << (double) m_cpt_inval_brdcast/m_cpt_cycles << std::endl
-    << "- SAVE DIRTY RATE      = " << (double) m_cpt_write_dirty/m_cpt_cycles << std::endl
-    << "- CLEANUP RATE         = " << (double) m_cpt_cleanup/m_cpt_cycles << std::endl
-    << "- LL RATE              = " << (double) m_cpt_ll/m_cpt_cycles << std::endl
-    << "- SC RATE              = " << (double) m_cpt_sc/m_cpt_cycles << std::endl
-    << "- CAS RATE             = " << (double) m_cpt_cas/m_cpt_cycles << std::endl;
+      << "MEM_CACHE " << name() << " / Time = " << m_cpt_cycles << std::endl
+      << "- READ RATE            = " << (double) m_cpt_read/m_cpt_cycles << std::endl
+      << "- READ TOTAL           = " << m_cpt_read << std::endl
+      << "- READ MISS RATE       = " << (double) m_cpt_read_miss/m_cpt_read << std::endl
+      << "- WRITE RATE           = " << (double) m_cpt_write/m_cpt_cycles << std::endl
+      << "- WRITE TOTAL          = " << m_cpt_write << std::endl
+      << "- WRITE MISS RATE      = " << (double) m_cpt_write_miss/m_cpt_write << std::endl
+      << "- WRITE BURST LENGTH   = " << (double) m_cpt_write_cells/m_cpt_write << std::endl
+      << "- WRITE BURST TOTAL    = " << m_cpt_write_cells << std::endl
+      << "- REQUESTS TRT FULL    = " << m_cpt_trt_full << std::endl
+      << "- READ TRT BLOKED HIT  = " << m_cpt_trt_rb << std::endl
+      << "- UPDATE RATE          = " << (double) m_cpt_update/m_cpt_cycles << std::endl
+      << "- UPDATE ARITY         = " << (double) m_cpt_update_mult/m_cpt_update << std::endl
+      << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast) /m_cpt_cycles << std::endl
+      << "- INVAL MULTICAST ARITY= " << (double) m_cpt_inval_mult/ (m_cpt_inval-m_cpt_inval_brdcast) << std::endl
+      << "- INVAL BROADCAST RATE = " << (double) m_cpt_inval_brdcast/m_cpt_cycles << std::endl
+      << "- SAVE DIRTY RATE      = " << (double) m_cpt_write_dirty/m_cpt_cycles << std::endl
+      << "- CLEANUP RATE         = " << (double) m_cpt_cleanup/m_cpt_cycles << std::endl
+      << "- LL RATE              = " << (double) m_cpt_ll/m_cpt_cycles << std::endl
+      << "- SC RATE              = " << (double) m_cpt_sc/m_cpt_cycles << std::endl
+      << "- CAS RATE             = " << (double) m_cpt_cas/m_cpt_cycles << std::endl;
 }
 
-  /////////////////////////////////
-  tmpl(/**/)::~VciMemCache()
-    /////////////////////////////////
-  {
-    delete [] r_ixr_rsp_to_xram_rsp_rok;
-
-    delete [] r_xram_rsp_victim_data;
-    delete [] r_xram_rsp_to_tgt_rsp_data;
-    delete [] r_xram_rsp_to_ixr_cmd_data;
-
-    delete [] r_read_data;
-    delete [] r_read_to_tgt_rsp_data;
-
-    delete [] r_write_data;
-    delete [] r_write_be;
-    delete [] r_write_to_init_cmd_data;
-  }
+/////////////////////////////////
+tmpl(/**/) ::~VciMemCache()
+/////////////////////////////////
+{
+  delete [] r_ixr_rsp_to_xram_rsp_rok;
+
+  delete [] r_xram_rsp_victim_data;
+  delete [] r_xram_rsp_to_tgt_rsp_data;
+  delete [] r_xram_rsp_to_ixr_cmd_data;
+
+  delete [] r_read_data;
+  delete [] r_read_to_tgt_rsp_data;
+
+  delete [] r_write_data;
+  delete [] r_write_be;
+  delete [] r_write_to_cc_send_data;
+}
 
 //////////////////////////////////
-tmpl(void)::transition()
+tmpl(void) ::transition()
 //////////////////////////////////
 {
@@ -572,11 +608,13 @@
 
   // RESET
-  if ( ! p_resetn.read() ) {
+  if(! p_resetn.read())
+  {
 
     // Initializing FSMs
     r_tgt_cmd_fsm    = TGT_CMD_IDLE;
     r_tgt_rsp_fsm    = TGT_RSP_READ_IDLE;
-    r_init_cmd_fsm   = INIT_CMD_INVAL_IDLE;
-    r_init_rsp_fsm   = INIT_RSP_IDLE;
+    r_cc_send_fsm    = CC_SEND_XRAM_RSP_IDLE;
+    r_cc_receive_fsm = CC_RECEIVE_IDLE;
+    r_multi_ack_fsm  = MULTI_ACK_IDLE;
     r_read_fsm       = READ_IDLE;
     r_write_fsm      = WRITE_IDLE;
@@ -594,6 +632,7 @@
     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_cc_send_fsm  = false;
+    m_debug_cc_receive_fsm  = false;
+    m_debug_multi_ack_fsm  = false;
     m_debug_read_fsm       = false;
     m_debug_write_fsm      = false;
@@ -607,6 +646,6 @@
 
     //  Initializing Tables
-    m_transaction_tab.init();
-    m_update_tab.init();
+    m_trt.init();
+    m_upt.init();
     m_llsc_table.init();
 
@@ -638,17 +677,21 @@
     r_write_to_tgt_rsp_req          = false;
     r_write_to_ixr_cmd_req          = false;
-    r_write_to_init_cmd_multi_req   = false;
-    r_write_to_init_cmd_brdcast_req = false;
-    r_write_to_init_rsp_req         = false;
-
-    m_write_to_init_cmd_inst_fifo.init();
-    m_write_to_init_cmd_srcid_fifo.init();
+    r_write_to_cc_send_multi_req   = false;
+    r_write_to_cc_send_brdcast_req = false;
+    r_write_to_multi_ack_req        = false;
+
+    m_write_to_cc_send_inst_fifo.init();
+    m_write_to_cc_send_srcid_fifo.init();
 #if L1_MULTI_CACHE
-    m_write_to_init_cmd_cache_id_fifo.init();
+    m_write_to_cc_send_cache_id_fifo.init();
 #endif
 
     r_cleanup_to_tgt_rsp_req      = false;
 
-    r_init_rsp_to_tgt_rsp_req     = false;
+    m_cc_receive_to_cleanup_fifo.init();
+
+    r_multi_ack_to_tgt_rsp_req     = false;
+
+    m_cc_receive_to_multi_ack_fifo.init();
 
     r_cas_to_tgt_rsp_req          = false;
@@ -656,27 +699,28 @@
     r_cas_lfsr                    = -1   ;
     r_cas_to_ixr_cmd_req          = false;
-    r_cas_to_init_cmd_multi_req   = false;
-    r_cas_to_init_cmd_brdcast_req = false;
-
-    m_cas_to_init_cmd_inst_fifo.init();
-    m_cas_to_init_cmd_srcid_fifo.init();
+    r_cas_to_cc_send_multi_req   = false;
+    r_cas_to_cc_send_brdcast_req = false;
+
+    m_cas_to_cc_send_inst_fifo.init();
+    m_cas_to_cc_send_srcid_fifo.init();
 #if L1_MULTI_CACHE
-    m_cas_to_init_cmd_cache_id_fifo.init();
-#endif
-
-    for(size_t i=0; i<m_transaction_tab_lines ; i++){
+    m_cas_to_cc_send_cache_id_fifo.init();
+#endif
+
+    for(size_t i=0; i<m_trt_lines ; i++)
+    {
       r_ixr_rsp_to_xram_rsp_rok[i] = false;
     }
 
     r_xram_rsp_to_tgt_rsp_req          = false;
-    r_xram_rsp_to_init_cmd_multi_req   = false;
-    r_xram_rsp_to_init_cmd_brdcast_req = false;
+    r_xram_rsp_to_cc_send_multi_req   = false;
+    r_xram_rsp_to_cc_send_brdcast_req = false;
     r_xram_rsp_to_ixr_cmd_req          = false;
     r_xram_rsp_trt_index               = 0;
 
-    m_xram_rsp_to_init_cmd_inst_fifo.init();
-    m_xram_rsp_to_init_cmd_srcid_fifo.init();
+    m_xram_rsp_to_cc_send_inst_fifo.init();
+    m_xram_rsp_to_cc_send_srcid_fifo.init();
 #if L1_MULTI_CACHE
-    m_xram_rsp_to_init_cmd_cache_id_fifo.init();
+    m_xram_rsp_to_cc_send_cache_id_fifo.init();
 #endif
 
@@ -684,6 +728,4 @@
     r_alloc_dir_reset_cpt  = 0;
     r_alloc_heap_reset_cpt = 0;
-
-    r_copies_limit         = 3;
 
     // Activity counters
@@ -719,65 +761,74 @@
   bool    cmd_cas_fifo_get = false;
 
-  bool    write_to_init_cmd_fifo_put   = false;
-  bool    write_to_init_cmd_fifo_get   = false;
-  bool    write_to_init_cmd_fifo_inst  = false;
-  size_t  write_to_init_cmd_fifo_srcid = 0;
+  bool    cc_receive_to_cleanup_fifo_get = false;
+  bool    cc_receive_to_cleanup_fifo_put = false;
+   
+  bool    cc_receive_to_multi_ack_fifo_get = false;
+  bool    cc_receive_to_multi_ack_fifo_put = false;
+
+  bool    write_to_cc_send_fifo_put   = false;
+  bool    write_to_cc_send_fifo_get   = false;
+  bool    write_to_cc_send_fifo_inst  = false;
+  size_t  write_to_cc_send_fifo_srcid = 0;
 
 #if L1_MULTI_CACHE
-  size_t  write_to_init_cmd_fifo_cache_id = 0;
-#endif
-
-  bool    xram_rsp_to_init_cmd_fifo_put   = false;
-  bool    xram_rsp_to_init_cmd_fifo_get   = false;
-  bool    xram_rsp_to_init_cmd_fifo_inst  = false;
-  size_t  xram_rsp_to_init_cmd_fifo_srcid = 0;
+  size_t  write_to_cc_send_fifo_cache_id = 0;
+#endif
+
+  bool    xram_rsp_to_cc_send_fifo_put   = false;
+  bool    xram_rsp_to_cc_send_fifo_get   = false;
+  bool    xram_rsp_to_cc_send_fifo_inst  = false;
+  size_t  xram_rsp_to_cc_send_fifo_srcid = 0;
 
 #if L1_MULTI_CACHE
-  size_t  xram_rsp_to_init_cmd_fifo_cache_id = 0;
-#endif
-
-  bool    cas_to_init_cmd_fifo_put   = false;
-  bool    cas_to_init_cmd_fifo_get   = false;
-  bool    cas_to_init_cmd_fifo_inst  = false;
-  size_t  cas_to_init_cmd_fifo_srcid = 0;
+  size_t  xram_rsp_to_cc_send_fifo_cache_id = 0;
+#endif
+
+  bool    cas_to_cc_send_fifo_put   = false;
+  bool    cas_to_cc_send_fifo_get   = false;
+  bool    cas_to_cc_send_fifo_inst  = false;
+  size_t  cas_to_cc_send_fifo_srcid = 0;
 
 #if L1_MULTI_CACHE
-  size_t  cas_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_cas_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;
+  size_t  cas_to_cc_send_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_cc_send_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+  m_debug_cc_receive_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
+  m_debug_multi_ack_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_cas_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 )
+  if(m_debug_global)
   {
     std::cout
-      << "---------------------------------------------" << std::dec << std::endl
-      << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
-      << " - TGT_CMD FSM    = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
-      << " - TGT_RSP FSM    = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
-      << " - INIT_CMD FSM   = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
-      << " - INIT_RSP FSM   = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
-      << " - READ FSM       = " << read_fsm_str[r_read_fsm] << std::endl
-      << " - WRITE FSM      = " << write_fsm_str[r_write_fsm] << std::endl
-      << " - CAS FSM        = " << cas_fsm_str[r_cas_fsm] << std::endl
-      << " - CLEANUP FSM    = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
-      << " - IXR_CMD FSM    = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
-      << " - IXR_RSP FSM    = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
-      << " - XRAM_RSP FSM   = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
-      << " - ALLOC_DIR FSM  = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
-      << " - ALLOC_TRT FSM  = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
-      << " - ALLOC_UPT FSM  = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl
-      << " - ALLOC_HEAP FSM = " << alloc_heap_fsm_str[r_alloc_heap_fsm] << std::endl;
+        << "---------------------------------------------"           << std::dec << std::endl
+        << "MEM_CACHE "            << name() 
+        << " ; Time = "            << m_cpt_cycles                                << std::endl
+        << " - TGT_CMD FSM    = "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]       << std::endl
+        << " - TGT_RSP FSM    = "  << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]       << std::endl
+        << " - CC_SEND FSM  = "    << cc_send_fsm_str[r_cc_send_fsm.read()]       << std::endl
+        << " - CC_RECEIVE FSM  = " << cc_receive_fsm_str[r_cc_receive_fsm.read()] << std::endl
+        << " - MULTI_ACK FSM  = "  << multi_ack_fsm_str[r_multi_ack_fsm.read()]   << std::endl
+        << " - READ FSM       = "  << read_fsm_str[r_read_fsm.read()]             << std::endl
+        << " - WRITE FSM      = "  << write_fsm_str[r_write_fsm.read()]           << std::endl
+        << " - CAS FSM        = "  << cas_fsm_str[r_cas_fsm.read()]               << std::endl
+        << " - CLEANUP FSM    = "  << cleanup_fsm_str[r_cleanup_fsm.read()]       << std::endl
+        << " - IXR_CMD FSM    = "  << ixr_cmd_fsm_str[r_ixr_cmd_fsm.read()]       << std::endl
+        << " - IXR_RSP FSM    = "  << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]       << std::endl
+        << " - XRAM_RSP FSM   = "  << xram_rsp_fsm_str[r_xram_rsp_fsm.read()]     << std::endl
+        << " - ALLOC_DIR FSM  = "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]   << std::endl
+        << " - ALLOC_TRT FSM  = "  << alloc_trt_fsm_str[r_alloc_trt_fsm.read()]   << std::endl
+        << " - ALLOC_UPT FSM  = "  << alloc_upt_fsm_str[r_alloc_upt_fsm.read()]   << std::endl
+        << " - ALLOC_HEAP FSM = "  << alloc_heap_fsm_str[r_alloc_heap_fsm.read()] << std::endl;
   }
 #endif
@@ -799,18 +850,21 @@
   ////////////////////////////////////////////////////////////////////////////////////
 
-  switch ( r_tgt_cmd_fsm.read() )
+  switch(r_tgt_cmd_fsm.read())
   {
-    //////////////////
+      //////////////////
     case TGT_CMD_IDLE:
-      if ( p_vci_tgt.cmdval )
+      if(p_vci_tgt.cmdval)
       {
 
 #if DEBUG_MEMC_TGT_CMD
-        if( m_debug_tgt_cmd_fsm )
+        if(m_debug_tgt_cmd_fsm)
         {
           std::cout
-            << "  <MEMC " << name() << ".TGT_CMD_IDLE> Receive command from srcid "
-            << std::dec << p_vci_tgt.srcid.read()
-            << " / for address " << std::hex << p_vci_tgt.address.read() << std::endl;
+              << "  <MEMC " << name()
+              << ".TGT_CMD_IDLE> Receive command from srcid "
+              << std::dec << p_vci_tgt.srcid.read()
+              << " / for address "
+              << std::hex << p_vci_tgt.address.read()
+              << std::endl;
         }
 #endif
@@ -819,23 +873,23 @@
         uint32_t    plen    = p_vci_tgt.plen.read();
         bool found = false;
-        for ( size_t seg_id = 0 ; seg_id < m_nseg ; seg_id++ )
-        {
-          if ( m_seg[seg_id]->contains(address) &&
-              m_seg[seg_id]->contains(address + plen - vci_param::B) )
+        for(size_t seg_id = 0 ; seg_id < m_nseg ; seg_id++)
+        {
+          if(m_seg[seg_id]->contains(address) &&
+              m_seg[seg_id]->contains(address + plen - vci_param::B))
           {
             found = true;
           }
         }
-        if ( not found )
+        if(not found)
         {
           std::cout << "VCI_MEM_CACHE ERROR " << name() << std::endl;
           std::cout
-            << "Out of segment VCI address in TGT_CMD_IDLE state (address = "
-            << std::hex << address << ", srcid = " << p_vci_tgt.srcid.read()
-            << std::dec << ", cycle = " << m_cpt_cycles << ")" << std::endl;
+              << "Out of segment VCI address in TGT_CMD_IDLE state (address = "
+              << std::hex << address << ", srcid = " << p_vci_tgt.srcid.read()
+              << std::dec << ", cycle = " << m_cpt_cycles << ")" << std::endl;
           exit(0);
         }
 
-        if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ )
+        if(p_vci_tgt.cmd.read() == vci_param::CMD_READ)
         {
           // check that the pktid is either :
@@ -847,8 +901,8 @@
           // ==> mask = 0b0100 = 0x4
           assert(((p_vci_tgt.pktid.read() & 0x4) == 0x0) &&
-            "The type specified in the pktid field is incompatible with the READ CMD");
+                 "The type specified in the pktid field is incompatible with the READ CMD");
           r_tgt_cmd_fsm = TGT_CMD_READ;
         }
-        else if ( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE )
+        else if(p_vci_tgt.cmd.read() == vci_param::CMD_WRITE)
         {
           // check that the pktid is TYPE_WRITE
@@ -856,8 +910,8 @@
           // ==> mask = 0b0111 = 0x7
           assert(((p_vci_tgt.pktid.read() & 0x7) == 0x4) &&
-            "The type specified in the pktid field is incompatible with the WRITE CMD");
+                 "The type specified in the pktid field is incompatible with the WRITE CMD");
           r_tgt_cmd_fsm = TGT_CMD_WRITE;
         }
-        else if ( p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ )
+        else if(p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ)
         {
           // check that the pktid is TYPE_LL
@@ -865,8 +919,8 @@
           // ==> mask = 0b0111 = 0x7
           assert(((p_vci_tgt.pktid.read() & 0x7) == 0x6) &&
-            "The type specified in the pktid field is incompatible with the LL CMD");
+                 "The type specified in the pktid field is incompatible with the LL CMD");
           r_tgt_cmd_fsm = TGT_CMD_READ;
         }
-        else if ( p_vci_tgt.cmd.read() == vci_param::CMD_NOP )
+        else if(p_vci_tgt.cmd.read() == vci_param::CMD_NOP)
         {
           // check that the pktid is either :
@@ -876,6 +930,6 @@
           // ==> TYPE_SC  = X111 with the TSAR encoding
           // ==> mask = 0b0101 = 0x5
-          assert(((p_vci_tgt.pktid.read() & 0x5) == 0x5 ) &&
-            "The type specified in the pktid field is incompatible with the NOP CMD");
+          assert(((p_vci_tgt.pktid.read() & 0x5) == 0x5) &&
+                 "The type specified in the pktid field is incompatible with the NOP CMD");
 
           if((p_vci_tgt.pktid.read() & 0x7) == TYPE_CAS)
@@ -887,5 +941,5 @@
         {
           std::cout << "VCI_MEM_CACHE ERROR " << name()
-            << " TGT_CMD_IDLE state" << std::endl;
+                    << " TGT_CMD_IDLE state" << std::endl;
           std::cout << " illegal VCI command type" << std::endl;
           exit(0);
@@ -894,25 +948,25 @@
       break;
 
-    //////////////////
+      //////////////////
     case TGT_CMD_READ:
       // This test checks that the read does not cross a cache line limit.
       // It must not be taken into account when dealing with an LL CMD.
-      if (((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2)) > 16) && ( p_vci_tgt.cmd.read() != vci_param::CMD_LOCKED_READ ))
+      if(((m_x[(vci_addr_t) p_vci_tgt.address.read()]+ (p_vci_tgt.plen.read() >>2)) > 16) && (p_vci_tgt.cmd.read() != vci_param::CMD_LOCKED_READ))
       {
         std::cout
-          << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
-          << std::endl;
+            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
+            << std::endl;
         std::cout
-          << " illegal address/plen combination for VCI read command" << std::endl;
+            << " illegal address/plen combination for VCI read command" << std::endl;
         exit(0);
       }
-      if ( !p_vci_tgt.eop.read() )
+      if(!p_vci_tgt.eop.read())
       {
         std::cout
-          << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
-          << std::endl;
+            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
+            << std::endl;
         std::cout
-          << " read or ll command packets must contain one single flit"
-          << std::endl;
+            << " read or ll command packets must contain one single flit"
+            << std::endl;
         exit(0);
       }
@@ -928,20 +982,20 @@
       }
 
-      if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() )
+      if(p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok())
       {
 
 #if DEBUG_MEMC_TGT_CMD
-        if( m_debug_tgt_cmd_fsm )
+        if(m_debug_tgt_cmd_fsm)
         {
           std::cout << "  <MEMC " << name() << ".TGT_CMD_READ> Push into read_fifo:"
-            << " address = " << std::hex << p_vci_tgt.address.read()
-            << " srcid = " << std::dec << p_vci_tgt.srcid.read()
-            << " trdid = " << p_vci_tgt.trdid.read()
-            << " pktid = " << p_vci_tgt.pktid.read()
-            << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
+                    << " address = " << std::hex << p_vci_tgt.address.read()
+                    << " srcid = " << std::dec << p_vci_tgt.srcid.read()
+                    << " trdid = " << p_vci_tgt.trdid.read()
+                    << " pktid = " << p_vci_tgt.pktid.read()
+                    << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
         }
 #endif
         cmd_read_fifo_put = true;
-        if ( p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ )
+        if(p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ)
           m_cpt_ll++;
         else
@@ -951,57 +1005,57 @@
       break;
 
-    ///////////////////
+      ///////////////////
     case TGT_CMD_WRITE:
-      if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() )
+      if(p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok())
       {
 
 #if DEBUG_MEMC_TGT_CMD
-        if( m_debug_tgt_cmd_fsm )
+        if(m_debug_tgt_cmd_fsm)
         {
           std::cout << "  <MEMC " << name() << ".TGT_CMD_WRITE> Push into write_fifo:"
-            << " address = " << std::hex << p_vci_tgt.address.read()
-            << " srcid = " << std::dec << p_vci_tgt.srcid.read()
-            << " trdid = " << p_vci_tgt.trdid.read()
-            << " pktid = " << p_vci_tgt.pktid.read()
-            << " wdata = " << std::hex << p_vci_tgt.wdata.read()
-            << " be = " << p_vci_tgt.be.read()
-            << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
+                    << " address = " << std::hex << p_vci_tgt.address.read()
+                    << " srcid = " << std::dec << p_vci_tgt.srcid.read()
+                    << " trdid = " << p_vci_tgt.trdid.read()
+                    << " pktid = " << p_vci_tgt.pktid.read()
+                    << " wdata = " << std::hex << p_vci_tgt.wdata.read()
+                    << " be = " << p_vci_tgt.be.read()
+                    << " plen = " << std::dec << 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;
-
-    ////////////////////
+        if(p_vci_tgt.eop)  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+      }
+      break;
+
+      ////////////////////
     case TGT_CMD_CAS:
-      if ( (p_vci_tgt.plen.read() != 8) && (p_vci_tgt.plen.read() != 16) )
+      if((p_vci_tgt.plen.read() != 8) && (p_vci_tgt.plen.read() != 16))
       {
         std::cout
-          << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_CAS state"
-          << std::endl
-          << "illegal format for CAS command " << std::endl;
+            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_CAS state"
+            << std::endl
+            << "illegal format for CAS command " << std::endl;
 
         exit(0);
       }
 
-      if ( p_vci_tgt.cmdval && m_cmd_cas_addr_fifo.wok() )
+      if(p_vci_tgt.cmdval && m_cmd_cas_addr_fifo.wok())
       {
 
 #if DEBUG_MEMC_TGT_CMD
-        if( m_debug_tgt_cmd_fsm )
+        if(m_debug_tgt_cmd_fsm)
         {
           std::cout << "  <MEMC " << name() << ".TGT_CMD_CAS> Pushing command into cmd_cas_fifo:"
-            << " address = " << std::hex << p_vci_tgt.address.read()
-            << " srcid = " << std::dec << p_vci_tgt.srcid.read()
-            << " trdid = " << p_vci_tgt.trdid.read()
-            << " pktid = " << p_vci_tgt.pktid.read()
-            << " wdata = " << std::hex << p_vci_tgt.wdata.read()
-            << " be = " << p_vci_tgt.be.read()
-            << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
+                    << " address = " << std::hex << p_vci_tgt.address.read()
+                    << " srcid = " << std::dec << p_vci_tgt.srcid.read()
+                    << " trdid = " << p_vci_tgt.trdid.read()
+                    << " pktid = " << p_vci_tgt.pktid.read()
+                    << " wdata = " << std::hex << p_vci_tgt.wdata.read()
+                    << " be = " << p_vci_tgt.be.read()
+                    << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
         }
 #endif
         cmd_cas_fifo_put = true;
-        if( p_vci_tgt.eop ) r_tgt_cmd_fsm = TGT_CMD_IDLE;
+        if(p_vci_tgt.eop) r_tgt_cmd_fsm = TGT_CMD_IDLE;
       }
       break;
@@ -1009,10 +1063,11 @@
 
   /////////////////////////////////////////////////////////////////////////
-  //    INIT_RSP FSM
+  //    MULTI_ACK FSM
   /////////////////////////////////////////////////////////////////////////
-  // This FSM controls the response to the update or inval coherence
-  // requests sent by the memory cache to the L1 caches and update the UPT.
+  // This FSM controls the response to the multicast update or multicast
+  // inval coherence requests sent by the memory cache to the L1 caches and
+  // update the UPT.
   //
-  // It can be update or inval requests initiated by the WRITE FSM,
+  // It can be update or inval requests initiated by the WRITE or CAS FSM,
   // or inval requests initiated by the XRAM_RSP FSM.
   // It can also be a direct request from the WRITE FSM.
@@ -1023,42 +1078,63 @@
   // 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
+  // All those response packets are one flit packet.
+  // The index in the Table is defined in the UPDT_TABLE INDEX field, and
   // the transaction type is defined in the UPT entry.
-  /////////////////////////////////////////////////////////////////////
-
-  switch ( r_init_rsp_fsm.read() )
+  ////////////////////////////////////////////////////////////////////////
+
+  switch(r_multi_ack_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 " << name() << ".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() )
+    case MULTI_ACK_IDLE:
+      {
+        bool multi_ack_fifo_rok = m_cc_receive_to_multi_ack_fifo.rok();
+
+        // None Multicast Acknowledgement received and
+        // none WRITE FSM UPT decrement request
+        if( not multi_ack_fifo_rok and
+            not r_write_to_multi_ack_req.read())
+        {
+          break;
+        }
+
+        // WRITE FSM request to decrement update table response counter
+        // Priority to Multicast Acknowledgement priority
+        if(not multi_ack_fifo_rok)
+        {
+          r_write_to_multi_ack_req = false;
+          r_multi_ack_upt_index    = r_write_to_multi_ack_upt_index.read();
+          r_multi_ack_fsm          = MULTI_ACK_UPT_LOCK;
+
+          break;
+        }
+
+        // Multicast Acknowledgement received 
+        uint64_t flit = m_cc_receive_to_multi_ack_fifo.read();
+
+        uint8_t updt_index = 
+          DspinDhccpParam::dspin_get(flit, DspinDhccpParam::MULTI_ACK_UPDT_INDEX);
+
+        bool eop =
+          (DspinDhccpParam::dspin_get(flit, DspinDhccpParam::FROM_L1_EOP) == 0x1);
+
+        if(updt_index >= m_upt.size())
         {
           std::cout
             << "VCI_MEM_CACHE ERROR " << name()
-            << " INIT_RSP_IDLE state" << std::endl
+            << " MULTI_ACK_IDLE state" << std::endl
             << "index too large for UPT: "
-            << " / rtrdid = " << std::dec << p_vci_ini.rtrdid.read()
-            << " / UPT size = " << std::dec << m_update_tab.size()
+            << std::dec
+            << " / UPT index = " << updt_index
+            << " / UPT size = "  << m_upt.size()
             << std::endl;
 
           exit(0);
         }
-        if ( !p_vci_ini.reop.read() )
+
+        if(not eop)
         {
           std::cout
             << "VCI_MEM_CACHE ERROR " << name()
-            << " INIT_RSP_IDLE state" << std::endl
-            << "all coherence response packets must be one flit"
+            << " MULTI_ACK_IDLE state" << std::endl
+            << "A Multicast Acknowledgement must be an one flit packet"
             << std::endl;
 
@@ -1066,92 +1142,133 @@
         }
 
-        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 )
-      {
+        cc_receive_to_multi_ack_fifo_get = true;
+        r_multi_ack_upt_index           = updt_index;
+        r_multi_ack_fsm                 = MULTI_ACK_UPT_LOCK;
+
+#if DEBUG_MEMC_MULTI_ACK
+        if(m_debug_multi_ack_fsm)
+        {
+          std::cout
+            <<  "  <MEMC " << name()
+            << ".MULTI_ACK_IDLE> Response for UPT entry "
+            << updt_index
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+    case MULTI_ACK_UPT_LOCK:
+      {
+        // get lock to the UPDATE table
+        if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) break;
+
+        // decrement the number of expected responses
         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 " << name() << ".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
-            << "unsuccessful access to decrement the UPT" << std::endl;
+        bool valid   = m_upt.decrement(r_multi_ack_upt_index.read(), count);
+
+        if(not valid)
+        {
+          std::cout
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " MULTI_ACK_UPT_LOCK state" << std::endl
+            << "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());
-
-#if DEBUG_MEMC_INIT_RSP
-        if ( m_debug_init_rsp_fsm )
-        {
-          std::cout <<  "  <MEMC " << name() << ".INIT_RSP_UPT_CLEAR> Clear UPT entry "
-            << r_init_rsp_upt_index.read() <<  std::endl;
-        }
-#endif
-      }
-      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 )
+        if(count == 0)
+        {
+          r_multi_ack_fsm = MULTI_ACK_UPT_CLEAR;
+        }
+        else
+        {
+          r_multi_ack_fsm = MULTI_ACK_IDLE;
+        }
+
+#if DEBUG_MEMC_MULTI_ACK
+        if(m_debug_multi_ack_fsm)
         {
           std::cout
             << "  <MEMC " << name()
-            << ".INIT_RSP_END> Request TGT_RSP FSM to send a response to srcid "
-            << r_init_rsp_srcid.read()
+            << ".MULTI_ACK_UPT_LOCK> Decrement the responses counter for UPT:"
+            << " entry = "       << r_multi_ack_upt_index.read()
+            << " / rsp_count = " << std::dec << count
             << std::endl;
         }
 #endif
-      }
-      break;
-  } // end switch r_init_rsp_fsm
+        break;
+      }
+
+    case MULTI_ACK_UPT_CLEAR:
+      {
+        if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK)
+        {
+          std::cout
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " MULTI_ACK_UPT_CLEAR state"
+            << " bad UPT allocation"
+            << std::endl;
+
+          exit(0);
+        }
+
+        r_multi_ack_srcid = m_upt.srcid(r_multi_ack_upt_index.read());
+        r_multi_ack_trdid = m_upt.trdid(r_multi_ack_upt_index.read());
+        r_multi_ack_pktid = m_upt.pktid(r_multi_ack_upt_index.read());
+        r_multi_ack_nline = m_upt.nline(r_multi_ack_upt_index.read());
+        bool need_rsp     = m_upt.need_rsp(r_multi_ack_upt_index.read());
+
+        // clear the UPT entry
+        m_upt.clear(r_multi_ack_upt_index.read());
+
+        if(need_rsp)
+        {
+          r_multi_ack_fsm = MULTI_ACK_WRITE_RSP;
+        }
+        else
+        {
+          r_multi_ack_fsm = MULTI_ACK_IDLE;
+        }
+
+#if DEBUG_MEMC_MULTI_ACK
+        if(m_debug_multi_ack_fsm)
+        {
+          std::cout
+            <<  "  <MEMC " << name()
+            << ".MULTI_ACK_UPT_CLEAR> Clear UPT entry "
+            << r_multi_ack_upt_index.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+    case MULTI_ACK_WRITE_RSP:
+      {
+        // Post a request to TGT_RSP FSM
+        // Wait if pending request to the TGT_RSP FSM
+        if(r_multi_ack_to_tgt_rsp_req.read()) break;
+
+        r_multi_ack_to_tgt_rsp_req   = true;
+        r_multi_ack_to_tgt_rsp_srcid = r_multi_ack_srcid.read();
+        r_multi_ack_to_tgt_rsp_trdid = r_multi_ack_trdid.read();
+        r_multi_ack_to_tgt_rsp_pktid = r_multi_ack_pktid.read();
+        r_multi_ack_fsm              = MULTI_ACK_IDLE;
+
+#if DEBUG_MEMC_MULTI_ACK
+        if(m_debug_multi_ack_fsm)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << ".MULTI_ACK_WRITE_RSP> Request TGT_RSP FSM to send a response to srcid "
+            << r_multi_ack_srcid.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+  } // end switch r_multi_ack_fsm
 
   ////////////////////////////////////////////////////////////////////////////////////
@@ -1178,21 +1295,21 @@
   ////////////////////////////////////////////////////////////////////////////////////
 
-  switch ( r_read_fsm.read() )
+  switch(r_read_fsm.read())
   {
-    ///////////////
+      ///////////////
     case READ_IDLE:
-    // waiting a read request
-    {
-      if (m_cmd_read_addr_fifo.rok())
+      // waiting a read request
+    {
+      if(m_cmd_read_addr_fifo.rok())
       {
 
 #if DEBUG_MEMC_READ
-        if( m_debug_read_fsm )
+        if(m_debug_read_fsm)
         {
           std::cout << "  <MEMC " << name() << ".READ_IDLE> Read request:"
-            << " srcid = " << std::dec << m_cmd_read_srcid_fifo.read()
-            << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
-            << " / pktid = " << std::hex << m_cmd_read_pktid_fifo.read()
-            << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
+                    << " srcid = " << std::dec << m_cmd_read_srcid_fifo.read()
+                    << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
+                    << " / pktid = " << std::hex << m_cmd_read_pktid_fifo.read()
+                    << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
         }
 #endif
@@ -1204,7 +1321,7 @@
     ///////////////////
     case READ_DIR_REQ:
-    // Get the lock to the directory
-    {
-      if ( r_alloc_dir_fsm.read() == ALLOC_DIR_READ )
+      // Get the lock to the directory
+    {
+      if(r_alloc_dir_fsm.read() == ALLOC_DIR_READ)
       {
         r_read_fsm = READ_DIR_LOCK;
@@ -1212,9 +1329,9 @@
 
 #if DEBUG_MEMC_READ
-      if( m_debug_read_fsm )
-      {
-        std::cout 
-          << "  <MEMC " << name() << ".READ_DIR_REQ> Requesting DIR lock "
-          << std::endl;
+      if(m_debug_read_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name() << ".READ_DIR_REQ> Requesting DIR lock "
+            << std::endl;
       }
 #endif
@@ -1224,12 +1341,12 @@
     ///////////////////
     case READ_DIR_LOCK:
-    // check directory for hit / miss
-    {
-      if ( r_alloc_dir_fsm.read() == ALLOC_DIR_READ )
+      // 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);
-        if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL) // access the global table ONLY when we have an LL cmd
+        if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)   // access the global table ONLY when we have an LL cmd
         {
           r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
@@ -1253,8 +1370,8 @@
         // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
         bool cached_read = (m_cmd_read_pktid_fifo.read() & 0x1);
-        if(  entry.valid ) // hit
+        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 )
+          if(entry.is_cnt || (entry.count == 0) || !cached_read)
           {
             r_read_fsm = READ_DIR_HIT;
@@ -1271,17 +1388,17 @@
 
 #if DEBUG_MEMC_READ
-        if( m_debug_read_fsm )
+        if(m_debug_read_fsm)
         {
           std::cout
-            << "  <MEMC " << name() << ".READ_DIR_LOCK> Accessing directory: "
-            << " address = " << std::hex << m_cmd_read_addr_fifo.read()
-            << " / hit = " << std::dec << entry.valid
-            << " / count = " <<std::dec << entry.count
-            << " / is_cnt = " << entry.is_cnt << std::endl;
-            if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)
-            {
-              std::cout
+              << "  <MEMC " << name() << ".READ_DIR_LOCK> Accessing directory: "
+              << " address = " << std::hex << m_cmd_read_addr_fifo.read()
+              << " / hit = " << std::dec << entry.valid
+              << " / count = " <<std::dec << entry.count
+              << " / is_cnt = " << entry.is_cnt << std::endl;
+          if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)
+          {
+            std::cout
                 << "  <MEMC " << name() << ".READ_DIR_LOCK> global_llsc_table LL access" << std::endl;
-            }
+          }
         }
 #endif
@@ -1290,7 +1407,7 @@
       {
         std::cout
-          << "VCI_MEM_CACHE ERROR " << name()
-          << " READ_DIR_LOCK state" << std::endl
-          << "Bad DIR allocation"   << std::endl;
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " READ_DIR_LOCK state" << std::endl
+            << "Bad DIR allocation"   << std::endl;
 
         exit(0);
@@ -1308,5 +1425,5 @@
       //  - the cache line is valid but not replcated
 
-      if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ )
+      if(r_alloc_dir_fsm.read() == ALLOC_DIR_READ)
       {
         // signals generation
@@ -1314,5 +1431,5 @@
         // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
         // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
-        bool inst_read    = (m_cmd_read_pktid_fifo.read() & 0x2);
+        bool inst_read    = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0);
         // check if this is a cached read, this means pktid is either
         // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
@@ -1335,7 +1452,7 @@
         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
+        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();
@@ -1367,16 +1484,25 @@
 
 #if DEBUG_MEMC_READ
-        if( m_debug_read_fsm )
+        if(m_debug_read_fsm)
         {
           std::cout
-            << "  <MEMC " << name() << ".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
+              << "  <MEMC " << name() << ".READ_DIR_HIT> Update directory entry:"
+              << " addr = " << std::hex << m_cmd_read_addr_fifo.read()
+              << " / 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
+/**/
+          if(m_monitor_ok)
+          {
+            char buf[80];
+            snprintf(buf, 80, "READ_DIR_HIT srcid %d, ins %d", m_cmd_read_srcid_fifo.read(), ((m_cmd_read_pktid_fifo.read()&0x2)!=0));
+            check_monitor_read(buf, m_cmd_read_addr_fifo.read());
+          }
+/**/
 
         m_cache_directory.write(set, way, entry);
@@ -1388,7 +1514,15 @@
     ////////////////////
     case READ_HEAP_REQ:
-    // Get the lock to the HEAP directory
-    {
-      if( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
+      // Get the lock to the HEAP directory
+    {
+/**/
+          if(m_monitor_ok)
+          {
+            char buf[80];
+            snprintf(buf, 80, "READ_HEAP_REQ srcid %d, ins %d", m_cmd_read_srcid_fifo.read(), ((m_cmd_read_pktid_fifo.read()&0x2)!=0));
+            check_monitor_read(buf, m_cmd_read_addr_fifo.read());
+          }
+/**/
+      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
       {
         r_read_fsm = READ_HEAP_LOCK;
@@ -1396,9 +1530,9 @@
 
 #if DEBUG_MEMC_READ
-      if( m_debug_read_fsm )
-      {
-        std::cout 
-          << "  <MEMC " << name() << ".READ_HEAP_REQ> Requesting HEAP lock "
-          << std::endl;
+      if(m_debug_read_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name() << ".READ_HEAP_REQ> Requesting HEAP lock "
+            << std::endl;
       }
 #endif
@@ -1408,11 +1542,11 @@
     ////////////////////
     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 )
+      // 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();
+        bool go_cnt = (r_read_count.read() >= m_max_copies) || m_heap.is_full();
 
         // read data in the cache
@@ -1431,5 +1565,5 @@
         entry.count  = r_read_count.read() + 1;
 
-        if (not go_cnt)        // Not entering counter mode
+        if(not go_cnt)         // Not entering counter mode
         {
           entry.owner.srcid    = r_read_copy.read();
@@ -1453,10 +1587,10 @@
 
         // prepare the heap update (add an entry, or clear the linked list)
-        if (not go_cnt)     // not switching to counter mode
+        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_last_free     = (heap_entry.next == m_heap.next_free_ptr());
 
           r_read_fsm           = READ_HEAP_WRITE; // add an entry in the HEAP
@@ -1464,5 +1598,5 @@
         else            // switching to counter mode
         {
-          if ( r_read_count.read()>1 )            // heap must be cleared
+          if(r_read_count.read() >1)              // heap must be cleared
           {
             HeapEntry next_entry = m_heap.read(r_read_ptr.read());
@@ -1470,5 +1604,5 @@
             m_heap.write_free_ptr(r_read_ptr.read());
 
-            if( next_entry.next == r_read_ptr.read() )  // last entry
+            if(next_entry.next == r_read_ptr.read())    // last entry
             {
               r_read_fsm = READ_HEAP_LAST;    // erase the entry
@@ -1487,12 +1621,12 @@
 
 #if DEBUG_MEMC_READ
-        if( m_debug_read_fsm )
+        if(m_debug_read_fsm)
         {
           std::cout << "  <MEMC " << name() << ".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;
+                    << " tag = " << std::hex << entry.tag
+                    << " set = " << std::dec << set
+                    << " way = " << way
+                    << " count = " << entry.count
+                    << " is_cnt = " << entry.is_cnt << std::endl;
         }
 #endif
@@ -1501,7 +1635,7 @@
       {
         std::cout
-          << "VCI_MEM_CACHE ERROR " << name()
-          << " READ_HEAP_LOCK state" << std::endl
-          << "Bad HEAP allocation"   << std::endl;
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " READ_HEAP_LOCK state" << std::endl
+            << "Bad HEAP allocation"   << std::endl;
 
         exit(0);
@@ -1514,5 +1648,5 @@
     case READ_HEAP_WRITE:       // add a entry in the heap
     {
-      if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
+      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
       {
         HeapEntry heap_entry;
@@ -1521,7 +1655,7 @@
         heap_entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
 #endif
-        heap_entry.owner.inst     = (m_cmd_read_pktid_fifo.read() & 0x2);
-
-        if(r_read_count.read() == 1) // creation of a new linked list
+        heap_entry.owner.inst     = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0);
+
+        if(r_read_count.read() == 1)  // creation of a new linked list
         {
           heap_entry.next         = m_heap.next_free_ptr();
@@ -1538,10 +1672,10 @@
 
 #if DEBUG_MEMC_READ
-        if( m_debug_read_fsm )
+        if(m_debug_read_fsm)
         {
           std::cout
-            << "  <MEMC " << name() << ".READ_HEAP_WRITE> Add an entry in the heap:"
-            << " owner_id = " << heap_entry.owner.srcid
-            << " owner_ins = " << heap_entry.owner.inst << std::endl;
+              << "  <MEMC " << name() << ".READ_HEAP_WRITE> Add an entry in the heap:"
+              << " owner_id = " << heap_entry.owner.srcid
+              << " owner_ins = " << heap_entry.owner.inst << std::endl;
         }
 #endif
@@ -1550,7 +1684,7 @@
       {
         std::cout
-          << "VCI_MEM_CACHE ERROR " << name()
-          << " READ_HEAP_WRITE state" << std::endl
-          << "Bad HEAP allocation" << std::endl;
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " READ_HEAP_WRITE state" << std::endl
+            << "Bad HEAP allocation" << std::endl;
 
         exit(0);
@@ -1562,8 +1696,8 @@
     case READ_HEAP_ERASE:
     {
-      if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
+      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() )
+        if(next_entry.next == r_read_ptr.read())
         {
           r_read_fsm = READ_HEAP_LAST;
@@ -1578,7 +1712,7 @@
       {
         std::cout
-          << "VCI_MEM_CACHE ERROR " << name()
-          << " READ_HEAP_ERASE state" << std::endl
-          << "Bad HEAP allocation" << std::endl;
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " READ_HEAP_ERASE state" << std::endl
+            << "Bad HEAP allocation" << std::endl;
 
         exit(0);
@@ -1590,5 +1724,5 @@
     case READ_HEAP_LAST:
     {
-      if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
+      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
       {
         HeapEntry last_entry;
@@ -1614,5 +1748,5 @@
       {
         std::cout << "VCI_MEM_CACHE ERROR " << name()
-          << " READ_HEAP_LAST state" << std::endl;
+                  << " READ_HEAP_LAST state" << std::endl;
         std::cout << "Bad HEAP allocation" << std::endl;
         exit(0);
@@ -1624,8 +1758,8 @@
     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()];
+      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();
@@ -1638,10 +1772,10 @@
 
 #if DEBUG_MEMC_READ
-        if( m_debug_read_fsm )
+        if(m_debug_read_fsm)
         {
           std::cout << "  <MEMC " << name() << ".READ_RSP> Request the TGT_RSP FSM to return data:"
-            << " rsrcid = " << std::dec << m_cmd_read_srcid_fifo.read()
-            << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
-            << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
+                    << " rsrcid = " << std::dec << m_cmd_read_srcid_fifo.read()
+                    << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
+                    << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
         }
 #endif
@@ -1653,13 +1787,13 @@
     case READ_TRT_LOCK: // read miss : check the Transaction Table
     {
-      if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ )
+      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
+        vci_addr_t  addr      = (vci_addr_t) m_cmd_read_addr_fifo.read();
+        bool        hit_read  = m_trt.hit_read(m_nline[addr], index);
+        bool        hit_write = m_trt.hit_write(m_nline[addr]);
+        bool        wok       = !m_trt.full(index);
+
+        if(hit_read || !wok || hit_write)    // missing line already requested or no space
         {
           if(!wok)      m_cpt_trt_full++;
@@ -1675,10 +1809,10 @@
 
 #if DEBUG_MEMC_READ
-        if( m_debug_read_fsm )
+        if(m_debug_read_fsm)
         {
           std::cout << "  <MEMC " << name() << ".READ_TRT_LOCK> Check TRT:"
-            << " hit_read = " << hit_read
-            << " / hit_write = " << hit_write
-            << " / full = " << !wok << std::endl;
+                    << " hit_read = " << hit_read
+                    << " / hit_write = " << hit_write
+                    << " / full = " << !wok << std::endl;
         }
 #endif
@@ -1690,25 +1824,25 @@
     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),
-            r_read_ll_key.read());
+      if(r_alloc_trt_fsm.read() == ALLOC_TRT_READ)
+      {
+        m_trt.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),
+                              r_read_ll_key.read());
 #if DEBUG_MEMC_READ
-        if( m_debug_read_fsm )
+        if(m_debug_read_fsm)
         {
           std::cout << "  <MEMC " << name() << ".READ_TRT_SET> Write in Transaction Table: " << std::hex
-            << " address = " << std::hex << m_cmd_read_addr_fifo.read()
-            << " / srcid = " << std::dec << m_cmd_read_srcid_fifo.read()
-            << std::endl;
+                    << " address = " << std::hex << m_cmd_read_addr_fifo.read()
+                    << " / srcid = " << std::dec << m_cmd_read_srcid_fifo.read()
+                    << std::endl;
         }
 #endif
@@ -1724,5 +1858,5 @@
       // and send it to the ixr_cmd_fsm
 
-      if( not r_read_to_ixr_cmd_req )
+      if(not r_read_to_ixr_cmd_req)
       {
         cmd_read_fifo_get       = true;
@@ -1733,9 +1867,9 @@
 
 #if DEBUG_MEMC_READ
-        if( m_debug_read_fsm )
+        if(m_debug_read_fsm)
         {
           std::cout
-            << "  <MEMC " << name() << ".READ_TRT_REQ> Request GET transaction for address "
-            << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
+              << "  <MEMC " << name() << ".READ_TRT_REQ> Request GET transaction for address "
+              << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
         }
 #endif
@@ -1764,7 +1898,7 @@
   //   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 coherence transaction, the WRITE FSM
+  //   through the CC_SEND FSM. In case of coherence transaction, the WRITE FSM
   //   does not respond to the writing processor, as this response will be sent by
-  //   the INIT_RSP FSM when all update responses have been received.
+  //   the MULTI_ACK FSM when all update responses have been received.
   //
   // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
@@ -1776,10 +1910,10 @@
   /////////////////////////////////////////////////////////////////////////////////////
 
-  switch ( r_write_fsm.read() )
+  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() )
+      if(m_cmd_write_addr_fifo.rok())
       {
         if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
@@ -1805,11 +1939,11 @@
 
         // initialize the be field for all words
-        for ( size_t word=0 ; word<m_words ; word++ )
-        {
-          if ( word == index ) r_write_be[word] = m_cmd_write_be_fifo.read();
-          else                 r_write_be[word] = 0x0;
-        }
-
-        if( m_cmd_write_eop_fifo.read() || ((m_cmd_write_pktid_fifo.read() & 0x7)  == TYPE_SC) )
+        for(size_t word=0 ; word<m_words ; word++)
+        {
+          if(word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
+          else              r_write_be[word] = 0x0;
+        }
+
+        if (m_cmd_write_eop_fifo.read() || ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC))
         {
           r_write_fsm = WRITE_DIR_REQ;
@@ -1821,10 +1955,10 @@
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_IDLE> Write request "
-            << " srcid = " << std::dec << m_cmd_write_srcid_fifo.read()
-            << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
-            << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
+                    << " srcid = " << std::dec << m_cmd_write_srcid_fifo.read()
+                    << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
+                    << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
         }
 #endif
@@ -1836,11 +1970,12 @@
     case WRITE_NEXT:  // copy next word of a write burst in local buffer
     {
-      if ( m_cmd_write_addr_fifo.rok() )
+      if(m_cmd_write_addr_fifo.rok())
       {
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
-        {
-          std::cout << "  <MEMC " << name() << ".WRITE_NEXT> Write another word in local buffer"
+        if(m_debug_write_fsm)
+        {
+          std::cout << "  <MEMC " << name()
+                    << ".WRITE_NEXT> Write another word in local buffer"
                     << std::endl;
         }
@@ -1849,6 +1984,6 @@
 
         // 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())] ))
+        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
@@ -1866,5 +2001,5 @@
         r_write_word_count  = r_write_word_count.read() + 1;
 
-        if ( m_cmd_write_eop_fifo.read() )
+        if(m_cmd_write_eop_fifo.read())
         {
           r_write_fsm = WRITE_DIR_REQ;
@@ -1913,5 +2048,5 @@
 
         ///////////////////////////////////////////////////////////////////////
-        // WRITE command or SC command treatment returning from the WAIT state
+        // WRITE command treatment or SC command returning from the WAIT state
         // In the second case, we must access the LL/SC global table to
         // erase any possible new reservation when we release the lock on the
@@ -1936,12 +2071,12 @@
     ////////////////////
     case WRITE_DIR_LOCK:
-    // access directory to check hit/miss
-    {
-      if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE )
+      // 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
+        if(entry.valid)    // hit
         {
           // copy directory entry in local buffer in case of hit
@@ -1958,5 +2093,5 @@
           r_write_way        = way;
 
-          if( entry.is_cnt && entry.count )
+          if(entry.is_cnt && entry.count)
           {
             r_write_fsm = WRITE_DIR_READ;
@@ -1973,11 +2108,11 @@
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_DIR_LOCK> Check the directory: "
-            << " address = " << std::hex << r_write_address.read()
-            << " hit = " << std::dec << entry.valid
-            << " count = " << entry.count
-            << " is_cnt = " << entry.is_cnt << std::endl;
+                    << " address = " << std::hex << r_write_address.read()
+                    << " hit = " << std::dec << entry.valid
+                    << " count = " << entry.count
+                    << " is_cnt = " << entry.is_cnt << std::endl;
           if((r_write_pktid.read() & 0x7) == TYPE_SC)
             std::cout << "  <MEMC " << name() << ".WRITE_DIR_LOCK> global_llsc_table SC access" << std::endl;
@@ -1990,6 +2125,6 @@
       {
         std::cout << "VCI_MEM_CACHE ERROR " << name()
-          << " WRITE_DIR_LOCK state"        << std::endl
-          << "bad DIR allocation"           << std::endl;
+                  << " WRITE_DIR_LOCK state"        << std::endl
+                  << "bad DIR allocation"           << std::endl;
 
         exit(0);
@@ -2008,12 +2143,12 @@
       {
         data_t mask = 0;
-        if  (r_write_be[word].read() & 0x1) mask = mask | 0x000000FF;
-        if  (r_write_be[word].read() & 0x2) mask = mask | 0x0000FF00;
-        if  (r_write_be[word].read() & 0x4) mask = mask | 0x00FF0000;
-        if  (r_write_be[word].read() & 0x8) mask = mask | 0xFF000000;
+        if(r_write_be[word].read() & 0x1) mask = mask | 0x000000FF;
+        if(r_write_be[word].read() & 0x2) mask = mask | 0x0000FF00;
+        if(r_write_be[word].read() & 0x4) mask = mask | 0x00FF0000;
+        if(r_write_be[word].read() & 0x8) mask = mask | 0xFF000000;
 
         // complete only if mask is not null (for energy consumption)
         r_write_data[word]  = (r_write_data[word].read() & mask) |
-          (m_cache_data.read(way, set, word) & ~mask);
+                              (m_cache_data.read(way, set, word) & ~mask);
 
       } // end for
@@ -2023,5 +2158,5 @@
 
 #if DEBUG_MEMC_WRITE
-      if( m_debug_write_fsm )
+      if(m_debug_write_fsm)
       {
         std::cout << "  <MEMC " << name() << ".WRITE_DIR_READ> Read the cache to complete local buffer" << std::endl;
@@ -2059,14 +2194,14 @@
       bool owner = (((r_write_copy.read() == r_write_srcid.read())
 #if L1_MULTI_CACHE
-            and (r_write_copy_cache.read()==r_write_pktid.read())
-#endif
-            ) and not r_write_copy_inst.read());
+                     and(r_write_copy_cache.read() ==r_write_pktid.read())
+#endif
+                    ) and not r_write_copy_inst.read());
 
       // no_update is true when there is no need for coherence transaction
       // (tests for sc requests)
-      bool no_update = ((r_write_count.read()==0) || ( owner && (r_write_count.read()==1) && (r_write_pktid.read() != TYPE_SC)));
+      bool no_update = ((r_write_count.read() ==0) || (owner && (r_write_count.read() ==1) && (r_write_pktid.read() != TYPE_SC)));
 
       // write data in the cache if no coherence transaction
-      if( no_update )
+      if(no_update)
       {
         for(size_t word=0 ; word<m_words ; word++)
@@ -2074,20 +2209,20 @@
           m_cache_data.write(way, set, word, r_write_data[word].read(), r_write_be[word].read());
 
-          if ( m_monitor_ok )
+          if(m_monitor_ok)
           {
-            vci_addr_t address = (r_write_address.read() & ~(vci_addr_t)0x3F) | word<<2;
+            vci_addr_t address = (r_write_address.read() & ~(vci_addr_t) 0x3F) | word<<2;
             char buf[80];
             snprintf(buf, 80, "WRITE_DIR_HIT srcid %d", r_write_srcid.read());
-            check_monitor( buf, address, r_write_data[word].read() );
+            check_monitor(buf, address, r_write_data[word].read());
           }
         }
       }
 
-      if ( owner and not no_update and (r_write_pktid.read() != TYPE_SC))
+      if(owner and not no_update and(r_write_pktid.read() != TYPE_SC))
       {
         r_write_count = r_write_count.read() - 1;
       }
 
-      if ( no_update )
+      if(no_update)
       // Write transaction completed
       {
@@ -2097,6 +2232,6 @@
       // coherence update required
       {
-        if( !r_write_to_init_cmd_multi_req.read()   &&
-            !r_write_to_init_cmd_brdcast_req.read() )
+        if(!r_write_to_cc_send_multi_req.read()   &&
+            !r_write_to_cc_send_brdcast_req.read())
         {
           r_write_fsm = WRITE_UPT_LOCK;
@@ -2109,17 +2244,17 @@
 
 #if DEBUG_MEMC_WRITE
-      if( m_debug_write_fsm )
-      {
-        if ( no_update )
+      if(m_debug_write_fsm)
+      {
+        if(no_update)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_DIR_HIT> Write into cache / No coherence transaction"
-            << std::endl;
+                    << std::endl;
         }
         else
         {
           std::cout << "  <MEMC " << name() << ".WRITE_DIR_HIT> Coherence update required:"
-            << " is_cnt = " << r_write_is_cnt.read()
-            << " nb_copies = " << std::dec << r_write_count.read() << std::endl;
-          if (owner)
+                    << " is_cnt = " << r_write_is_cnt.read()
+                    << " nb_copies = " << std::dec << r_write_count.read() << std::endl;
+          if(owner)
             std::cout << "       ... but the first copy is the writer" << std::endl;
         }
@@ -2129,8 +2264,8 @@
     }
 
-      ////////////////////
+    ////////////////////
     case WRITE_UPT_LOCK:  // Try to register the update request in UPT
     {
-      if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE )
+      if(r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE)
       {
         bool        wok        = false;
@@ -2144,14 +2279,14 @@
         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
+        wok = m_upt.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 word=0 ; word<m_words ; word++)
@@ -2159,10 +2294,10 @@
             m_cache_data.write(way, set, word, r_write_data[word].read(), r_write_be[word].read());
 
-            if ( m_monitor_ok )
+            if(m_monitor_ok)
             {
-              vci_addr_t address = (r_write_address.read() & ~(vci_addr_t)0x3F) | word<<2;
+              vci_addr_t address = (r_write_address.read() & ~(vci_addr_t) 0x3F) | word<<2;
               char buf[80];
               snprintf(buf, 80, "WRITE_UPT_LOCK srcid %d", srcid);
-              check_monitor(buf, address, r_write_data[word].read() );
+              check_monitor(buf, address, r_write_data[word].read());
             }
           }
@@ -2170,10 +2305,10 @@
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
-        {
-          if ( wok )
+        if(m_debug_write_fsm)
+        {
+          if(wok)
           {
             std::cout << "  <MEMC " << name() << ".WRITE_UPT_LOCK> Register the multicast update in UPT / "
-              << " nb_copies = " << r_write_count.read() << std::endl;
+                      << " nb_copies = " << r_write_count.read() << std::endl;
           }
         }
@@ -2181,18 +2316,18 @@
         r_write_upt_index = index;
         //  releases the lock protecting UPT and the DIR if no entry...
-        if ( wok ) r_write_fsm = WRITE_UPT_HEAP_LOCK;
-        else       r_write_fsm = WRITE_WAIT;
-      }
-      break;
-    }
-
-      /////////////////////////
+        if(wok) r_write_fsm = WRITE_UPT_HEAP_LOCK;
+        else    r_write_fsm = WRITE_WAIT;
+      }
+      break;
+    }
+
+    /////////////////////////
     case WRITE_UPT_HEAP_LOCK:   // get access to heap
     {
-      if( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE )
+      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE)
       {
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_UPT_HEAP_LOCK> Get acces to the HEAP" << std::endl;
@@ -2207,40 +2342,40 @@
     case WRITE_UPT_REQ:
     {
-      // prepare the coherence transaction for the INIT_CMD FSM
+      // prepare the coherence transaction for the CC_SEND FSM
       // and write the first copy in the FIFO
       // send the request if only one copy
 
-      if( !r_write_to_init_cmd_multi_req.read() &&
-          !r_write_to_init_cmd_brdcast_req.read()  )  // no pending coherence request
-      {
-        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();
+      if(!r_write_to_cc_send_multi_req.read() &&
+          !r_write_to_cc_send_brdcast_req.read())    // no pending coherence request
+      {
+        r_write_to_cc_send_brdcast_req  = false;
+        r_write_to_cc_send_trdid        = r_write_upt_index.read();
+        r_write_to_cc_send_nline        = m_nline[(vci_addr_t)(r_write_address.read())];
+        r_write_to_cc_send_index        = r_write_word_index.read();
+        r_write_to_cc_send_count        = r_write_word_count.read();
+
+        for(size_t i=0; i<m_words ; i++) r_write_to_cc_send_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 (r_write_pktid.read() == TYPE_SC) or
+        for(size_t i=min ; i<max ; i++) r_write_to_cc_send_data[i] = r_write_data[i];
+
+        if((r_write_copy.read() != r_write_srcid.read()) or(r_write_pktid.read() == TYPE_SC) or
 #if L1_MULTI_CACHE
             (r_write_copy_cache.read() != r_write_pktid.read()) or
 #endif
-            r_write_copy_inst.read() )
+            r_write_copy_inst.read())
         {
           // put the first srcid 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();
+          write_to_cc_send_fifo_put     = true;
+          write_to_cc_send_fifo_inst    = r_write_copy_inst.read();
+          write_to_cc_send_fifo_srcid   = r_write_copy.read();
 #if L1_MULTI_CACHE
-          write_to_init_cmd_fifo_cache_id= r_write_copy_cache.read();
+          write_to_cc_send_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;
+            r_write_to_cc_send_multi_req = true;
           }
           else
@@ -2258,10 +2393,10 @@
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
-        {
-          std::cout << "  <MEMC " << name() << ".WRITE_UPT_REQ> Post first request to INIT_CMD FSM"
-            << " / srcid = " << std::dec << r_write_copy.read()
-            << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
-          if ( r_write_count.read() == 1)
+        if(m_debug_write_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".WRITE_UPT_REQ> Post first request to CC_SEND FSM"
+                    << " / srcid = " << std::dec << r_write_copy.read()
+                    << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
+          if(r_write_count.read() == 1)
             std::cout << "         ... and this is the last" << std::endl;
         }
@@ -2274,5 +2409,5 @@
     case WRITE_UPT_NEXT:
     {
-      // continue the multi-update request to INIT_CMD fsm
+      // continue the multi-update request to CC_SEND fsm
       // when there is copies in the heap.
       // if one copy in the heap is the writer itself
@@ -2294,19 +2429,19 @@
       {
         dec_upt_counter                 = false;
-        write_to_init_cmd_fifo_put      = true;
-        write_to_init_cmd_fifo_inst     = entry.owner.inst;
-        write_to_init_cmd_fifo_srcid    = entry.owner.srcid;
+        write_to_cc_send_fifo_put      = true;
+        write_to_cc_send_fifo_inst     = entry.owner.inst;
+        write_to_cc_send_fifo_srcid    = entry.owner.srcid;
 #if L1_MULTI_CACHE
-        write_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
+        write_to_cc_send_fifo_cache_id = entry.owner.cache_id;
 #endif
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
-        {
-          std::cout << "  <MEMC " << name() << ".WRITE_UPT_NEXT> Post another request to INIT_CMD FSM"
-            << " / heap_index = " << std::dec << r_write_ptr.read()
-            << " / srcid = " << std::dec << r_write_copy.read()
-            << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
-          if( entry.next == r_write_ptr.read() )
+        if(m_debug_write_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".WRITE_UPT_NEXT> Post another request to CC_SEND FSM"
+                    << " / heap_index = " << std::dec << r_write_ptr.read()
+                    << " / srcid = " << std::dec << r_write_copy.read()
+                    << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
+          if(entry.next == r_write_ptr.read())
             std::cout << "        ... and this is the last" << std::endl;
         }
@@ -2318,11 +2453,11 @@
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_UPT_NEXT> Skip one entry in heap matching the writer"
-            << " / heap_index = " << std::dec << r_write_ptr.read()
-            << " / srcid = " << std::dec << r_write_copy.read()
-            << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
-          if( entry.next == r_write_ptr.read() )
+                    << " / heap_index = " << std::dec << r_write_ptr.read()
+                    << " / srcid = " << std::dec << r_write_copy.read()
+                    << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
+          if(entry.next == r_write_ptr.read())
             std::cout << "        ... and this is the last" << std::endl;
         }
@@ -2333,9 +2468,9 @@
       r_write_to_dec = dec_upt_counter or r_write_to_dec.read();
 
-      if( not m_write_to_init_cmd_inst_fifo.wok() )
+      if(not m_write_to_cc_send_inst_fifo.wok())
       {
         std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_UPT_NEXT state" << std::endl
-          << "The write_to_init_cmd_fifo should not be full" << std::endl
-          << "as the depth should be larger than the max number of copies" << std::endl;
+                  << "The write_to_cc_send_fifo should not be full" << std::endl
+                  << "as the depth should be larger than the max number of copies" << std::endl;
         exit(0);
       }
@@ -2343,8 +2478,8 @@
       r_write_ptr = entry.next;
 
-      if( entry.next == r_write_ptr.read() )  // last copy
-      {
-        r_write_to_init_cmd_multi_req = true;
-        if( r_write_to_dec.read() or dec_upt_counter)   r_write_fsm = WRITE_UPT_DEC;
+      if(entry.next == r_write_ptr.read())    // last copy
+      {
+        r_write_to_cc_send_multi_req = true;
+        if(r_write_to_dec.read() or dec_upt_counter)   r_write_fsm = WRITE_UPT_DEC;
         else                                          r_write_fsm = WRITE_IDLE;
       }
@@ -2357,15 +2492,15 @@
       // If the initial writer has a copy, it should not
       // receive an update request, but the counter in the
-      // update table must be decremented by the INIT_RSP FSM.
-
-      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();
+      // update table must be decremented by the MULTI_ACK FSM.
+
+      if(!r_write_to_multi_ack_req.read())
+      {
+        r_write_to_multi_ack_req = true;
+        r_write_to_multi_ack_upt_index = r_write_upt_index.read();
         r_write_fsm = WRITE_IDLE;
       }
       break;
     }
-    
+
     ///////////////
     case WRITE_RSP:
@@ -2376,5 +2511,5 @@
       // a new request in the write FIFO
 
-      if ( !r_write_to_tgt_rsp_req.read() )
+      if(!r_write_to_tgt_rsp_req.read())
       {
         // post the request to TGT_RSP_FSM
@@ -2386,5 +2521,5 @@
 
         // try to get a new write request from the FIFO
-        if ( m_cmd_write_addr_fifo.rok() )
+        if(m_cmd_write_addr_fifo.rok())
         {
           if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
@@ -2410,11 +2545,11 @@
 
           // initialize the be field for all words
-          for ( size_t word=0 ; word<m_words ; word++ )
+          for(size_t word=0 ; word<m_words ; word++)
           {
-            if ( word == index ) r_write_be[word] = m_cmd_write_be_fifo.read();
+            if(word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
             else                 r_write_be[word] = 0x0;
           }
 
-          if( m_cmd_write_eop_fifo.read() || ((m_cmd_write_pktid_fifo.read() & 0x7)  == TYPE_SC) )
+          if(m_cmd_write_eop_fifo.read() || ((m_cmd_write_pktid_fifo.read() & 0x7)  == TYPE_SC))
           {
             r_write_fsm = WRITE_DIR_REQ;
@@ -2431,14 +2566,14 @@
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_RSP> Post a request to TGT_RSP FSM: rsrcid = "
-            << std::dec << r_write_srcid.read() << std::endl;
-          if ( m_cmd_write_addr_fifo.rok() )
+                    << std::dec << r_write_srcid.read() << std::endl;
+          if(m_cmd_write_addr_fifo.rok())
           {
             std::cout << "                    New Write request: "
-              << " srcid = " << std::dec << m_cmd_write_srcid_fifo.read()
-              << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
-              << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
+                      << " srcid = " << std::dec << m_cmd_write_srcid_fifo.read()
+                      << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
+                      << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
           }
         }
@@ -2451,9 +2586,9 @@
     case WRITE_MISS_TRT_LOCK: // Miss : check Transaction Table
     {
-      if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
+      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
       {
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_MISS_TRT_LOCK> Check the TRT" << std::endl;
@@ -2462,10 +2597,10 @@
         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
+        vci_addr_t  addr  = (vci_addr_t) r_write_address.read();
+        bool    hit_read  = m_trt.hit_read(m_nline[addr], hit_index);
+        bool    hit_write = m_trt.hit_write(m_nline[addr]);
+        bool    wok       = !m_trt.full(wok_index);
+
+        if(hit_read)      // register the modified data in TRT
         {
           r_write_trt_index = hit_index;
@@ -2473,5 +2608,5 @@
           m_cpt_write_miss++;
         }
-        else if ( wok && !hit_write )   // set a new entry in TRT
+        else if(wok && !hit_write)      // set a new entry in TRT
         {
           r_write_trt_index = wok_index;
@@ -2492,5 +2627,5 @@
     {
 #if DEBUG_MEMC_WRITE
-      if( m_debug_write_fsm )
+      if(m_debug_write_fsm)
       {
         std::cout << "  <MEMC " << name() << ".WRITE_WAIT> Releases the locks before retry" << std::endl;
@@ -2504,5 +2639,5 @@
     case WRITE_MISS_TRT_SET:  // register a new transaction in TRT (Write Buffer)
     {
-      if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
+      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
       {
         std::vector<be_t>   be_vector;
@@ -2510,24 +2645,24 @@
         be_vector.clear();
         data_vector.clear();
-        for ( size_t i=0; i<m_words; i++ )
+        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);
+        m_trt.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_MISS_XRAM_REQ;
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_MISS_TRT_SET> Set a new entry in TRT" << std::endl;
@@ -2538,8 +2673,8 @@
     }
 
-      /////////////////////////
+    /////////////////////////
     case WRITE_MISS_TRT_DATA: // update an entry in TRT (used as a Write Buffer)
     {
-      if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
+      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
       {
         std::vector<be_t> be_vector;
@@ -2547,19 +2682,19 @@
         be_vector.clear();
         data_vector.clear();
-        for ( size_t i=0; i<m_words; i++ )
+        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);
+        m_trt.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 )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_MISS_TRT_DATA> Modify an existing entry in TRT" << std::endl;
-          m_transaction_tab.print( r_write_trt_index.read() );
+          m_trt.print(r_write_trt_index.read());
         }
 #endif
@@ -2571,5 +2706,5 @@
     case WRITE_MISS_XRAM_REQ: // send a GET request to IXR_CMD FSM
     {
-      if ( !r_write_to_ixr_cmd_req )
+      if(!r_write_to_ixr_cmd_req)
       {
         r_write_to_ixr_cmd_req   = true;
@@ -2580,5 +2715,5 @@
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_MISS_XRAM_REQ> Post a GET request to the IXR_CMD FSM" << std::endl;
@@ -2592,9 +2727,9 @@
     case WRITE_BC_TRT_LOCK:     // Check TRT not full
     {
-      if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
+      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
+        bool wok = !m_trt.full(wok_index);
+        if(wok)       // set a new entry in TRT
         {
           r_write_trt_index = wok_index;
@@ -2607,8 +2742,8 @@
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_BC_TRT_LOCK> Check TRT : wok = "
-            << wok << " / index = " << wok_index << std::endl;
+                    << wok << " / index = " << wok_index << std::endl;
         }
 #endif
@@ -2620,5 +2755,5 @@
     case WRITE_BC_UPT_LOCK:      // register BC transaction in UPT
     {
-      if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE )
+      if(r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE)
       {
         bool        wok       = false;
@@ -2630,21 +2765,21 @@
         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);
+        wok =m_upt.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 )
+        if(m_debug_write_fsm)
+        {
+          if(wok)
           {
             std::cout << "  <MEMC " << name() << ".WRITE_BC_UPT_LOCK> Register the broadcast inval in UPT / "
-              << " nb_copies = " << r_write_count.read() << std::endl;
+                      << " nb_copies = " << r_write_count.read() << std::endl;
           }
         }
@@ -2652,5 +2787,5 @@
         r_write_upt_index = index;
 
-        if ( wok ) r_write_fsm = WRITE_BC_DIR_INVAL;
+        if(wok) r_write_fsm = WRITE_BC_DIR_INVAL;
         else       r_write_fsm = WRITE_WAIT;
       }
@@ -2663,7 +2798,7 @@
       // 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 ) )
+      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_BC_DIR_INVAL state" << std::endl;
@@ -2673,15 +2808,15 @@
 
       // register a write request to XRAM in TRT
-      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));
+      m_trt.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));
 
       // invalidate directory entry
@@ -2705,8 +2840,8 @@
 
 #if DEBUG_MEMC_WRITE
-      if( m_debug_write_fsm )
+      if(m_debug_write_fsm)
       {
         std::cout << "  <MEMC " << name() << ".WRITE_BC_DIR_INVAL> Invalidate the directory entry: @ = "
-          << r_write_address.read() << " / register the put transaction in TRT:" << std::endl;
+                  << r_write_address.read() << " / register the put transaction in TRT:" << std::endl;
       }
 #endif
@@ -2716,26 +2851,26 @@
 
     //////////////////////
-    case WRITE_BC_CC_SEND:    // 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;
+    case WRITE_BC_CC_SEND:    // Post a coherence broadcast request to CC_SEND FSM
+    {
+      if(!r_write_to_cc_send_multi_req.read() && !r_write_to_cc_send_brdcast_req.read())
+      {
+        r_write_to_cc_send_multi_req   = false;
+        r_write_to_cc_send_brdcast_req = true;
+        r_write_to_cc_send_trdid       = r_write_upt_index.read();
+        r_write_to_cc_send_nline       = m_nline[(vci_addr_t)(r_write_address.read())];
+        r_write_to_cc_send_index       = 0;
+        r_write_to_cc_send_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_to_cc_send_be[i]=0;
+          r_write_to_cc_send_data[i] = 0;
         }
         r_write_fsm = WRITE_BC_XRAM_REQ;
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
-        {
-          std::cout << "  <MEMC " << name() << ".WRITE_BC_CC_SEND> Post a broadcast request to INIT_CMD FSM" << std::endl;
+        if(m_debug_write_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".WRITE_BC_CC_SEND> Post a broadcast request to CC_SEND FSM" << std::endl;
         }
 #endif
@@ -2747,5 +2882,5 @@
     case WRITE_BC_XRAM_REQ:   // Post a put request to IXR_CMD FSM
     {
-      if ( !r_write_to_ixr_cmd_req )
+      if(!r_write_to_ixr_cmd_req)
       {
         r_write_to_ixr_cmd_req     = true;
@@ -2759,5 +2894,5 @@
 
 #if DEBUG_MEMC_WRITE
-        if( m_debug_write_fsm )
+        if(m_debug_write_fsm)
         {
           std::cout << "  <MEMC " << name() << ".WRITE_BC_XRAM_REQ> Post a put request to IXR_CMD FSM" << std::endl;
@@ -2769,3605 +2904,4227 @@
   } // end switch r_write_fsm
 
-    ///////////////////////////////////////////////////////////////////////
-    //    IXR_CMD FSM
-    ///////////////////////////////////////////////////////////////////////
-    // The IXR_CMD fsm controls the command packets to the XRAM :
-    // - It sends a single cell VCI read request to the XRAM in case of MISS
-    // posted by the READ, WRITE or CAS 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, WRITE FSM
-    // or CAS 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, CAS & XRAM_RSP FSMs
-    // with a round-robin priority.
-    ////////////////////////////////////////////////////////////////////////
-
-    switch ( r_ixr_cmd_fsm.read() )
-    {
-        ////////////////////////
-        case IXR_CMD_READ_IDLE:
-        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
-        else if ( r_cas_to_ixr_cmd_req  )      r_ixr_cmd_fsm = IXR_CMD_CAS_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;
+  ///////////////////////////////////////////////////////////////////////
+  //    IXR_CMD FSM
+  ///////////////////////////////////////////////////////////////////////
+  // The IXR_CMD fsm controls the command packets to the XRAM :
+  // - It sends a single cell VCI read request to the XRAM in case of MISS
+  // posted by the READ, WRITE or CAS 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, WRITE FSM
+  // or CAS 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, CAS & XRAM_RSP FSMs
+  // with a round-robin priority.
+  ////////////////////////////////////////////////////////////////////////
+
+  switch(r_ixr_cmd_fsm.read())
+  {
+      ////////////////////////
+    case IXR_CMD_READ_IDLE:
+      if(r_write_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+      else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS_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_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS_NLINE;
+      else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+      else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+      else if(r_write_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+      break;
+      ////////////////////////
+    case IXR_CMD_CAS_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_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS_NLINE;
+      break;
+      ////////////////////////
+    case IXR_CMD_XRAM_IDLE:
+      if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+      else if(r_write_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+      else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS_NLINE;
+      else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+      break;
+      /////////////////////////       // send a get request to XRAM
+    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 " << name() << ".IXR_CMD_READ_NLINE> Send a get request to xram" << std::endl;
+        }
+#endif
+      }
+      break;
+      //////////////////////////
+    case IXR_CMD_WRITE_NLINE:     // send a put or get command to XRAM
+      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 " << name() << ".IXR_CMD_WRITE_NLINE> Send a put request to xram" << std::endl;
+          }
+#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 " << name() << ".IXR_CMD_WRITE_NLINE> Send a get request to xram" << std::endl;
+          }
+#endif
+        }
+      }
+      break;
+      //////////////////////
+    case IXR_CMD_CAS_NLINE:      // send a put or get command to XRAM
+      if(p_vci_ixr.cmdack)
+      {
+        if(r_cas_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_CAS_IDLE;
+            r_cas_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 " << name() << ".IXR_CMD_CAS_NLINE> Send a put request to xram" << std::endl;
+          }
+#endif
+        }
+        else
+        {
+          r_ixr_cmd_fsm = IXR_CMD_CAS_IDLE;
+          r_cas_to_ixr_cmd_req = false;
+
+#if DEBUG_MEMC_IXR_CMD
+          if(m_debug_ixr_cmd_fsm)
+          {
+            std::cout << "  <MEMC " << name() << ".IXR_CMD_CAS_NLINE> Send a get request to xram" << std::endl;
+          }
+#endif
+        }
+      }
+      break;
+      ////////////////////////
+    case IXR_CMD_XRAM_DATA:     // send a put command to XRAM
+      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 " << name() << ".IXR_CMD_XRAM_DATA> Send a put request to xram" << std::endl;
+        }
+#endif
+      }
+      break;
+
+  } // end switch r_ixr_cmd_fsm
+
+  ////////////////////////////////////////////////////////////////////////////
+  //                IXR_RSP FSM
+  ////////////////////////////////////////////////////////////////////////////
+  // The IXR_RSP FSM receives the response packets from the XRAM,
+  // for both put transaction, and get transaction.
+  //
+  // - 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 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.
+  // The FSM takes the lock protecting the TRT to store the line in the TRT
+  // (taking into account the write requests already stored in the TRT).
+  // When the line is completely written, the corresponding rok signal is set.
+  ///////////////////////////////////////////////////////////////////////////////
+
+  switch(r_ixr_rsp_fsm.read())
+  {
+      //////////////////
+    case IXR_RSP_IDLE:  // test if it's a 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 " << name() << ".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 " << name() << ".IXR_RSP_IDLE> Response from XRAM to a get transaction" << std::endl;
+          }
+#endif
+        }
+      }
+      break;
+    }
+    ////////////////////////
+    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 " << name() << ".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_trt.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 " << name() << ".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)
+      {
+        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) == 1);
+        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_trt.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 " << name() << ".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
+
+  ////////////////////////////////////////////////////////////////////////////
+  //                XRAM_RSP FSM
+  ////////////////////////////////////////////////////////////////////////////
+  // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
+  // 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
+  // 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
+  // FSM to return the cache line to the registered processor.
+  // If there is no empty slot, a victim line is evicted, and
+  // invalidate requests are sent to the L1 caches containing copies.
+  // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD
+  // FSM to save the victim line to the XRAM, and register the write transaction
+  // in the TRT (using the entry previously used by the read transaction).
+  ///////////////////////////////////////////////////////////////////////////////
+
+  switch(r_xram_rsp_fsm.read())
+  {
+      ///////////////////
+    case XRAM_RSP_IDLE: // scan the XRAM responses to get the TRT index (round robin)
+    {
+      size_t ptr   = r_xram_rsp_trt_index.read();
+      size_t lines = m_trt_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 " << name() << ".XRAM_RSP_IDLE> Available cache line in TRT:"
+                      << " index = " << std::dec << index << std::endl;
+          }
+#endif
+          break;
+        }
+      }
+      break;
+    }
+    ///////////////////////
+    case XRAM_RSP_DIR_LOCK:
+      // Takes the lock on the directory
+      // Takes the lock on TRT
+      // Copy the TRT entry in a local buffer
+    {
+      if((r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP) &&
+          (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_trt.read(index));
+        r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
+
+        r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
+
+#if DEBUG_MEMC_XRAM_RSP
+        if(m_debug_xram_rsp_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".XRAM_RSP_DIR_LOCK> Get access to directory" << std::endl;
+        }
+#endif
+      }
+      break;
+    }
+    ///////////////////////
+    case XRAM_RSP_TRT_COPY:
+      // Select a victim cache line
+    {
+      if((r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP))
+      {
+        // selects & extracts a victim line from cache
+        size_t way = 0;
+        size_t set = m_y[(vci_addr_t)(r_xram_rsp_trt_buf.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
+        m_cache_data.read_line(way, set, r_xram_rsp_victim_data);
+
+        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(!r_xram_rsp_trt_buf.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 " << name() << ".XRAM_RSP_TRT_COPY> Select a slot: "
+                    << " way = " << std::dec << way
+                    << " / set = " << set
+                    << " / inval_required = " << inval << std::endl;
+        }
+#endif
+      }
+      else
+      {
+        std::cout << "VCI_MEM_CACHE ERROR "     << name()
+                  << " XRAM_RSP_TRT_COPY state" << std::endl
+                  << "bad TRT allocation"       << std::endl;
+
+        exit(0);
+      }
+      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_upt.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 " << name() << ".XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
+                      << " but an invalidation is already registered at this address" << std::endl;
+            m_upt.print();
+          }
+#endif
+
+        }
+        else if(m_upt.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 " << name() << ".XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
+                      << " but the table is full" << std::endl;
+            m_upt.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 " << name() << ".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
+      // check if this is an instruction read, this means pktid is either
+      // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
+      // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
+      bool inst_read = (r_xram_rsp_trt_buf.pktid & 0x2) && r_xram_rsp_trt_buf.proc_read;
+      // check if this is a cached read, this means pktid is either
+      // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
+      // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
+      bool cached_read = (r_xram_rsp_trt_buf.pktid & 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 word=0; word<m_words ; word++)
+      {
+        m_cache_data.write(way, set, word, r_xram_rsp_trt_buf.wdata[word]);
+
+        if(m_monitor_ok)
+        {
+          vci_addr_t address = r_xram_rsp_trt_buf.nline<<6 | word<<2;
+          check_monitor("XRAM_RSP_DIR_UPDT", address, r_xram_rsp_trt_buf.wdata[word]);
+        }
+      }
+      // 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_upt.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 " << name() << ".XRAM_RSP_DIR_UPDT> Directory update: "
+                  << " way = " << std::dec << way
+                  << " / set = " << set
+                  << " / owner_id = " << entry.owner.srcid
+                  << " / owner_ins = " << entry.owner.inst
+                  << " / 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_trt.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_trt.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 " << name() << ".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_ll_key = r_xram_rsp_trt_buf.ll_key;
+        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 " << name() << ".XRAM_RSP_DIR_RSP> Request the TGT_RSP FSM to return data:"
+                    << " rsrcid = " << std::dec << r_xram_rsp_trt_buf.srcid
+                    << " / address = " << std::hex << 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 CC_SEND FSM
+    {
+      if(!r_xram_rsp_to_cc_send_multi_req.read() &&
+          !r_xram_rsp_to_cc_send_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_cc_send_multi_req    = last_multi_req;
+        r_xram_rsp_to_cc_send_brdcast_req  = r_xram_rsp_victim_is_cnt.read();
+        r_xram_rsp_to_cc_send_nline        = r_xram_rsp_victim_nline.read();
+        r_xram_rsp_to_cc_send_trdid        = r_xram_rsp_upt_index;
+        xram_rsp_to_cc_send_fifo_srcid     = r_xram_rsp_victim_copy.read();
+        xram_rsp_to_cc_send_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
+#if L1_MULTI_CACHE
+        xram_rsp_to_cc_send_fifo_cache_id  = r_xram_rsp_victim_copy_cache.read();
+#endif
+        xram_rsp_to_cc_send_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_REQ;
+        else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#if DEBUG_MEMC_XRAM_RSP
+        if(m_debug_xram_rsp_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".XRAM_RSP_INVAL> Send an inval request to CC_SEND FSM:"
+                    << " victim line = " << r_xram_rsp_victim_nline.read() << 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_REQ;
+        else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#if DEBUG_MEMC_XRAM_RSP
+        if(m_debug_xram_rsp_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".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_REQ:
+      // Get the lock to the HEAP directory
+    {
+      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP)
+      {
+        r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+      }
+
+#if DEBUG_MEMC_XRAM_RSP
+      if(m_debug_xram_rsp_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name() << ".XRAM_RSP_HEAP_REQ> Requesting HEAP lock "
+            << 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_cc_send_fifo_srcid    = entry.owner.srcid;
+#if L1_MULTI_CACHE
+        xram_rsp_to_cc_send_fifo_cache_id = entry.owner.cache_id;
+#endif
+        xram_rsp_to_cc_send_fifo_inst  = entry.owner.inst;
+        xram_rsp_to_cc_send_fifo_put   = true;
+        if(m_xram_rsp_to_cc_send_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_cc_send_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 " << name() << ".XRAM_RSP_HEAP_ERASE> Erase the list of copies:"
+                    << " srcid = " << std::dec << entry.owner.srcid
+                    << " / inst = " << std::dec << 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
+      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 " << name() << ".XRAM_RSP_HEAP_LAST> Heap housekeeping" << std::endl;
+      }
+#endif
+      break;
+    }
+    // ///////////////////////
+    case XRAM_RSP_ERROR_ERASE:  // erase TRT entry in case of error
+    {
+      m_trt.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 " << name() << ".XRAM_RSP_ERROR_ERASE> Error reported by XRAM / erase the TRT entry" << 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 " << name() << ".XRAM_RSP_ERROR_RSP> Request a response error to TGT_RSP FSM:"
+                    << " srcid = " << std::dec << r_xram_rsp_trt_buf.srcid << std::endl;
+        }
+#endif
+      }
+      break;
+    }
+  } // end swich r_xram_rsp_fsm
+
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    CLEANUP FSM
+  ////////////////////////////////////////////////////////////////////////////////////
+  // The CLEANUP FSM handles the cleanup request from L1 caches.
+  // It accesses the cache directory and the heap to update the list of copies.
+  ////////////////////////////////////////////////////////////////////////////////////
+
+  switch(r_cleanup_fsm.read())
+  {
+    case CLEANUP_IDLE:
+    {
+      // Get first DSPIN flit of the CLEANUP command
+      if(not m_cc_receive_to_cleanup_fifo.rok()) break;
+
+      uint64_t flit = m_cc_receive_to_cleanup_fifo.read();
+
+      uint32_t srcid =
+        DspinDhccpParam::dspin_get(
+            flit,
+            DspinDhccpParam::CLEANUP_SRCID);
+
+      uint8_t type =
+        DspinDhccpParam::dspin_get(
+            flit,
+            DspinDhccpParam::FROM_L1_TYPE);
+
+      r_cleanup_way_index =
+        DspinDhccpParam::dspin_get(
+            flit,
+            DspinDhccpParam::CLEANUP_WAY_INDEX);
+
+      r_cleanup_nline =
+        DspinDhccpParam::dspin_get(
+            flit,
+            DspinDhccpParam::CLEANUP_NLINE_MSB) 
+        << 32;
+
+      r_cleanup_inst  = (type == DspinDhccpParam::TYPE_CLEANUP_INST);
+      r_cleanup_srcid = srcid;
+
+      if(srcid >= m_initiators)
+      {
+        std::cout
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " CLEANUP_IDLE state"  << std::endl
+            << "illegal srcid for cleanup request" << std::endl;
+
+        exit(0);
+      }
+
+      m_cpt_cleanup++;
+      cc_receive_to_cleanup_fifo_get = true;
+      r_cleanup_fsm                 = CLEANUP_GET_NLINE;
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC "         << name()
+            << ".CLEANUP_IDLE> Cleanup request:" << std::hex
+            << " / owner_id = "   << srcid
+            << " / owner_ins = "  << (type == DspinDhccpParam::TYPE_CLEANUP_INST)
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CLEANUP_GET_NLINE:
+    {
+      // Get second flit of cleanup command
+      if(not m_cc_receive_to_cleanup_fifo.rok()) break;
+
+      uint64_t flit = m_cc_receive_to_cleanup_fifo.read();
+
+      addr_t nline =
+        r_cleanup_nline.read() |
+        DspinDhccpParam::dspin_get(flit, DspinDhccpParam::CLEANUP_NLINE_LSB);
+
+      bool eop =
+        DspinDhccpParam::dspin_get(flit, DspinDhccpParam::FROM_L1_EOP) == 0x1;
+
+      assert(
+          eop &&
+          "VCI_MEM_CACHE ERROR: "
+          "CLEANUP command must have exactly two flits");
+
+      cc_receive_to_cleanup_fifo_get = true;
+      r_cleanup_nline               = nline;
+      r_cleanup_fsm                 = CLEANUP_DIR_REQ;
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC "         << name()
+            << ".CLEANUP_GET_NLINE> Cleanup request:"
+            << std::hex
+            << " / address = "    << nline * m_words * 4
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CLEANUP_DIR_REQ:
+    {
+      // Get the lock to the directory
+      if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP) break;
+
+      r_cleanup_fsm = CLEANUP_DIR_LOCK;
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name() << ".CLEANUP_DIR_REQ> Requesting DIR lock "
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CLEANUP_DIR_LOCK:
+    {
+      // test directory status
+      if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP)
+      {
+        std::cout
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " CLEANUP_DIR_LOCK state"
+            << " bad DIR allocation" << std::endl;
+
+        exit(0);
+      }
+
+      // 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_count        = entry.count;
+      r_cleanup_ptr          = entry.ptr;
+      r_cleanup_copy         = entry.owner.srcid;
+      r_cleanup_copy_inst    = entry.owner.inst;
+#if L1_MULTI_CACHE
+      r_cleanup_copy_cache   = entry.owner.cache_id;
+#endif
+
+      // hit :
+      // the copy must be cleared
+      if(entry.valid)
+      {
+        assert(
+            (entry.count > 0) &&
+            "VCI MEM CACHE ERROR: "
+            "In CLEANUP_DIR_LOCK, CLEANUP command on a valid entry "
+            "with no copies");
+
+        // no access to the heap
+        if((entry.count == 1) || (entry.is_cnt))
+        {
+          r_cleanup_fsm = CLEANUP_DIR_WRITE;
+        }
+        // access to the heap
+        else
+        {
+          r_cleanup_fsm = CLEANUP_HEAP_REQ;
+        }
+      }
+      // miss :
+      // we must check the update table for a pending
+      // invalidation transaction
+      else
+      {
+        r_cleanup_fsm = CLEANUP_UPT_LOCK;
+      }
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << ".CLEANUP_DIR_LOCK> Test directory status: "
+            << std::hex
+            << " line = "         << cleanup_address
+            << " / hit = "        << entry.valid
+            << " / dir_id = "     << entry.owner.srcid
+            << " / dir_ins = "    << entry.owner.inst
+            << " / search_id = "  << r_cleanup_srcid.read()
+            << " / search_ins = " << r_cleanup_inst.read()
+            << " / count = "      << entry.count
+            << " / is_cnt = "     << entry.is_cnt
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    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   match_srcid = (r_cleanup_copy.read() == r_cleanup_srcid.read());
+
+#if L1_MULTI_CACHE
+      match_srcid       &= (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
+#endif
+
+      bool   match_inst  = (r_cleanup_copy_inst.read() == r_cleanup_inst.read());
+      bool   match       = match_srcid && match_inst;
+
+      if(not r_cleanup_is_cnt.read() and not match)
+      {
+        std::cout
+            << "VCI_MEM_CACHE ERROR : Cleanup request on a valid"
+            << "entry using linked list mode with no corresponding"
+            << "directory or heap entry"
+            << std::endl;
+
+        exit(1);
+      }
+
+      // 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();
+      entry.count       = r_cleanup_count.read() - 1;
+      entry.owner.srcid = 0;
+      entry.owner.inst  = 0;
+
+#if L1_MULTI_CACHE
+      entry.owner.cache_id = 0;
+#endif
+
+      m_cache_directory.write(set, way, entry);
+
+      r_cleanup_fsm = CLEANUP_SEND_ACK;
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << ".CLEANUP_DIR_WRITE> Update directory:"
+            << std::hex
+            << " address = "   << 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_REQ:
+    {
+      // get the lock to the HEAP directory
+      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP) break;
+
+      r_cleanup_fsm = CLEANUP_HEAP_LOCK;
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << ".CLEANUP_HEAP_REQ> HEAP lock acquired "
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CLEANUP_HEAP_LOCK:
+    {
+      // two cases are handled in this state :
+      // 1. the matching copy is directly in the directory
+      // 2. the matching copy is the first copy in the heap
+      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
+      {
+        std::cout
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " CLEANUP_HEAP_LOCK state"
+            << " bad HEAP 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)];
+
+      HeapEntry heap_entry  = m_heap.read(r_cleanup_ptr.read());
+      bool last             = (heap_entry.next == r_cleanup_ptr.read());
+
+      // match_dir computation
+      bool match_dir_srcid  = (r_cleanup_copy.read()      == r_cleanup_srcid.read());
+      bool match_dir_inst   = (r_cleanup_copy_inst.read() == r_cleanup_inst.read());
+      bool match_dir        = match_dir_srcid  and match_dir_inst;
+
+      // match_heap computation
+      bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+      bool match_heap_inst  = (heap_entry.owner.inst  == r_cleanup_inst.read());
+      bool match_heap       = match_heap_srcid and match_heap_inst;
+
+      r_cleanup_prev_ptr    = r_cleanup_ptr.read();
+      r_cleanup_prev_srcid  = heap_entry.owner.srcid;
+      r_cleanup_prev_inst   = heap_entry.owner.inst;
+
+#if L1_MULTI_CACHE
+      match_dir  = match_dir  and(r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
+      match_heap = match_heap and(heap_entry.owner.cache_id   == r_cleanup_pktid.read());
+      r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
+#endif
+
+      if(not match_dir and not match_heap and last)
+      {
+        std::cout
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " CLEANUP_HEAP_LOCK state"
+            << " hit but copy not found"
+            << std::endl;
+/**/
+        std::cout
+          << "r_cleanup_srcid = " << r_cleanup_srcid.read()
+          << " / r_cleanup_inst = " << r_cleanup_inst.read() << std::endl
+          << "r_cleanup_copy = " << r_cleanup_copy.read()
+          << " / r_cleanup_copy_inst = " << r_cleanup_copy_inst.read() << std::endl
+          << "heap_entry.owner.srcid = " << heap_entry.owner.srcid
+          << " / heap_entry.owner.inst = " << heap_entry.owner.inst << std::endl;
+/**/
+        exit(0);
+      }
+
+      if(match_dir and match_heap)
+      {
+        std::cout
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " CLEANUP_HEAP_LOCK state"
+            << " two copies matching the cleanup owner id"
+            << std::endl;
+/**/
+        std::cout
+          << "r_cleanup_srcid = " << r_cleanup_srcid.read()
+          << " / r_cleanup_inst = " << r_cleanup_inst.read() << std::endl
+          << "r_cleanup_copy = " << r_cleanup_copy.read()
+          << " / r_cleanup_copy_inst = " << r_cleanup_copy_inst.read() << std::endl
+          << "heap_entry.owner.srcid = " << heap_entry.owner.srcid
+          << " / heap_entry.owner.inst = " << heap_entry.owner.inst << std::endl;
+/**/
+
+        exit(0);
+      }
+
+      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.count          = r_cleanup_count.read()-1;
+
+      // the matching copy is registered in the directory and
+      // it must be replaced by the first copy registered in
+      // the heap. The corresponding entry must be freed
+      if(match_dir)
+      {
+        dir_entry.ptr            = heap_entry.next;
+        dir_entry.owner.srcid    = heap_entry.owner.srcid;
+        dir_entry.owner.inst     = heap_entry.owner.inst;
+
+#if L1_MULTI_CACHE
+        dir_entry.owner.cache_id = heap_entry.owner.cache_id;
+#endif
+
+        r_cleanup_next_ptr       = r_cleanup_ptr.read();
+        r_cleanup_fsm            = CLEANUP_HEAP_FREE;
+      }
+
+      // the matching copy is the first copy in the heap
+      // It must be freed and the copy registered in directory
+      // must point to the next copy in heap
+      else if(match_heap)
+      {
+        dir_entry.ptr            = heap_entry.next;
+        dir_entry.owner.srcid    = r_cleanup_copy.read();
+        dir_entry.owner.inst     = r_cleanup_copy_inst.read();
+
+#if L1_MULTI_CACHE
+        dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
+#endif
+
+        r_cleanup_next_ptr       = r_cleanup_ptr.read();
+        r_cleanup_fsm            = CLEANUP_HEAP_FREE;
+      }
+
+      // The matching copy is in the heap, but is not the first copy
+      // The directory entry must be modified to decrement count
+      else
+      {
+        dir_entry.ptr            = r_cleanup_ptr.read();
+        dir_entry.owner.srcid    = r_cleanup_copy.read();
+        dir_entry.owner.inst     = r_cleanup_copy_inst.read();
+
+#if L1_MULTI_CACHE
+        dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
+#endif
+
+        r_cleanup_next_ptr       = heap_entry.next;
+        r_cleanup_fsm            = CLEANUP_HEAP_SEARCH;
+      }
+
+      m_cache_directory.write(set,way,dir_entry);
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << ".CLEANUP_HEAP_LOCK> Checks matching:"
+            << " address = "      << 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_inst.read()
+            << 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 match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+      bool match_heap_inst  = (heap_entry.owner.inst  == r_cleanup_inst.read());
+      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(not match_heap and last)
+      {
+        std::cout
+            << "VCI_MEM_CACHE_ERROR " << name()
+            << " CLEANUP_HEAP_SEARCH state"
+            << " cleanup on valid line but copy not found"
+            << std::endl;
+
+        exit(0);
+      }
+
+      // the matching copy must be removed
+      if(match_heap)
+      {
+        // re-use ressources
+        r_cleanup_ptr = heap_entry.next;
+        r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
+      }
+      // test the next in the linked list
+      else
+      {
+        r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
+        r_cleanup_prev_srcid    = heap_entry.owner.srcid;
+        r_cleanup_prev_inst     = heap_entry.owner.inst;
+        r_cleanup_next_ptr      = heap_entry.next;
+
+        r_cleanup_fsm           = CLEANUP_HEAP_SEARCH;
+
+#if L1_MULTI_CACHE
+        r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
+#endif
+      }
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        if(not match_heap)
+        {
+          std::cout
+              << "  <MEMC " << name()
+              << ".CLEANUP_HEAP_SEARCH> Matching copy not found, search next:"
+              << std::endl;
+        }
+        else
+        {
+          std::cout
+              << "  <MEMC " << name()
+              << ".CLEANUP_HEAP_SEARCH> Matching copy found:"
+              << std::endl;
+        }
+
+        std::cout
+            << " address = "      << 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_inst.read()
+            << " / last = "       << last
+            << 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);
+      }
+
+      HeapEntry heap_entry;
+      heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
+      heap_entry.owner.inst     = r_cleanup_prev_inst.read();
+
+#if L1_MULTI_CACHE
+      heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
+#endif
+
+      bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
+
+      // this is the last entry of the list of copies
+      if(last)
+      {
+        heap_entry.next = r_cleanup_prev_ptr.read();
+      }
+      // this is not the last entry
+      else
+      {
+        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 " << name()
+            << ".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
+            << "Bad HEAP allocation" << std::endl;
+
+        exit(0);
+      }
+
+      HeapEntry heap_entry;
+      heap_entry.owner.srcid    = 0;
+      heap_entry.owner.inst     = false;
+
+#if L1_MULTI_CACHE
+      heap_entry.owner.cache_id = 0;
+#endif
+
+      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_SEND_ACK;
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << ".CLEANUP_HEAP_SEARCH> Update the list of free entries"
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CLEANUP_UPT_LOCK:
+    {
+      // search pending invalidate transaction matching the Cleanup NLINE in the UPDATE TABLE
+      // get the lock in the UPDATE_TABLE
+      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP) break;
+
+      size_t index = 0;
+      bool   match_inval;
+
+      match_inval = m_upt.search_inval(r_cleanup_nline.read(), index);
+
+      // no pending inval
+      if(not match_inval)
+      {
+        r_cleanup_fsm = CLEANUP_SEND_ACK;
+
+#if DEBUG_MEMC_CLEANUP
+        if(m_debug_cleanup_fsm)
+        {
+          std::cout
+              << "  <MEMC " << name()
+              << ".CLEANUP_UPT_LOCK> Unexpected cleanup"
+              << " with no corresponding UPT entry:"
+              << " address = " << std::hex
+              << (r_cleanup_nline.read() *4*m_words)
+              << std::endl;
+        }
+#endif
         break;
-        ////////////////////////
-        case IXR_CMD_WRITE_IDLE:
-        if      ( r_cas_to_ixr_cmd_req  )      r_ixr_cmd_fsm = IXR_CMD_CAS_NLINE;
-        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
-        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
-        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
-        break;
-        ////////////////////////
-        case IXR_CMD_CAS_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_cas_to_ixr_cmd_req  )      r_ixr_cmd_fsm = IXR_CMD_CAS_NLINE;
-        break;
-        ////////////////////////
-        case IXR_CMD_XRAM_IDLE:
-        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
-        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
-        else if ( r_cas_to_ixr_cmd_req  )      r_ixr_cmd_fsm = IXR_CMD_CAS_NLINE;
-        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
-        break;
-        /////////////////////////       // send a get request to XRAM
-        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 " << name() << ".IXR_CMD_READ_NLINE> Send a get request to xram" << std::endl;
-}
-#endif
-        }
-        break;
-        //////////////////////////
-        case IXR_CMD_WRITE_NLINE:     // send a put or get command to XRAM
-        if ( p_vci_ixr.cmdack )
-        {
-            if( r_write_to_ixr_cmd_write.read())
+      }
+
+      // pending inval
+      r_cleanup_write_srcid    = m_upt.srcid(index);
+      r_cleanup_write_trdid    = m_upt.trdid(index);
+      r_cleanup_write_pktid    = m_upt.pktid(index);
+      r_cleanup_write_need_rsp = m_upt.need_rsp(index);
+      r_cleanup_index          = index;
+
+      r_cleanup_fsm         = CLEANUP_UPT_DECREMENT;
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << ".CLEANUP_UPT_LOCK> Cleanup matching pending"
+            << " invalidate transaction on UPT:"
+            << std::hex
+            << " address = "   << r_cleanup_nline.read() * m_words * 4
+            << " upt_entry = " << index
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CLEANUP_UPT_DECREMENT:
+    {
+      // decrement response counter in UPT matching entry
+      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP)
+      {
+        std::cout
+            << "VCI_MEM_CACHE ERROR "         << name()
+            << " CLEANUP_UPT_DECREMENT state" << std::endl
+            << "Bad UPT allocation"
+            << std::endl;
+
+        exit(0);
+      }
+
+      size_t count = 0;
+      m_upt.decrement(r_cleanup_index.read(), count);
+
+      // invalidation transaction finished
+      // (all acknowledgements received)
+      if(count == 0)
+      {
+        r_cleanup_fsm = CLEANUP_UPT_CLEAR;
+      }
+      // invalidation transaction not finished
+      else
+      {
+        r_cleanup_fsm = CLEANUP_SEND_ACK ;
+      }
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC "      << name()
+            << ".CLEANUP_UPT_DECREMENT> Decrement response counter in UPT:"
+            << " UPT_index = " << r_cleanup_index.read()
+            << " rsp_count = " << count
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CLEANUP_UPT_CLEAR:
+    {
+      // Clear UPT entry of finished invalidation transaction
+      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP)
+      {
+        std::cout
+            << "VCI_MEM_CACHE ERROR "     << name()
+            << " CLEANUP_UPT_CLEAR state" << std::endl
+            << "Bad UPT allocation"
+            << std::endl;
+
+        exit(0);
+      }
+
+      m_upt.clear(r_cleanup_index.read());
+
+      if(r_cleanup_write_need_rsp.read())
+      {
+        r_cleanup_fsm = CLEANUP_WRITE_RSP;
+      }
+      else
+      {
+        r_cleanup_fsm = CLEANUP_SEND_ACK;
+      }
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC "      << name()
+            << ".CLEANUP_UPT_CLEAR> Clear entry in UPT:"
+            << " UPT_index = " << r_cleanup_index.read()
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CLEANUP_WRITE_RSP:
+    {
+      // response to a previous write on the direct network
+      // wait if pending request to the TGT_RSP FSM
+      if(r_cleanup_to_tgt_rsp_req.read()) break;
+
+      // no pending request
+      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_SEND_ACK;
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << ".CLEANUP_WRITE_RSP> Send a response to a previous"
+            << " write request waiting for coherence transaction completion: "
+            << " rsrcid = "   << std::dec << r_cleanup_write_srcid.read()
+            << " / rtrdid = " << std::dec << r_cleanup_write_trdid.read()
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CLEANUP_SEND_ACK:
+    {
+      // acknowledgement to a cleanup command
+      // on the coherence network (request to the CC_SEND FSM).
+      // wait if pending request to the CC_SEND FSM
+      if(r_cleanup_to_cc_send_req.read()) break;
+
+      r_cleanup_to_cc_send_req       = true;
+      r_cleanup_to_cc_send_set_index = r_cleanup_nline.read() & 0xFFFF;
+      r_cleanup_to_cc_send_way_index = r_cleanup_way_index.read();
+      r_cleanup_to_cc_send_srcid     = r_cleanup_srcid.read();
+      r_cleanup_to_cc_send_inst      = r_cleanup_inst.read();
+
+      r_cleanup_fsm = CLEANUP_IDLE;
+
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug_cleanup_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << ".CLEANUP_SEND_ACK> Send the response to a cleanup request:"
+            << " srcid = " << std::dec << r_cleanup_srcid.read()
+            << std::endl;
+      }
+#endif
+      break;
+    }
+  } // end switch cleanup fsm
+
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    CAS FSM
+  ////////////////////////////////////////////////////////////////////////////////////
+  // The CAS FSM handles the CAS (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 CAS 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 CAS request is not consumed in the FIFO until a HIT is obtained.
+  // - In case of hit...
+  ///////////////////////////////////////////////////////////////////////////////////
+
+  switch(r_cas_fsm.read())
+  {
+      /////////////
+    case CAS_IDLE:     // fill the local rdata buffers
+    {
+      if(m_cmd_cas_addr_fifo.rok())
+      {
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_IDLE> CAS command: " << std::hex
+                    << " srcid = " <<  std::dec << m_cmd_cas_srcid_fifo.read()
+                    << " addr = " << std::hex << m_cmd_cas_addr_fifo.read()
+                    << " wdata = " << m_cmd_cas_wdata_fifo.read()
+                    << " eop = " << std::dec << m_cmd_cas_eop_fifo.read()
+                    << " cpt  = " << std::dec << r_cas_cpt.read() << std::endl;
+        }
+#endif
+        if(m_cmd_cas_eop_fifo.read())
+        {
+          m_cpt_cas++;
+          r_cas_fsm = CAS_DIR_REQ;
+        }
+        else  // we keep the last word in the FIFO
+        {
+          cmd_cas_fifo_get = true;
+        }
+        // We fill the two buffers
+        if(r_cas_cpt.read() < 2)    // 32 bits access
+          r_cas_rdata[r_cas_cpt.read()] = m_cmd_cas_wdata_fifo.read();
+
+        if((r_cas_cpt.read() == 1) && m_cmd_cas_eop_fifo.read())
+          r_cas_wdata = m_cmd_cas_wdata_fifo.read();
+
+        if(r_cas_cpt.read() >3)  // more than 4 flits...
+        {
+          std::cout << "VCI_MEM_CACHE ERROR in CAS_IDLE state : illegal CAS command"
+                    << std::endl;
+          exit(0);
+        }
+
+        if(r_cas_cpt.read() ==2)
+          r_cas_wdata = m_cmd_cas_wdata_fifo.read();
+
+        r_cas_cpt = r_cas_cpt.read() +1;
+      }
+      break;
+    }
+
+    /////////////////
+    case CAS_DIR_REQ:
+    {
+      if(r_alloc_dir_fsm.read() == ALLOC_DIR_CAS)
+      {
+        r_cas_fsm = CAS_DIR_LOCK;
+      }
+
+#if DEBUG_MEMC_CAS
+      if(m_debug_cas_fsm)
+      {
+        std::cout
+            << "  <MEMC " << name() << ".CAS_DIR_REQ> Requesting DIR lock "
+            << std::endl;
+      }
+#endif
+      break;
+    }
+
+    /////////////////
+    case CAS_DIR_LOCK:  // Read the directory
+    {
+      if(r_alloc_dir_fsm.read() == ALLOC_DIR_CAS)
+      {
+        size_t way = 0;
+        DirectoryEntry entry(m_cache_directory.read(m_cmd_cas_addr_fifo.read(), way));
+
+        r_cas_is_cnt     = entry.is_cnt;
+        r_cas_dirty      = entry.dirty;
+        r_cas_tag        = entry.tag;
+        r_cas_way        = way;
+        r_cas_copy       = entry.owner.srcid;
+#if L1_MULTI_CACHE
+        r_cas_copy_cache = entry.owner.cache_id;
+#endif
+        r_cas_copy_inst  = entry.owner.inst;
+        r_cas_ptr        = entry.ptr;
+        r_cas_count      = entry.count;
+
+        if(entry.valid)  r_cas_fsm = CAS_DIR_HIT_READ;
+        else             r_cas_fsm = CAS_MISS_TRT_LOCK;
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_DIR_LOCK> Directory acces"
+                    << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
+                    << " / hit = " << std::dec << entry.valid
+                    << " / count = " << entry.count
+                    << " / is_cnt = " << entry.is_cnt << std::endl;
+        }
+#endif
+      }
+      else
+      {
+        std::cout
+            << "VCI_MEM_CACHE ERROR " << name()
+            << " CAS_DIR_LOCK state" << std::endl
+            << "Bad DIR allocation"   << std::endl;
+
+        exit(0);
+      }
+
+      break;
+    }
+    /////////////////////
+    case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
+                            // and check data change in cache
+    {
+      size_t way  = r_cas_way.read();
+      size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+
+      // update directory (lock & dirty bits)
+      DirectoryEntry entry;
+      entry.valid          = true;
+      entry.is_cnt         = r_cas_is_cnt.read();
+      entry.dirty          = true;
+      entry.lock           = true;
+      entry.tag            = r_cas_tag.read();
+      entry.owner.srcid    = r_cas_copy.read();
+#if L1_MULTI_CACHE
+      entry.owner.cache_id = r_cas_copy_cache.read();
+#endif
+      entry.owner.inst     = r_cas_copy_inst.read();
+      entry.count          = r_cas_count.read();
+      entry.ptr            = r_cas_ptr.read();
+
+      m_cache_directory.write(set, way, entry);
+
+      // Stored data from cache in buffer to do the comparison in next state
+      m_cache_data.read_line(way, set, r_cas_data);
+
+      r_cas_fsm = CAS_DIR_HIT_COMPARE;
+
+#if DEBUG_MEMC_CAS
+      if(m_debug_cas_fsm)
+      {
+        std::cout
+          << "  <MEMC " << name() << ".CAS_DIR_HIT_READ> Read data from "
+          << " cache and store it in buffer"
+          << std::endl;
+      }
+#endif
+      break;
+    }
+
+    case CAS_DIR_HIT_COMPARE:
+    {
+      size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+
+      // Read data in buffer & check data change
+      bool ok = (r_cas_rdata[0].read() == r_cas_data[word].read());
+
+      if(r_cas_cpt.read() == 4)     // 64 bits CAS
+        ok &= (r_cas_rdata[1] == r_cas_data[word+1]);
+
+      // to avoid livelock, force the atomic access to fail pseudo-randomly
+      bool forced_fail = ((r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS);
+      r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((- (r_cas_lfsr & 1)) & 0xd0000001);
+
+      // cas success
+      if(ok and not forced_fail)
+      {
+        r_cas_fsm = CAS_DIR_HIT_WRITE;
+      }
+      // cas failure
+      else
+      {
+        r_cas_fsm = CAS_RSP_FAIL;
+      }
+
+#if DEBUG_MEMC_CAS
+      if(m_debug_cas_fsm)
+      {
+        std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_COMPARE> Compare the old"
+                  << " and the new data"
+                  << " / expected value = " << r_cas_rdata[0].read()
+                  << " / actual value = "   << r_cas_data[word].read()
+                  << " / forced_fail = "    << forced_fail << std::endl;
+      }
+#endif
+      break;
+    }
+    //////////////////////
+    case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
+      // write data in cache if no CC request
+    {
+      // The CAS is a success => sw access to the llsc_global_table
+      m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
+
+      // test coherence request
+      if(r_cas_count.read())   // replicated line
+      {
+        if(r_cas_is_cnt.read())
+        {
+          r_cas_fsm = CAS_BC_TRT_LOCK;    // broadcast invalidate required
+        }
+        else if(!r_cas_to_cc_send_multi_req.read() &&
+                !r_cas_to_cc_send_brdcast_req.read())
+        {
+          r_cas_fsm = CAS_UPT_LOCK;     // multi update required
+        }
+        else
+        {
+          r_cas_fsm = CAS_WAIT;
+        }
+      }
+      else                    // no copies
+      {
+        size_t way  = r_cas_way.read();
+        size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+        size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+
+        // cache update
+        m_cache_data.write(way, set, word, r_cas_wdata.read());
+        if(r_cas_cpt.read() == 4)
+          m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
+
+        r_cas_fsm = CAS_RSP_SUCCESS;
+
+        // monitor
+        if(m_monitor_ok)
+        {
+          vci_addr_t address = m_cmd_cas_addr_fifo.read();
+          char buf[80];
+          snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
+          check_monitor(buf, address, r_cas_wdata.read());
+
+          if(r_cas_cpt.read() == 4)
+            check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read());
+        }
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> Update cache:"
+                    << " way = " << std::dec << way
+                    << " / set = " << set
+                    << " / word = " << word
+                    << " / value = " << r_cas_wdata.read()
+                    << " / count = " << r_cas_count.read() << std::endl;
+          std::cout << "  <MEMC "
+                    << name() << ".CAS_DIR_HIT_WRITE> global_llsc_table SW access" << std::endl;
+        }
+#endif
+      }
+      break;
+    }
+    /////////////////
+    case CAS_UPT_LOCK:  // try to register the transaction in UPT
+      // and write data in cache if successful registration
+      // releases locks to retry later if UPT full
+    {
+      if(r_alloc_upt_fsm.read() == ALLOC_UPT_CAS)
+      {
+        bool        wok        = false;
+        size_t      index      = 0;
+        size_t      srcid      = m_cmd_cas_srcid_fifo.read();
+        size_t      trdid      = m_cmd_cas_trdid_fifo.read();
+        size_t      pktid      = m_cmd_cas_pktid_fifo.read();
+        addr_t      nline      = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+        size_t      nb_copies  = r_cas_count.read();
+
+        wok = m_upt.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
+        {
+          // cache update
+          size_t way  = r_cas_way.read();
+          size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+          size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+
+          m_cache_data.write(way, set, word, r_cas_wdata.read());
+          if(r_cas_cpt.read() ==4)
+            m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
+
+          r_cas_upt_index = index;
+          r_cas_fsm = CAS_UPT_HEAP_LOCK;
+
+          // monitor
+          if(m_monitor_ok)
+          {
+            vci_addr_t address = m_cmd_cas_addr_fifo.read();
+            char buf[80];
+            snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
+            check_monitor(buf, address, r_cas_wdata.read());
+
+            if(r_cas_cpt.read() ==4)
+              check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read());
+          }
+        }
+        else       //  releases the locks protecting UPT and DIR UPT full
+        {
+          r_cas_fsm = CAS_WAIT;
+        }
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name()
+                    << ".CAS_UPT_LOCK> Register multi-update transaction in UPT"
+                    << " / wok = " << wok
+                    << " / nline  = " << std::hex << nline
+                    << " / count = " << nb_copies << std::endl;
+        }
+#endif
+      }
+      break;
+    }
+    /////////////
+    case CAS_WAIT:   // release all locks and retry from beginning
+    {
+
+#if DEBUG_MEMC_CAS
+      if(m_debug_cas_fsm)
+      {
+        std::cout << "  <MEMC " << name()
+                  << ".CAS_WAIT> Release all locks" << std::endl;
+      }
+#endif
+      r_cas_fsm = CAS_DIR_REQ;
+      break;
+    }
+    //////////////////
+    case CAS_UPT_HEAP_LOCK:  // lock the heap
+    {
+      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
+      {
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name()
+                    << ".CAS_UPT_HEAP_LOCK> Get access to the heap" << std::endl;
+        }
+#endif
+        r_cas_fsm = CAS_UPT_REQ;
+      }
+      break;
+    }
+    ////////////////
+    case CAS_UPT_REQ:  // send a first update request to CC_SEND FSM
+    {
+      assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS) and
+             "VCI_MEM_CACHE ERROR : bad HEAP allocation");
+
+      if(!r_cas_to_cc_send_multi_req.read() && !r_cas_to_cc_send_brdcast_req.read())
+      {
+        r_cas_to_cc_send_brdcast_req  = false;
+        r_cas_to_cc_send_trdid        = r_cas_upt_index.read();
+        r_cas_to_cc_send_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+        r_cas_to_cc_send_index        = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+        r_cas_to_cc_send_wdata        = r_cas_wdata.read();
+
+        if(r_cas_cpt.read() == 4)
+        {
+          r_cas_to_cc_send_is_long    = true;
+          r_cas_to_cc_send_wdata_high = m_cmd_cas_wdata_fifo.read();
+        }
+        else
+        {
+          r_cas_to_cc_send_is_long    = false;
+          r_cas_to_cc_send_wdata_high = 0;
+        }
+
+        // We put the first copy in the fifo
+        cas_to_cc_send_fifo_put     = true;
+        cas_to_cc_send_fifo_inst    = r_cas_copy_inst.read();
+        cas_to_cc_send_fifo_srcid   = r_cas_copy.read();
+#if L1_MULTI_CACHE
+        cas_to_cc_send_fifo_cache_id= r_cas_copy_cache.read();
+#endif
+        if(r_cas_count.read() == 1)  // one single copy
+        {
+          r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
+          // update responses
+          cmd_cas_fifo_get            = true;
+          r_cas_to_cc_send_multi_req = true;
+          r_cas_cpt = 0;
+        }
+        else      // several copies
+        {
+          r_cas_fsm = CAS_UPT_NEXT;
+        }
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_UPT_REQ> Send the first update request to CC_SEND FSM "
+                    << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
+                    << " / wdata = " << std::hex << r_cas_wdata.read()
+                    << " / srcid = " << std::dec << r_cas_copy.read()
+                    << " / inst = " << std::dec << r_cas_copy_inst.read() << std::endl;
+        }
+#endif
+      }
+      break;
+    }
+    /////////////////
+    case CAS_UPT_NEXT:     // send a multi-update request to CC_SEND FSM
+    {
+      assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
+             and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
+
+      HeapEntry entry = m_heap.read(r_cas_ptr.read());
+      cas_to_cc_send_fifo_srcid    = entry.owner.srcid;
+#if L1_MULTI_CACHE
+      cas_to_cc_send_fifo_cache_id = entry.owner.cache_id;
+#endif
+      cas_to_cc_send_fifo_inst     = entry.owner.inst;
+      cas_to_cc_send_fifo_put = true;
+
+      if(m_cas_to_cc_send_inst_fifo.wok())   // request accepted by CC_SEND FSM
+      {
+        r_cas_ptr = entry.next;
+        if(entry.next == r_cas_ptr.read())    // last copy
+        {
+          r_cas_to_cc_send_multi_req = true;
+          r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
+          // all update responses
+          cmd_cas_fifo_get = true;
+          r_cas_cpt        = 0;
+        }
+      }
+
+#if DEBUG_MEMC_CAS
+      if(m_debug_cas_fsm)
+      {
+        std::cout << "  <MEMC " << name() << ".CAS_UPT_NEXT> Send the next update request to CC_SEND FSM "
+                  << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
+                  << " / wdata = " << std::hex << r_cas_wdata.read()
+                  << " / srcid = " << std::dec << entry.owner.srcid
+                  << " / inst = " << std::dec << entry.owner.inst << std::endl;
+      }
+#endif
+      break;
+    }
+    /////////////////////
+    case CAS_BC_TRT_LOCK:      // check the TRT to register a PUT transaction
+    {
+      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
+      {
+        if(!r_cas_to_ixr_cmd_req)    // we can transfer the request to IXR_CMD FSM
+        {
+          // fill the data buffer
+          size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+          for(size_t i = 0; i<m_words; i++)
+          {
+            if(i == word)
             {
-                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 " << name() << ".IXR_CMD_WRITE_NLINE> Send a put request to xram" << std::endl;
-}
-#endif
+              r_cas_to_ixr_cmd_data[i] = r_cas_wdata.read();
+            }
+            else if((i == word+1) && (r_cas_cpt.read() == 4))   // 64 bit CAS
+            {
+              r_cas_to_ixr_cmd_data[i] = m_cmd_cas_wdata_fifo.read();
             }
             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 " << name() << ".IXR_CMD_WRITE_NLINE> Send a get request to xram" << std::endl;
-}
-#endif
-            }
-        }
-        break;
-        //////////////////////
-        case IXR_CMD_CAS_NLINE:      // send a put or get command to XRAM
-        if ( p_vci_ixr.cmdack )
-        {
-            if( r_cas_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_CAS_IDLE;
-                    r_cas_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 " << name() << ".IXR_CMD_CAS_NLINE> Send a put request to xram" << std::endl;
-}
-#endif
-            }
-            else
-            {
-                r_ixr_cmd_fsm = IXR_CMD_CAS_IDLE;
-                r_cas_to_ixr_cmd_req = false;
-
-#if DEBUG_MEMC_IXR_CMD
-if( m_debug_ixr_cmd_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".IXR_CMD_CAS_NLINE> Send a get request to xram" << std::endl;
-}
-#endif
-            }
-        }
-        break;
-        ////////////////////////
-        case IXR_CMD_XRAM_DATA:     // send a put command to XRAM
-        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 " << name() << ".IXR_CMD_XRAM_DATA> Send a put request to xram" << std::endl;
-}
-#endif
-        }
-        break;
-
-    } // end switch r_ixr_cmd_fsm
-
-    ////////////////////////////////////////////////////////////////////////////
-    //                IXR_RSP FSM
-    ////////////////////////////////////////////////////////////////////////////
-    // The IXR_RSP FSM receives the response packets from the XRAM,
-    // for both put transaction, and get transaction.
-    //
-    // - 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 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.
-    // The FSM takes the lock protecting the TRT to store the line in the TRT
-    // (taking into account the write requests already stored in the TRT).
-    // When the line is completely written, the corresponding rok signal is set.
-    ///////////////////////////////////////////////////////////////////////////////
-
-    switch ( r_ixr_rsp_fsm.read() )
-    {
-        //////////////////
-        case IXR_RSP_IDLE:  // test if it's a 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 " << name() << ".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 " << name() << ".IXR_RSP_IDLE> Response from XRAM to a get transaction" << std::endl;
-}
-#endif
-                }
-            }
-            break;
-        }
-        ////////////////////////
-        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 " << name() << ".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;
-
-#if DEBUG_MEMC_IXR_RSP
-if( m_debug_ixr_rsp_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".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 )
-            {
-                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) == 1);
-                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 " << name() << ".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
-
-    ////////////////////////////////////////////////////////////////////////////
-    //                XRAM_RSP FSM
-    ////////////////////////////////////////////////////////////////////////////
-    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
-    // 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
-    // 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
-    // FSM to return the cache line to the registered processor.
-    // If there is no empty slot, a victim line is evicted, and
-    // invalidate requests are sent to the L1 caches containing copies.
-    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD
-    // FSM to save the victim line to the XRAM, and register the write transaction
-    // in the TRT (using the entry previously used by the read transaction).
-    ///////////////////////////////////////////////////////////////////////////////
-
-    switch ( r_xram_rsp_fsm.read() )
-    {
-        ///////////////////
-        case XRAM_RSP_IDLE: // 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 " << name() << ".XRAM_RSP_IDLE> Available cache line in TRT:"
-              << " index = " << std::dec << index << std::endl;
-}
-#endif
-                    break;
-                }
-            }
-            break;
-        }
-        ///////////////////////
-        case XRAM_RSP_DIR_LOCK:
-        // Takes the lock on the directory
-        // Takes the lock on TRT
-        // Copy the TRT entry in a local buffer
-        {
-            if (( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) &&
-                ( 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
-
-                r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
-
-#if DEBUG_MEMC_XRAM_RSP
-if( m_debug_xram_rsp_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".XRAM_RSP_DIR_LOCK> Get access to directory" << std::endl;
-}
-#endif
-            }
-            break;
-        }
-        ///////////////////////
-        case XRAM_RSP_TRT_COPY:
-        // Select a victim cache line
-        {
-            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) )
-            {
-                // selects & extracts a victim line from cache
-                size_t way = 0;
-                size_t set = m_y[(vci_addr_t)(r_xram_rsp_trt_buf.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
-                m_cache_data.read_line(way, set, r_xram_rsp_victim_data);
-
-                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(!r_xram_rsp_trt_buf.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 " << name() << ".XRAM_RSP_TRT_COPY> Select a slot: "
-              << " way = " << std::dec << way
-              << " / set = " << set
-              << " / inval_required = " << inval << std::endl;
-}
-#endif
-            }
-            else
-            {
-                std::cout << "VCI_MEM_CACHE ERROR "     << name()
-                          << " XRAM_RSP_TRT_COPY state" << std::endl
-                          << "bad TRT allocation"       << std::endl;
-
-                exit(0);
-            }
-            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 " << name() << ".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 " << name() << ".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 " << name() << ".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
-            // check if this is an instruction read, this means pktid is either
-            // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
-            // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
-            bool inst_read = (r_xram_rsp_trt_buf.pktid & 0x2) && r_xram_rsp_trt_buf.proc_read;
-            // check if this is a cached read, this means pktid is either
-            // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
-            // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
-            bool cached_read = (r_xram_rsp_trt_buf.pktid & 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 word=0; word<m_words ; word++)
-            {
-                m_cache_data.write(way, set, word, r_xram_rsp_trt_buf.wdata[word]);
-
-                if ( m_monitor_ok )
-                {
-                    vci_addr_t address = r_xram_rsp_trt_buf.nline<<6 | word<<2;
-                    check_monitor("XRAM_RSP_DIR_UPDT", address, r_xram_rsp_trt_buf.wdata[word]);
-                }
-            }
-            // 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 " << name() << ".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 " << name() << ".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_ll_key = r_xram_rsp_trt_buf.ll_key;
-                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 " << name() << ".XRAM_RSP_DIR_RSP> Request the TGT_RSP FSM to return data:"
-              << " rsrcid = " << std::dec << r_xram_rsp_trt_buf.srcid
-              << " / address = " << std::hex << 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_REQ;
-                else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
-
-#if DEBUG_MEMC_XRAM_RSP
-if( m_debug_xram_rsp_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".XRAM_RSP_INVAL> Send an inval request to INIT_CMD FSM:"
-              << " victim line = " << r_xram_rsp_victim_nline.read() << 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_REQ;
-                else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
-
-#if DEBUG_MEMC_XRAM_RSP
-if( m_debug_xram_rsp_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".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_REQ:
-        // Get the lock to the HEAP directory
-        {
-          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP )
-          {
-            r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
-          }
-
-#if DEBUG_MEMC_XRAM_RSP
-          if( m_debug_xram_rsp_fsm )
-          {
-            std::cout 
-              << "  <MEMC " << name() << ".XRAM_RSP_HEAP_REQ> Requesting HEAP lock "
-              << 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
-                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 " << name() << ".XRAM_RSP_HEAP_ERASE> Erase the list of copies:"
-              << " srcid = " << std::dec << entry.owner.srcid
-              << " / inst = " << std::dec << 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
-            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 " << name() << ".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 " << name() << ".XRAM_RSP_ERROR_ERASE> Error reported by XRAM / erase the TRT entry" << 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 " << name() << ".XRAM_RSP_ERROR_RSP> Request a response error to TGT_RSP FSM:"
-              << " srcid = " << std::dec << r_xram_rsp_trt_buf.srcid << std::endl;
-}
-#endif
-            }
-            break;
-        }
-    } // end swich r_xram_rsp_fsm
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    CLEANUP FSM
-    ////////////////////////////////////////////////////////////////////////////////////
-    // The CLEANUP FSM handles the cleanup request from L1 caches.
-    // It accesses the cache directory and the heap to update the list of copies.
-    ////////////////////////////////////////////////////////////////////////////////////
-
-    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 < m_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) p_vci_tgt_cleanup.be.read() << (vci_param::B*8))) |
-              (((addr_t) p_vci_tgt_cleanup.wdata.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_REQ;
-
-  #if DEBUG_MEMC_CLEANUP
-            if( m_debug_cleanup_fsm )
-            {
-              std::cout << "  <MEMC " << name() << ".CLEANUP_IDLE> Cleanup request:" << std::hex
-                << " line addr = " << 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_REQ:
-      // Get the lock to the directory
-      {
-        if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP )
-        {
-          r_cleanup_fsm = CLEANUP_DIR_LOCK;
-        }
-
-#if DEBUG_MEMC_CLEANUP
-        if( m_debug_cleanup_fsm )
-        {
-          std::cout 
-            << "  <MEMC " << name() << ".CLEANUP_DIR_REQ> Requesting DIR lock "
-            << std::endl;
-        }
-#endif
-        break;
-      }
-
-      //////////////////////
-      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;
-
-          if( entry.valid) //  hit : the copy must be cleared
-          {
-            assert( (entry.count > 0) &&
-                    "CLEANUP command received with no copy in the directory");
-
-            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_REQ;
+              r_cas_to_ixr_cmd_data[i] = r_cas_data[i].read();
             }
           }
-          else    // miss : we must check the update table
+          size_t wok_index = 0;
+          bool   wok       = !m_trt.full(wok_index);
+          if(wok)
           {
-            r_cleanup_fsm = CLEANUP_UPT_LOCK;
-          }
-
-#if DEBUG_MEMC_CLEANUP
-          if( m_debug_cleanup_fsm )
-          {
-            std::cout
-              << "  <MEMC " << name()
-              << ".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
-        }
-        else
-        {
-          std::cout << "VCI_MEM_CACHE ERROR " << name()
-            << " CLEANUP_DIR_LOCK state"
-            << " bad DIR allocation" << std::endl;
-
-          exit(0);
-        }
-        break;
-      }
-
-      ///////////////////////
-      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;
-
-        if (not r_cleanup_is_cnt.read() and not match) {
-            std::cout
-              << "VCI_MEM_CACHE ERROR : Cleanup request on a valid "
-              << "entry using linked list mode with no corresponding "
-              << "directory or heap entry"
-              << std::endl;
-
-            exit(1);
-        }
-
-        // 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();
-        entry.count       = r_cleanup_count.read() - 1;
-        entry.owner.srcid = 0;
-        entry.owner.inst  = 0;
-#if L1_MULTI_CACHE
-        entry.owner.cache_id = 0;
-#endif
-
-        m_cache_directory.write(set, way, entry);
-
-        r_cleanup_fsm = CLEANUP_RSP;
-
-#if DEBUG_MEMC_CLEANUP
-        if( m_debug_cleanup_fsm )
-        {
-          std::cout
-            << "  <MEMC " << name()
-            << ".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_REQ:
-      // Get the lock to the HEAP directory
-      {
-        if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP )
-        {
-          r_cleanup_fsm = CLEANUP_HEAP_LOCK;
-        }
-
-#if DEBUG_MEMC_CLEANUP
-        if( m_debug_cleanup_fsm )
-        {
-          std::cout 
-            << "  <MEMC " << name() << ".CLEANUP_HEAP_REQ> Requesting HEAP lock "
-            << 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;
+            r_cas_trt_index = wok_index;
+            r_cas_fsm       = CAS_BC_UPT_LOCK;
           }
           else
           {
-            std::cout << "VCI_MEM_CACHE ERROR " << name()
-              << " CLEANUP_HEAP_LOCK state"
-              << " hit but copy not found" << std::endl;
-            exit(0);
+            r_cas_fsm       = CAS_WAIT;
           }
-
-#if DEBUG_MEMC_CLEANUP
-          if( m_debug_cleanup_fsm )
+        }
+        else
+        {
+          r_cas_fsm = CAS_WAIT;
+        }
+      }
+      break;
+    }
+    ///////////////////
+    case CAS_BC_UPT_LOCK:  // register a broadcast inval transaction in UPT
+      // write data in cache in case of successful registration
+    {
+      if(r_alloc_upt_fsm.read() == ALLOC_UPT_CAS)
+      {
+        bool        wok       = false;
+        size_t      index     = 0;
+        size_t      srcid     = m_cmd_cas_srcid_fifo.read();
+        size_t      trdid     = m_cmd_cas_trdid_fifo.read();
+        size_t      pktid     = m_cmd_cas_pktid_fifo.read();
+        addr_t      nline     = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+        size_t      nb_copies = r_cas_count.read();
+
+        // register a broadcast inval transaction in UPT
+        wok = m_upt.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
+        {
+          // cache update
+          size_t way  = r_cas_way.read();
+          size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+          size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+
+          m_cache_data.write(way, set, word, r_cas_wdata.read());
+          if(r_cas_cpt.read() ==4)
+            m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
+
+          // monitor
+          if(m_monitor_ok)
           {
-            std::cout
-              << "  <MEMC " << name() << ".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;
+            vci_addr_t address = m_cmd_cas_addr_fifo.read();
+            char buf[80];
+            snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
+            check_monitor(buf, address, r_cas_wdata.read());
+            if(r_cas_cpt.read() ==4)
+              check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read());
           }
-#endif
+          r_cas_upt_index = index;
+          r_cas_fsm = CAS_BC_DIR_INVAL;
+#if DEBUG_MEMC_CAS
+          if(m_debug_cas_fsm)
+          {
+            std::cout << "  <MEMC " << name() << ".CAS_BC_UPT_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_cas_fsm = CAS_WAIT;
+        }
+      }
+      break;
+    }
+    //////////////////
+    case CAS_BC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
+    {
+      if((r_alloc_trt_fsm.read() == ALLOC_TRT_CAS) &&
+          (r_alloc_upt_fsm.read() == ALLOC_UPT_CAS) &&
+          (r_alloc_dir_fsm.read() == ALLOC_DIR_CAS))
+      {
+        // set TRT
+        m_trt.set(r_cas_trt_index.read(),
+                              false,    // PUT request to XRAM
+                              m_nline[(vci_addr_t)(m_cmd_cas_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
+        entry.owner.cache_id= 0;
+#endif
+        entry.owner.inst    = false;
+        entry.ptr           = 0;
+        size_t set          = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+        size_t way          = r_cas_way.read();
+        m_cache_directory.write(set, way, entry);
+
+        r_cas_fsm = CAS_BC_CC_SEND;
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_BC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
+                    << " / nline = " << std::hex << m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())]
+                    << " / set = " << std::dec << set << " / way = " << way << std::endl;
+        }
+#endif
+      }
+      else
+      {
+        assert(false and "LOCK ERROR in CAS_FSM, STATE = CAS_BC_DIR_INVAL");
+      }
+      break;
+    }
+    ///////////////////
+    case CAS_BC_CC_SEND:  // Request the broadcast inval to CC_SEND FSM
+    {
+      if(!r_cas_to_cc_send_multi_req.read() &&
+          !r_cas_to_cc_send_brdcast_req.read())
+      {
+        r_cas_to_cc_send_multi_req    = false;
+        r_cas_to_cc_send_brdcast_req  = true;
+        r_cas_to_cc_send_trdid        = r_cas_upt_index.read();
+        r_cas_to_cc_send_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+        r_cas_to_cc_send_index        = 0;
+        r_cas_to_cc_send_wdata        = 0;
+
+        r_cas_fsm = CAS_BC_XRAM_REQ;
+      }
+      break;
+    }
+    ////////////////////
+    case CAS_BC_XRAM_REQ: // request the IXR FSM to start a put transaction
+    {
+      if(!r_cas_to_ixr_cmd_req)
+      {
+        r_cas_to_ixr_cmd_req     = true;
+        r_cas_to_ixr_cmd_write   = true;
+        r_cas_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+        r_cas_to_ixr_cmd_trdid   = r_cas_trt_index.read();
+        r_cas_fsm                = CAS_IDLE;
+        cmd_cas_fifo_get         = true;
+        r_cas_cpt                = 0;
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_BC_XRAM_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
+                    << " / nline = " << m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()]
+                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
+        }
+#endif
+      }
+      else
+      {
+        std::cout << "MEM_CACHE, CAS_BC_XRAM_REQ state : request should not have been previously set"
+                  << std::endl;
+      }
+      break;
+    }
+    /////////////////
+    case CAS_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
+    {
+      if(!r_cas_to_tgt_rsp_req)
+      {
+        cmd_cas_fifo_get     = true;
+        r_cas_cpt              = 0;
+        r_cas_to_tgt_rsp_req = true;
+        r_cas_to_tgt_rsp_data  = 1;
+        r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
+        r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
+        r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
+        r_cas_fsm              = CAS_IDLE;
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
+        }
+#endif
+      }
+      break;
+    }
+    ////////////////////
+    case CAS_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
+    {
+      if(!r_cas_to_tgt_rsp_req)
+      {
+        cmd_cas_fifo_get       = true;
+        r_cas_cpt              = 0;
+        r_cas_to_tgt_rsp_req = true;
+        r_cas_to_tgt_rsp_data  = 0;
+        r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
+        r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
+        r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
+        r_cas_fsm              = CAS_IDLE;
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
+        }
+#endif
+      }
+      break;
+    }
+    /////////////////////
+    case CAS_MISS_TRT_LOCK:         // cache miss : request access to transaction Table
+    {
+      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
+      {
+        size_t   index = 0;
+        bool hit_read = m_trt.hit_read(
+                          m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()],index);
+        bool hit_write = m_trt.hit_write(
+                           m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()]);
+        bool wok = !m_trt.full(index);
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_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_cas_fsm = CAS_WAIT;
         }
         else
         {
-          std::cout << "VCI_MEM_CACHE ERROR " << name()
-            << " CLEANUP_HEAP_LOCK state"
-            << " bad HEAP allocation" << std::endl;
-
-          exit(0);
+          r_cas_trt_index = index;
+          r_cas_fsm       = CAS_MISS_TRT_SET;
+        }
+      }
+      break;
+    }
+    ////////////////////
+    case CAS_MISS_TRT_SET: // register the GET transaction in TRT
+    {
+      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
+      {
+        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(0);
+          data_vector.push_back(0);
+        }
+
+        m_trt.set(r_cas_trt_index.read(),
+                              true,   // read request
+                              m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()],
+                              m_cmd_cas_srcid_fifo.read(),
+                              m_cmd_cas_trdid_fifo.read(),
+                              m_cmd_cas_pktid_fifo.read(),
+                              false,    // write request from processor
+                              0,
+                              0,
+                              be_vector,
+                              data_vector);
+        r_cas_fsm = CAS_MISS_XRAM_REQ;
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_SET> Register a GET transaction in TRT" << std::hex
+                    << " / nline = " << m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()]
+                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
+        }
+#endif
+      }
+      break;
+    }
+    //////////////////////
+    case CAS_MISS_XRAM_REQ:  // request the IXR_CMD FSM to fetch the missing line
+    {
+      if(!r_cas_to_ixr_cmd_req)
+      {
+        r_cas_to_ixr_cmd_req        = true;
+        r_cas_to_ixr_cmd_write      = false;
+        r_cas_to_ixr_cmd_trdid      = r_cas_trt_index.read();
+        r_cas_to_ixr_cmd_nline      = m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()];
+        r_cas_fsm                   = CAS_WAIT;
+
+#if DEBUG_MEMC_CAS
+        if(m_debug_cas_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".CAS_MISS_XRAM_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
+                    << " / nline = " << m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()]
+                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
+        }
+#endif
+      }
+      break;
+    }
+  } // end switch r_cas_fsm
+
+
+  //////////////////////////////////////////////////////////////////////////////
+  //    CC_SEND FSM
+  //////////////////////////////////////////////////////////////////////////////
+  // The CC_SEND fsm controls the DSPIN initiator port on the coherence
+  // network, used to update or invalidate cache lines in L1 caches.
+  //
+  // This fsm is used also to acknowledge CLEANUP a command after request from
+  // the CLEANUP fsm.
+  //
+  // It implements a round-robin priority between the four possible client FSMs
+  // XRAM_RSP, WRITE, CAS and CLEANUP. Each FSM can request the next services:
+  // - r_xram_rsp_to_cc_send_multi_req : multi-inval
+  //   r_xram_rsp_to_cc_send_brdcast_req : broadcast-inval
+  // - r_write_to_cc_send_multi_req : multi-update
+  //   r_write_to_cc_send_brdcast_req : broadcast-inval
+  // - r_cas_to_cc_send_multi_req : multi-update
+  //   r_cas_to_cc_send_brdcast_req : broadcast-inval
+  // - r_cleanup_to_cc_send_req : cleanup acknowledgement
+  //
+  // An inval request is a double DSPIN flit command containing:
+  // 1. the index of the line to be invalidated.
+  //
+  // An update request is a multi-flit DSPIN command containing:
+  // 1. the index of the cache line to be updated.
+  // 2. the index of the first modified word in the line.
+  // 3. the data to update
+  ///////////////////////////////////////////////////////////////////////////////
+
+  switch(r_cc_send_fsm.read())
+  {
+    case CC_SEND_WRITE_IDLE:
+      {
+        // XRAM_RSP FSM has highest priority
+        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
+            r_xram_rsp_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(r_xram_rsp_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(m_cas_to_cc_send_inst_fifo.rok() ||
+            r_cas_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
+          m_cpt_update++;
+          break;
+        }
+
+        if(r_cas_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if (r_cleanup_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
+          break;
+        }
+
+        if(m_write_to_cc_send_inst_fifo.rok() ||
+            r_write_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
+          m_cpt_update++;
+          break;
+        }
+
+        if(r_write_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
+          m_cpt_inval++;
         }
         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;
+    case CC_SEND_XRAM_RSP_IDLE:
+      {
+        // CAS FSM has highest priority
+        if(m_cas_to_cc_send_inst_fifo.rok() ||
+            r_cas_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
+          m_cpt_update++;
+          break;
+        }
+
+        if(r_cas_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(r_cleanup_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
+          break;
+        }
+
+        if(m_write_to_cc_send_inst_fifo.rok() ||
+            r_write_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
+          m_cpt_update++;
+          break;
+        }
+
+        if(r_write_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
+            r_xram_rsp_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(r_xram_rsp_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
+          m_cpt_inval++;
+        }
+
+        break;
+      }
+
+    case CC_SEND_CAS_IDLE:
+      {
+        // CLEANUP FSM has highest priority
+        if(r_cleanup_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
+          break;
+        }
+
+        if(m_write_to_cc_send_inst_fifo.rok() ||
+            r_write_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
+          m_cpt_update++;
+          break;
+        }
+
+        if(r_write_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
+            r_xram_rsp_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(r_xram_rsp_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(m_cas_to_cc_send_inst_fifo.rok() ||
+            r_cas_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
+          m_cpt_update++;
+          break;
+        }
+
+        if(r_cas_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
+          m_cpt_inval++;
+        }
+        break;
+      }
+
+    case CC_SEND_CLEANUP_IDLE:
+      {
+        // WRITE FSM has highest priority
+        if(m_write_to_cc_send_inst_fifo.rok() ||
+            r_write_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
+          m_cpt_update++;
+          break;
+        }
+
+        if(r_write_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
+            r_xram_rsp_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(r_xram_rsp_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(m_cas_to_cc_send_inst_fifo.rok() ||
+            r_cas_to_cc_send_multi_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
+          m_cpt_update++;
+          break;
+        }
+
+        if(r_cas_to_cc_send_brdcast_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
+          m_cpt_inval++;
+          break;
+        }
+
+        if(r_cleanup_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
+        }
+
+        break;
+      }
+
+    case CC_SEND_CLEANUP_ACK:
+      {
+        // send only flit for a cleanup acknowledgement (from CLEANUP FSM)
+        if(not p_dspin_out.read) break;
+
+        r_cleanup_to_cc_send_req = false;
+        r_cc_send_fsm = CC_SEND_CLEANUP_IDLE;
+
+#if DEBUG_MEMC_CC_SEND
+        if(m_debug_cc_send_fsm)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << ".CC_SEND_CLEANUP_ACK> Cleanup Acknowledgement for srcid "
+            << r_cleanup_to_cc_send_srcid.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+    case CC_SEND_XRAM_RSP_INVAL_HEADER:
+      {
+        // send first flit multi-inval (from XRAM_RSP FSM)
+        if(m_xram_rsp_to_cc_send_inst_fifo.rok())
+        {
+          if(not p_dspin_out.read) break;
+
+          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_NLINE;
+          break;
+        }
+
+        if(r_xram_rsp_to_cc_send_multi_req.read())
+        {
+          r_xram_rsp_to_cc_send_multi_req = false;
+        }
+
+        r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE;
+        break;
+      }
+
+    case CC_SEND_XRAM_RSP_INVAL_NLINE:
+      {
+        // send second flit multi-inval (from XRAM_RSP FSM)
+        if(not p_dspin_out.read) break;
+
+        m_cpt_inval_mult++;
+
+        r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
+
+#if DEBUG_MEMC_CC_SEND
+        if(m_debug_cc_send_fsm)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << ".CC_SEND_XRAM_RSP_INVAL_NLINE> Broadcast-Inval for line "
+            << r_xram_rsp_to_cc_send_nline.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+    case CC_SEND_XRAM_RSP_BRDCAST_HEADER:
+      {
+        // send first flit broadcast-inval (from XRAM_RSP FSM)
+        if(not p_dspin_out.read) break;
+
+        r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_NLINE;
+        break;
+      }
+
+    case CC_SEND_XRAM_RSP_BRDCAST_NLINE:
+      {
+        // send second flit broadcast-inval (from XRAM_RSP FSM)
+        if(not p_dspin_out.read) break;
+
+        m_cpt_inval_brdcast++;
+
+        r_xram_rsp_to_cc_send_brdcast_req = false;
+        r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE;
+
+#if DEBUG_MEMC_CC_SEND
+        if(m_debug_cc_send_fsm)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << ".CC_SEND_XRAM_RSP_BRDCAST_NLINE> Broadcast-Inval for line "
+            << r_xram_rsp_to_cc_send_nline.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+    case CC_SEND_WRITE_BRDCAST_HEADER:
+      {
+        // send first flit broadcast-inval (from WRITE FSM)
+        if(not p_dspin_out.read) break;
+
+        r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_NLINE;
+        break;
+      }
+
+    case CC_SEND_WRITE_BRDCAST_NLINE:
+      {
+        // send second flit broadcast-inval (from WRITE FSM)
+        if(not p_dspin_out.read) break;
+
+        m_cpt_inval_brdcast++;
+
+        r_write_to_cc_send_brdcast_req = false;
+        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
+
+#if DEBUG_MEMC_CC_SEND
+        if(m_debug_cc_send_fsm)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << ".CC_SEND_WRITE_BRDCAST_NLINE> Broadcast-Inval for line "
+            << r_write_to_cc_send_nline.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+    case CC_SEND_WRITE_UPDT_HEADER:
+      {
+        // send first flit for a multi-update (from WRITE FSM)
+        if(m_write_to_cc_send_inst_fifo.rok())
+        {
+          if(not p_dspin_out.read) break;
+
+          r_cc_send_fsm = CC_SEND_WRITE_UPDT_NLINE;
+          break;
+        }
+
+        if(r_write_to_cc_send_multi_req.read())
+        {
+          r_write_to_cc_send_multi_req = false;
+        }
+
+        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
+        break;
+      }
+
+    case CC_SEND_WRITE_UPDT_NLINE:
+      {
+        // send second flit for a multi-update (from WRITE FSM)
+        if(not p_dspin_out.read) break;
+
+        m_cpt_update_mult++;
+
+        r_cc_send_cpt = 0;
+        r_cc_send_fsm = CC_SEND_WRITE_UPDT_DATA;
+
+#if DEBUG_MEMC_CC_SEND
+        if(m_debug_cc_send_fsm)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << ".CC_SEND_WRITE_UPDT_NLINE> Multicast-Update for line "
+            << r_write_to_cc_send_nline.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+    case CC_SEND_WRITE_UPDT_DATA:
+      {
+        // send N data flits for a multi-update (from WRITE FSM)
+        if(not p_dspin_out.read) break;
+
+        if(r_cc_send_cpt.read() == (r_write_to_cc_send_count.read()-1))
+        {
+          write_to_cc_send_fifo_get = true;
+          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
+          break;
+        }
+
+        r_cc_send_cpt = r_cc_send_cpt.read() + 1;
+        break;
+      }
+
+    case CC_SEND_CAS_BRDCAST_HEADER:
+      {
+        // send first flit for a broadcast-inval (from CAS FSM)
+        if(not p_dspin_out.read) break;
+
+        r_cc_send_fsm = CC_SEND_CAS_BRDCAST_NLINE;
+        break;
+      }
+
+    case CC_SEND_CAS_BRDCAST_NLINE:
+      {
+        // send second flit broadcast-inval (from CAS FSM)
+        if(not p_dspin_out.read) break;
+
+        m_cpt_inval_brdcast++;
+
+        r_cas_to_cc_send_brdcast_req = false;
+        r_cc_send_fsm = CC_SEND_CAS_IDLE;
+
+#if DEBUG_MEMC_CC_SEND
+        if(m_debug_cc_send_fsm)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << ".CC_SEND_CAS_BRDCAST_NLINE> Broadcast-Inval for line "
+            << r_cas_to_cc_send_nline.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+    case CC_SEND_CAS_UPDT_HEADER:
+      {
+        // send first flit for a multi-update (from CAS FSM)
+        if(m_cas_to_cc_send_inst_fifo.rok())
+        {
+          if(not p_dspin_out.read) break;
+
+          r_cc_send_fsm = CC_SEND_CAS_UPDT_NLINE;
+          break;
+        }
+
+        // no more packets to send for the multi-update
+        if(r_cas_to_cc_send_multi_req.read())
+        {
+          r_cas_to_cc_send_multi_req = false;
+        }
+
+        r_cc_send_fsm = CC_SEND_CAS_IDLE;
+        break;
+      }
+
+    case CC_SEND_CAS_UPDT_NLINE:
+      {
+        // send second flit for a multi-update (from CAS FSM)
+        if(not p_dspin_out.read) break;
+
+        m_cpt_update_mult++;
+
+        r_cc_send_cpt = 0;
+        r_cc_send_fsm = CC_SEND_CAS_UPDT_DATA;
+
+#if DEBUG_MEMC_CC_SEND
+        if(m_debug_cc_send_fsm)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << ".CC_SEND_CAS_UPDT_NLINE> Multicast-Update for line "
+            << r_cas_to_cc_send_nline.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+    case CC_SEND_CAS_UPDT_DATA:
+      {
+        // send first data for a multi-update (from CAS FSM)
+        if(not p_dspin_out.read) break;
+
+        if(r_cas_to_cc_send_is_long.read())
+        {
+          r_cc_send_fsm = CC_SEND_CAS_UPDT_DATA_HIGH;
+          break;
+        }
+
+        cas_to_cc_send_fifo_get = true;
+        r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
+        break;
+      }
+
+    case CC_SEND_CAS_UPDT_DATA_HIGH:
+      {
+        // send second data for a multi-update (from CAS FSM)
+        if(not p_dspin_out.read) break;
+
+        cas_to_cc_send_fifo_get = true;
+        r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
+        break;
+      }
+  }
+  // end switch r_cc_send_fsm
+
+  //////////////////////////////////////////////////////////////////////////////
+  //    CC_RECEIVE FSM
+  //////////////////////////////////////////////////////////////////////////////
+  // The CC_RECEIVE fsm controls the DSPIN target port on the coherence
+  // network.
+  ///////////////////////////////////////////////////////////////////////////////
+
+  switch(r_cc_receive_fsm.read())
+  {
+    case CC_RECEIVE_IDLE:
+      {
+        if(not p_dspin_in.write) break;
+
+        uint8_t type =
+          DspinDhccpParam::dspin_get(
+              p_dspin_in.data.read(),
+              DspinDhccpParam::FROM_L1_TYPE);
+
+        if((type == DspinDhccpParam::TYPE_CLEANUP_DATA) ||
+           (type == DspinDhccpParam::TYPE_CLEANUP_INST) )
+        { 
+          r_cc_receive_fsm = CC_RECEIVE_CLEANUP;
+          break;
+        }
+        
+        if(type == DspinDhccpParam::TYPE_MULTI_ACK)
+        {
+          r_cc_receive_fsm = CC_RECEIVE_MULTI_ACK;
+          break;
+        }
+
+        assert(
+            false && 
+            "VCI_MEM_CACHE ERROR: Incorrect type in coherence request from "
+            "L1 Cache");
+        
+        break;
+      }
+    case CC_RECEIVE_CLEANUP:
+      {
+        // wait for a valid cleanup flit
+        // wait for a WOK in the CC_RECEIVE to CLEANUP fifo
+        if(not p_dspin_in.write or not m_cc_receive_to_cleanup_fifo.wok()) break;
+
+        bool eop = (
+            DspinDhccpParam::dspin_get(
+              p_dspin_in.data.read(),
+              DspinDhccpParam::FROM_L1_EOP)
+            == 0x1);
+
+        cc_receive_to_cleanup_fifo_put = true;
+        if(eop)
+        {
+          r_cc_receive_fsm = CC_RECEIVE_IDLE;
+        }
+
+        break;
+      }
+    case CC_RECEIVE_MULTI_ACK:
+      {
+        // wait for a valid multicast acknowledgement flit
+        // wait for a WOK in the CC_RECEIVE to MULTI_ACK fifo
+        if(not p_dspin_in.write or not m_cc_receive_to_multi_ack_fifo.wok()) break;
+
+        bool eop = (
+            DspinDhccpParam::dspin_get(
+              p_dspin_in.data.read(),
+              DspinDhccpParam::FROM_L1_EOP) 
+            == 0x1);
+
+        cc_receive_to_multi_ack_fifo_put  = true;
+        if(eop)
+        {
+          r_cc_receive_fsm = CC_RECEIVE_IDLE;
+        }
+
+        break;
+      }
+    default:
+      {
+        assert(
+            false &&
+            "VCI_MEM_CACHE ERROR: Invalid state in CC_RECEIVE FSM");
+      }
+  }
+  /////////////////////////////////////////////////////////////////////
+  //    TGT_RSP FSM
+  /////////////////////////////////////////////////////////////////////
+  // The TGT_RSP fsm sends the responses on the VCI target port
+  // with a round robin priority between six requests :
+  // - r_read_to_tgt_rsp_req
+  // - r_write_to_tgt_rsp_req
+  // - r_cas_to_tgt_rsp_req
+  // - r_cleanup_to_tgt_rsp_req
+  // - r_xram_rsp_to_tgt_rsp_req
+  // - r_multi_ack_to_tgt_rsp_req
+  // The  ordering is :  read > write > cas > xram > init > cleanup
+  /////////////////////////////////////////////////////////////////////
+
+  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_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
+      else if(r_xram_rsp_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_XRAM;
+        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+      }
+      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
+      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+      else if(r_read_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_READ;
+        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+      }
+      break;
+    }
+    ////////////////////////
+    case TGT_RSP_WRITE_IDLE:  // cas requests have the highest priority
+    {
+      if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS;
+      else if(r_xram_rsp_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_XRAM;
+        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+      }
+      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
+      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+      else if(r_read_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_READ;
+        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+      }
+
+      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+      break;
+    }
+    ///////////////////////
+    case TGT_RSP_CAS_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();
+      }
+      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
+      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+      else if(r_read_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_READ;
+        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+      }
+      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
+      break;
+    }
+    ///////////////////////
+    case TGT_RSP_XRAM_IDLE:   // init requests have the highest priority
+    {
+
+      if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
+      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+      else if(r_read_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_READ;
+        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+      }
+      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
+      else if(r_xram_rsp_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_XRAM;
+        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+      }
+      break;
+    }
+    ///////////////////////
+    case TGT_RSP_INIT_IDLE:   // cleanup requests have the highest priority
+    {
+      if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+      else if(r_read_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_READ;
+        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+      }
+      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
+      else if(r_xram_rsp_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_XRAM;
+        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+      }
+      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT;
+      break;
+    }
+    ///////////////////////
+    case TGT_RSP_CLEANUP_IDLE:    // read requests have the highest priority
+    {
+      if(r_read_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_READ;
+        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+      }
+      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
+      else if(r_xram_rsp_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_XRAM;
+        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+      }
+      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
+      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+      break;
+    }
+    //////////////////
+    case TGT_RSP_READ:    // send the response to a read
+    {
+      if(p_vci_tgt.rspack)
+      {
+
+#if DEBUG_MEMC_TGT_RSP
+        if(m_debug_tgt_rsp_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".TGT_RSP_READ> Read response"
+                    << " / rsrcid = " << std::dec << r_read_to_tgt_rsp_srcid.read()
+                    << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
+                    << " / rpktid = " << r_read_to_tgt_rsp_pktid.read()
+                    << " / rdata = " << std::hex << 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 " << name() << ".TGT_RSP_WRITE> Write response"
+                    << " / rsrcid = " << std::dec << r_write_to_tgt_rsp_srcid.read()
+                    << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read()
+                    << " / rpktid = " << r_write_to_tgt_rsp_pktid.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 " << name() << ".TGT_RSP_CLEANUP> Cleanup response"
+                    << " / rsrcid = " << std::dec << r_cleanup_to_tgt_rsp_srcid.read()
+                    << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read()
+                    << " / rpktid = " << r_cleanup_to_tgt_rsp_pktid.read() << std::endl;
+        }
+#endif
+        r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
+        r_cleanup_to_tgt_rsp_req = false;
+      }
+      break;
+    }
+    //////////////////
+    case TGT_RSP_CAS:    // send one atomic word response
+    {
+      if(p_vci_tgt.rspack)
+      {
+
+#if DEBUG_MEMC_TGT_RSP
+        if(m_debug_tgt_rsp_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".TGT_RSP_CAS> CAS response"
+                    << " / rsrcid = " << std::dec << r_cas_to_tgt_rsp_srcid.read()
+                    << " / rtrdid = " << r_cas_to_tgt_rsp_trdid.read()
+                    << " / rpktid = " << r_cas_to_tgt_rsp_pktid.read() << std::endl;
+        }
+#endif
+        r_tgt_rsp_fsm = TGT_RSP_CAS_IDLE;
+        r_cas_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 " << name() << ".TGT_RSP_XRAM> Response following XRAM access"
+                    << " / rsrcid = " << std::dec << r_xram_rsp_to_tgt_rsp_srcid.read()
+                    << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
+                    << " / rpktid = " << r_xram_rsp_to_tgt_rsp_pktid.read()
+                    << " / rdata = " << std::hex << r_xram_rsp_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_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 write response after coherence transaction
+    {
+      if(p_vci_tgt.rspack)
+      {
+
+#if DEBUG_MEMC_TGT_RSP
+        if(m_debug_tgt_rsp_fsm)
+        {
+          std::cout << "  <MEMC " << name() << ".TGT_RSP_INIT> Write response after coherence transaction"
+                    << " / rsrcid = " << std::dec << r_multi_ack_to_tgt_rsp_srcid.read()
+                    << " / rtrdid = " << r_multi_ack_to_tgt_rsp_trdid.read()
+                    << " / rpktid = " << r_multi_ack_to_tgt_rsp_pktid.read() << std::endl;
+        }
+#endif
+        r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
+        r_multi_ack_to_tgt_rsp_req = false;
+      }
+      break;
+    }
+  } // end switch tgt_rsp_fsm
+
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    ALLOC_UPT FSM
+  ////////////////////////////////////////////////////////////////////////////////////
+  // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
+  // with a round robin priority between three FSMs : MULTI_ACK > WRITE > XRAM_RSP > CLEANUP
+  // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
+  // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
+  // - The MULTI_ACK FSM complete those trasactions and erase the UPT entry.
+  // - The CLEANUP  FSM decrement an entry in UPT.
+  // The resource is always allocated.
+  /////////////////////////////////////////////////////////////////////////////////////
+
+  switch(r_alloc_upt_fsm.read())
+  {
+
+      ////////////////////////
+    case ALLOC_UPT_MULTI_ACK:
+      if((r_multi_ack_fsm.read() != MULTI_ACK_UPT_LOCK) &&
+          (r_multi_ack_fsm.read() != MULTI_ACK_UPT_CLEAR))
+      {
+        if((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+            (r_write_fsm.read() == WRITE_BC_UPT_LOCK))
+          r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+
+        else if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+
+        else if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
+                (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
+          r_alloc_upt_fsm = ALLOC_UPT_CAS;
+      }
+      break;
+
+      /////////////////////
+    case ALLOC_UPT_WRITE:
+      if((r_write_fsm.read() != WRITE_UPT_LOCK) &&
+          (r_write_fsm.read() != WRITE_BC_UPT_LOCK))
+      {
+        if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+
+        else if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+
+        else if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
+                (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
+          r_alloc_upt_fsm = ALLOC_UPT_CAS;
+
+        else if(r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
+      }
+      break;
+
+      ////////////////////////
+    case ALLOC_UPT_XRAM_RSP:
+      if(r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)
+      {
+        if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+
+        else if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
+                (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
+          r_alloc_upt_fsm = ALLOC_UPT_CAS;
+
+        else if(r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
+
+        else if((r_write_fsm.read() == WRITE_UPT_LOCK)   ||
+                (r_write_fsm.read() == WRITE_BC_UPT_LOCK))
+          r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+      }
+      break;
+
+      //////////////////////////
+    case ALLOC_UPT_CLEANUP:
+      if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK)
+      {
+        if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
+            (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
+          r_alloc_upt_fsm = ALLOC_UPT_CAS;
+
+        else if(r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
+
+        else if((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                (r_write_fsm.read() == WRITE_BC_UPT_LOCK))
+          r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+      }
+      break;
+
+      //////////////////////////
+    case ALLOC_UPT_CAS:
+      if((r_cas_fsm.read() != CAS_UPT_LOCK) &&
+          (r_cas_fsm.read() != CAS_BC_UPT_LOCK))
+      {
+        if(r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
+
+        else if((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                (r_write_fsm.read() == WRITE_BC_UPT_LOCK))
+          r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+
+        else if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
+          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+      }
+      break;
+
+  } // end switch r_alloc_upt_fsm
+
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    ALLOC_DIR FSM
+  ////////////////////////////////////////////////////////////////////////////////////
+  // The ALLOC_DIR FSM allocates the access to the directory and
+  // the data cache with a round robin priority between 5 user FSMs :
+  // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
+  // The ressource is always allocated.
+  /////////////////////////////////////////////////////////////////////////////////////
+
+  switch(r_alloc_dir_fsm.read())
+  {
+    case ALLOC_DIR_RESET:
+      // Initializes the directory one SET each cycle. All the WAYS of a SET are
+      // initialize in parallel
+
+      r_alloc_dir_reset_cpt.write(r_alloc_dir_reset_cpt.read() + 1);
+
+      if(r_alloc_dir_reset_cpt.read() == (m_sets - 1))
+      {
+        m_cache_directory.init();
+
+        r_alloc_dir_fsm = ALLOC_DIR_READ;
+      }
+      break;
+
+      ////////////////////
+    case ALLOC_DIR_READ:
+      if(((r_read_fsm.read()        != READ_DIR_REQ)   &&
+          (r_read_fsm.read()        != READ_DIR_LOCK)   &&
+          (r_read_fsm.read()        != READ_TRT_LOCK)   &&
+          (r_read_fsm.read()        != READ_HEAP_REQ))
+          ||
+          ((r_read_fsm.read()       == READ_TRT_LOCK)   &&
+           (r_alloc_trt_fsm.read()  == ALLOC_TRT_READ)))
+      {
+        if(r_write_fsm.read() == WRITE_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+
+        else if(r_cas_fsm.read() == CAS_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_CAS;
+
+        else if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
+          r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+      }
+      break;
+
+      /////////////////////
+    case ALLOC_DIR_WRITE:
+      if(((r_write_fsm.read()       != WRITE_DIR_REQ)  &&
+          (r_write_fsm.read()       != WRITE_DIR_LOCK)  &&
+          (r_write_fsm.read()       != WRITE_DIR_READ)  &&
+          (r_write_fsm.read()       != WRITE_DIR_HIT)  &&
+          (r_write_fsm.read()       != WRITE_BC_TRT_LOCK)  &&
+          (r_write_fsm.read()       != WRITE_BC_UPT_LOCK)  &&
+          (r_write_fsm.read()       != WRITE_MISS_TRT_LOCK)  &&
+          (r_write_fsm.read()       != WRITE_UPT_LOCK)  &&
+          (r_write_fsm.read()       != WRITE_UPT_HEAP_LOCK))
+          ||
+          ((r_write_fsm.read()      == WRITE_UPT_HEAP_LOCK)  &&
+           (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE))
+          ||
+          ((r_write_fsm.read()      == WRITE_MISS_TRT_LOCK)  &&
+           (r_alloc_trt_fsm.read()  == ALLOC_TRT_WRITE)))
+      {
+        if(r_cas_fsm.read() == CAS_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_CAS;
+
+        else if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
+          r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+
+        else if(r_read_fsm.read() == READ_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_READ;
+      }
+      break;
+
+      ////////////////////
+    case ALLOC_DIR_CAS:
+      if(((r_cas_fsm.read()         != CAS_DIR_REQ)  &&
+          (r_cas_fsm.read()         != CAS_DIR_LOCK)  &&
+          (r_cas_fsm.read()         != CAS_DIR_HIT_READ)  &&
+          (r_cas_fsm.read()         != CAS_DIR_HIT_COMPARE)  &&
+          (r_cas_fsm.read()         != CAS_DIR_HIT_WRITE)  &&
+          (r_cas_fsm.read()         != CAS_BC_TRT_LOCK)  &&
+          (r_cas_fsm.read()         != CAS_BC_UPT_LOCK)  &&
+          (r_cas_fsm.read()         != CAS_MISS_TRT_LOCK)  &&
+          (r_cas_fsm.read()         != CAS_UPT_LOCK)  &&
+          (r_cas_fsm.read()         != CAS_UPT_HEAP_LOCK))
+          ||
+          ((r_cas_fsm.read()        == CAS_UPT_HEAP_LOCK)  &&
+           (r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS))
+          ||
+          ((r_cas_fsm.read()        == CAS_MISS_TRT_LOCK)  &&
+           (r_alloc_trt_fsm.read()  == ALLOC_TRT_CAS)))
+      {
+        if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
+          r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+
+        else if(r_read_fsm.read() == READ_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_READ;
+
+        else if(r_write_fsm.read() == WRITE_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+      }
+      break;
+
+      ///////////////////////
+    case ALLOC_DIR_CLEANUP:
+      if((r_cleanup_fsm.read() != CLEANUP_DIR_REQ) &&
+          (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
+          (r_cleanup_fsm.read() != CLEANUP_HEAP_REQ) &&
+          (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK))
+      {
+        if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
+          r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+
+        else if(r_read_fsm.read() == READ_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_READ;
+
+        else if(r_write_fsm.read() == WRITE_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+
+        else if(r_cas_fsm.read() == CAS_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_CAS;
+      }
+      break;
+
+      ////////////////////////
+    case ALLOC_DIR_XRAM_RSP:
+      if((r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK) &&
+          (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY) &&
+          (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
+      {
+        if(r_read_fsm.read() == READ_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_READ;
+
+        else if(r_write_fsm.read() == WRITE_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+
+        else if(r_cas_fsm.read() == CAS_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_CAS;
+
+        else if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
+          r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+      }
+      break;
+
+  } // end switch alloc_dir_fsm
+
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    ALLOC_TRT FSM
+  ////////////////////////////////////////////////////////////////////////////////////
+  // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
+  // with a round robin priority between 4 user FSMs :
+  // The cyclic priority is READ > WRITE > CAS > XRAM_RSP
+  // The ressource is always allocated.
+  ///////////////////////////////////////////////////////////////////////////////////
+
+  switch(r_alloc_trt_fsm.read())
+  {
+      ////////////////////
+    case ALLOC_TRT_READ:
+      if(r_read_fsm.read() != READ_TRT_LOCK)
+      {
+        if((r_write_fsm.read() == WRITE_MISS_TRT_LOCK) ||
+            (r_write_fsm.read() == WRITE_BC_TRT_LOCK))
+          r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+
+        else if((r_cas_fsm.read() == CAS_MISS_TRT_LOCK) ||
+                (r_cas_fsm.read() == CAS_BC_TRT_LOCK))
+          r_alloc_trt_fsm = ALLOC_TRT_CAS;
+
+        else if((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) &&
+                (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
+          r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+
+        else if((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
+          r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+      }
+      break;
+
+      /////////////////////
+    case ALLOC_TRT_WRITE:
+      if((r_write_fsm.read() != WRITE_MISS_TRT_LOCK) &&
+          (r_write_fsm.read() != WRITE_BC_TRT_LOCK) &&
+          (r_write_fsm.read() != WRITE_BC_UPT_LOCK))
+      {
+        if((r_cas_fsm.read() == CAS_MISS_TRT_LOCK) ||
+            (r_cas_fsm.read() == CAS_BC_TRT_LOCK))
+          r_alloc_trt_fsm = ALLOC_TRT_CAS;
+
+        else if((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) &&
+                (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
+          r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+
+        else if((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
+          r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+
+        else if(r_read_fsm.read() == READ_TRT_LOCK)
+          r_alloc_trt_fsm = ALLOC_TRT_READ;
+      }
+      break;
+
+      ////////////////////
+    case ALLOC_TRT_CAS:
+      if((r_cas_fsm.read() != CAS_MISS_TRT_LOCK) &&
+          (r_cas_fsm.read() != CAS_BC_TRT_LOCK) &&
+          (r_cas_fsm.read() != CAS_BC_UPT_LOCK))
+      {
+        if((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) &&
+            (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
+          r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+
+        else if((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
+          r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+
+        else if(r_read_fsm.read() == READ_TRT_LOCK)
+          r_alloc_trt_fsm = ALLOC_TRT_READ;
+
+        else if((r_write_fsm.read() == WRITE_MISS_TRT_LOCK) ||
+                (r_write_fsm.read() == WRITE_BC_TRT_LOCK))
+          r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+      }
+      break;
+
+      ////////////////////////
+    case ALLOC_TRT_XRAM_RSP:
+      if(((r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_LOCK)  ||
+          (r_alloc_dir_fsm.read() != ALLOC_DIR_XRAM_RSP)) &&
+          (r_xram_rsp_fsm.read()  != XRAM_RSP_TRT_COPY)  &&
+          (r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_UPDT)  &&
+          (r_xram_rsp_fsm.read()  != XRAM_RSP_INVAL_LOCK))
+      {
+        if((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+            (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
+          r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+
+        else if(r_read_fsm.read() == READ_TRT_LOCK)
+          r_alloc_trt_fsm = ALLOC_TRT_READ;
+
+        else if((r_write_fsm.read() == WRITE_MISS_TRT_LOCK) ||
+                (r_write_fsm.read() == WRITE_BC_TRT_LOCK))
+          r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+
+        else if((r_cas_fsm.read() == CAS_MISS_TRT_LOCK) ||
+                (r_cas_fsm.read() == CAS_BC_TRT_LOCK))
+          r_alloc_trt_fsm = ALLOC_TRT_CAS;
+      }
+      break;
+
+      ////////////////////////
+    case ALLOC_TRT_IXR_RSP:
+      if((r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
+          (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ))
+      {
+        if(r_read_fsm.read() == READ_TRT_LOCK)
+          r_alloc_trt_fsm = ALLOC_TRT_READ;
+
+        else if((r_write_fsm.read() == WRITE_MISS_TRT_LOCK) ||
+                (r_write_fsm.read() == WRITE_BC_TRT_LOCK))
+          r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+
+        else if((r_cas_fsm.read() == CAS_MISS_TRT_LOCK) ||
+                (r_cas_fsm.read() == CAS_BC_TRT_LOCK))
+          r_alloc_trt_fsm = ALLOC_TRT_CAS;
+
+        else if((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) &&
+                (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
+          r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+      }
+      break;
+
+  } // end switch alloc_trt_fsm
+
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    ALLOC_HEAP FSM
+  ////////////////////////////////////////////////////////////////////////////////////
+  // 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 > CAS > CLEANUP > XRAM_RSP
+  // The ressource is always allocated.
+  /////////////////////////////////////////////////////////////////////////////////////
+
+  switch(r_alloc_heap_fsm.read())
+  {
+      ////////////////////
+    case ALLOC_HEAP_RESET:
+      // Initializes the heap one ENTRY each cycle.
+
+      r_alloc_heap_reset_cpt.write(r_alloc_heap_reset_cpt.read() + 1);
+
+      if(r_alloc_heap_reset_cpt.read() == (m_heap_size-1))
+      {
+        m_heap.init();
+
+        r_alloc_heap_fsm = ALLOC_HEAP_READ;
+      }
+      break;
+
+      ////////////////////
+    case ALLOC_HEAP_READ:
+      if((r_read_fsm.read() != READ_HEAP_REQ) &&
+          (r_read_fsm.read() != READ_HEAP_LOCK) &&
+          (r_read_fsm.read() != READ_HEAP_ERASE))
+      {
+        if(r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)
+          r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+
+        else if(r_cas_fsm.read() == CAS_UPT_HEAP_LOCK)
+          r_alloc_heap_fsm = ALLOC_HEAP_CAS;
+
+        else if(r_cleanup_fsm.read() == CLEANUP_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+      }
+      break;
+
+      /////////////////////
+    case ALLOC_HEAP_WRITE:
+      if((r_write_fsm.read() != WRITE_UPT_HEAP_LOCK) &&
+          (r_write_fsm.read() != WRITE_UPT_REQ) &&
+          (r_write_fsm.read() != WRITE_UPT_NEXT))
+      {
+        if(r_cas_fsm.read() == CAS_UPT_HEAP_LOCK)
+          r_alloc_heap_fsm = ALLOC_HEAP_CAS;
+
+        else if(r_cleanup_fsm.read() == CLEANUP_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+
+        else if(r_read_fsm.read() == READ_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_READ;
+      }
+      break;
+
+      ////////////////////
+    case ALLOC_HEAP_CAS:
+      if((r_cas_fsm.read() != CAS_UPT_HEAP_LOCK) &&
+          (r_cas_fsm.read() != CAS_UPT_REQ) &&
+          (r_cas_fsm.read() != CAS_UPT_NEXT))
+      {
+        if(r_cleanup_fsm.read() == CLEANUP_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+
+        else if(r_read_fsm.read() == READ_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_READ;
+
+        else if(r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)
+          r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+      }
+      break;
+
+      ///////////////////////
+    case ALLOC_HEAP_CLEANUP:
+      if((r_cleanup_fsm.read() != CLEANUP_HEAP_REQ) &&
+          (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) &&
+          (r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH) &&
+          (r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN))
+      {
+        if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+
+        else if(r_read_fsm.read() == READ_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_READ;
+
+        else if(r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)
+          r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+
+        else if(r_cas_fsm.read() == CAS_UPT_HEAP_LOCK)
+          r_alloc_heap_fsm = ALLOC_HEAP_CAS;
+      }
+      break;
+
+      ////////////////////////
+    case ALLOC_HEAP_XRAM_RSP:
+      if((r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_REQ) &&
+          (r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE))
+      {
+        if(r_read_fsm.read() == READ_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_READ;
+
+        else if(r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)
+          r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+
+        else if(r_cas_fsm.read() == CAS_UPT_HEAP_LOCK)
+          r_alloc_heap_fsm = ALLOC_HEAP_CAS;
+
+        else if(r_cleanup_fsm.read() == CLEANUP_HEAP_REQ)
+          r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+
+      }
+      break;
+
+  } // end switch alloc_heap_fsm
+
+
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    TGT_CMD to READ FIFO
+  ////////////////////////////////////////////////////////////////////////////////////
+
+  if(cmd_read_fifo_put)
+  {
+    if(cmd_read_fifo_get)
+    {
+      m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+      m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read() >>2);
+      m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+      m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+      m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+    }
+    else
+    {
+      m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+      m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read() >>2);
+      m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+      m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+      m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+    }
+  }
+  else
+  {
+    if(cmd_read_fifo_get)
+    {
+      m_cmd_read_addr_fifo.simple_get();
+      m_cmd_read_length_fifo.simple_get();
+      m_cmd_read_srcid_fifo.simple_get();
+      m_cmd_read_trdid_fifo.simple_get();
+      m_cmd_read_pktid_fifo.simple_get();
+    }
+  }
+  /////////////////////////////////////////////////////////////////////
+  //    TGT_CMD to WRITE FIFO
+  /////////////////////////////////////////////////////////////////////
+
+  if(cmd_write_fifo_put)
+  {
+    if(cmd_write_fifo_get)
+    {
+      m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+      m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
+      m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+      m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+      m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+      m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
+      m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
+    }
+    else
+    {
+      m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+      m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
+      m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+      m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+      m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+      m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
+      m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
+    }
+  }
+  else
+  {
+    if(cmd_write_fifo_get)
+    {
+      m_cmd_write_addr_fifo.simple_get();
+      m_cmd_write_eop_fifo.simple_get();
+      m_cmd_write_srcid_fifo.simple_get();
+      m_cmd_write_trdid_fifo.simple_get();
+      m_cmd_write_pktid_fifo.simple_get();
+      m_cmd_write_data_fifo.simple_get();
+      m_cmd_write_be_fifo.simple_get();
+    }
+  }
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    TGT_CMD to CAS FIFO
+  ////////////////////////////////////////////////////////////////////////////////////
+
+  if(cmd_cas_fifo_put)
+  {
+    if(cmd_cas_fifo_get)
+    {
+      m_cmd_cas_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+      m_cmd_cas_eop_fifo.put_and_get(p_vci_tgt.eop.read());
+      m_cmd_cas_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+      m_cmd_cas_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+      m_cmd_cas_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+      m_cmd_cas_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
+    }
+    else
+    {
+      m_cmd_cas_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+      m_cmd_cas_eop_fifo.simple_put(p_vci_tgt.eop.read());
+      m_cmd_cas_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+      m_cmd_cas_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+      m_cmd_cas_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+      m_cmd_cas_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
+    }
+  }
+  else
+  {
+    if(cmd_cas_fifo_get)
+    {
+      m_cmd_cas_addr_fifo.simple_get();
+      m_cmd_cas_eop_fifo.simple_get();
+      m_cmd_cas_srcid_fifo.simple_get();
+      m_cmd_cas_trdid_fifo.simple_get();
+      m_cmd_cas_pktid_fifo.simple_get();
+      m_cmd_cas_wdata_fifo.simple_get();
+    }
+  }
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    CC_RECEIVE to CLEANUP FIFO
+  ////////////////////////////////////////////////////////////////////////////////////
+
+  if(cc_receive_to_cleanup_fifo_put)
+  {
+    if(cc_receive_to_cleanup_fifo_get)
+    {
+      m_cc_receive_to_cleanup_fifo.put_and_get(p_dspin_in.data.read());
+    }
+    else
+    {
+      m_cc_receive_to_cleanup_fifo.simple_put(p_dspin_in.data.read());
+    }
+  }
+  else
+  {
+    if(cc_receive_to_cleanup_fifo_get)
+    {
+      m_cc_receive_to_cleanup_fifo.simple_get();
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    CC_RECEIVE to MULTI_ACK FIFO
+  ////////////////////////////////////////////////////////////////////////////////////
+
+  if(cc_receive_to_multi_ack_fifo_put)
+  {
+    if(cc_receive_to_multi_ack_fifo_get)
+    {
+      m_cc_receive_to_multi_ack_fifo.put_and_get(p_dspin_in.data.read());
+    }
+    else
+    {
+      m_cc_receive_to_multi_ack_fifo.simple_put(p_dspin_in.data.read());
+    }
+  }
+  else
+  {
+    if(cc_receive_to_multi_ack_fifo_get)
+    {
+      m_cc_receive_to_multi_ack_fifo.simple_get();
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    WRITE to CC_SEND FIFO
+  ////////////////////////////////////////////////////////////////////////////////////
+
+  if(write_to_cc_send_fifo_put)
+  {
+    if(write_to_cc_send_fifo_get)
+    {
+      m_write_to_cc_send_inst_fifo.put_and_get(write_to_cc_send_fifo_inst);
+      m_write_to_cc_send_srcid_fifo.put_and_get(write_to_cc_send_fifo_srcid);
 #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 " << name() << ".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;
+      m_write_to_cc_send_cache_id_fifo.put_and_get(write_to_cc_send_fifo_cache_id);
+#endif
+    }
+    else
+    {
+      m_write_to_cc_send_inst_fifo.simple_put(write_to_cc_send_fifo_inst);
+      m_write_to_cc_send_srcid_fifo.simple_put(write_to_cc_send_fifo_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 " << name() << ".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();
+      m_write_to_cc_send_cache_id_fifo.simple_put(write_to_cc_send_fifo_cache_id);
+#endif
+    }
+  }
+  else
+  {
+    if(write_to_cc_send_fifo_get)
+    {
+      m_write_to_cc_send_inst_fifo.simple_get();
+      m_write_to_cc_send_srcid_fifo.simple_get();
 #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 " << name() << ".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
-            << "Bad HEAP allocation" << std::endl;
-
-          exit(0);
-        }
-
-        HeapEntry heap_entry;
-        heap_entry.owner.srcid    = 0;
+      m_write_to_cc_send_cache_id_fifo.simple_get();
+#endif
+    }
+  }
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    XRAM_RSP to CC_SEND FIFO
+  ////////////////////////////////////////////////////////////////////////////////////
+
+  if(xram_rsp_to_cc_send_fifo_put)
+  {
+    if(xram_rsp_to_cc_send_fifo_get)
+    {
+      m_xram_rsp_to_cc_send_inst_fifo.put_and_get(xram_rsp_to_cc_send_fifo_inst);
+      m_xram_rsp_to_cc_send_srcid_fifo.put_and_get(xram_rsp_to_cc_send_fifo_srcid);
 #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;
-
-#if DEBUG_MEMC_CLEANUP
-        if( m_debug_cleanup_fsm )
-        {
-          std::cout << "  <MEMC " << name() << ".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 " << name() << ".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 " << name() << ".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 " << name() << ".CLEANUP_WRITE_RSP> Send a response to a cleanup request:"
-              << " rsrcid = " << std::dec << r_cleanup_write_srcid.read()
-              << " / rtrdid = " << std::dec << 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 " << name() << ".CLEANUP_RSP> Send the response to a cleanup request:"
-              << " rsrcid = " << std::dec << r_cleanup_write_srcid.read()
-              << " / rtrdid = " << r_cleanup_write_trdid.read() << std::endl;
-          }
-#endif
-        }
-        break;
-      }
-    } // end switch cleanup fsm
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    CAS FSM
-    ////////////////////////////////////////////////////////////////////////////////////
-    // The CAS FSM handles the CAS (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 CAS 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 CAS request is not consumed in the FIFO until a HIT is obtained.
-    // - In case of hit...
-    ///////////////////////////////////////////////////////////////////////////////////
-
-    switch ( r_cas_fsm.read() )
-    {
-        /////////////
-        case CAS_IDLE:     // fill the local rdata buffers
-        {
-            if( m_cmd_cas_addr_fifo.rok() )
-            {
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_IDLE> CAS command: " << std::hex
-              << " srcid = " <<  std::dec << m_cmd_cas_srcid_fifo.read()
-              << " addr = " << std::hex << m_cmd_cas_addr_fifo.read()
-              << " wdata = " << m_cmd_cas_wdata_fifo.read()
-              << " eop = " << std::dec << m_cmd_cas_eop_fifo.read()
-              << " cpt  = " << std::dec << r_cas_cpt.read() << std::endl;
-}
-#endif
-                if( m_cmd_cas_eop_fifo.read() )
-                {
-                    m_cpt_cas++;
-                    r_cas_fsm = CAS_DIR_REQ;
-                }
-                else  // we keep the last word in the FIFO
-                {
-                    cmd_cas_fifo_get = true;
-                }
-                // We fill the two buffers
-                if ( r_cas_cpt.read() < 2 ) // 32 bits access
-                    r_cas_rdata[r_cas_cpt.read()] = m_cmd_cas_wdata_fifo.read();
-
-                if((r_cas_cpt.read() == 1) && m_cmd_cas_eop_fifo.read())
-                    r_cas_wdata = m_cmd_cas_wdata_fifo.read();
-
-                if( r_cas_cpt.read()>3 ) // more than 4 flits...
-                {
-                    std::cout << "VCI_MEM_CACHE ERROR in CAS_IDLE state : illegal CAS command"
-                              << std::endl;
-                    exit(0);
-                }
-
-                if ( r_cas_cpt.read()==2 )
-                    r_cas_wdata = m_cmd_cas_wdata_fifo.read();
-
-                r_cas_cpt = r_cas_cpt.read()+1;
-            }
-            break;
-        }
-        
-        /////////////////
-        case CAS_DIR_REQ:
-        {
-            if( r_alloc_dir_fsm.read() == ALLOC_DIR_CAS )
-            {
-                r_cas_fsm = CAS_DIR_LOCK;
-            }
-
-#if DEBUG_MEMC_CAS
-            if( m_debug_cas_fsm )
-            {
-                std::cout 
-                    << "  <MEMC " << name() << ".CAS_DIR_REQ> Requesting DIR lock "
-                    << std::endl;
-            }
-#endif
-            break;
-        }
-
-        /////////////////
-        case CAS_DIR_LOCK:  // Read the directory
-        {
-            if( r_alloc_dir_fsm.read() == ALLOC_DIR_CAS )
-            {
-                size_t way = 0;
-                DirectoryEntry entry(m_cache_directory.read(m_cmd_cas_addr_fifo.read(), way));
-
-                r_cas_is_cnt     = entry.is_cnt;
-                r_cas_dirty      = entry.dirty;
-                r_cas_tag        = entry.tag;
-                r_cas_way        = way;
-                r_cas_copy       = entry.owner.srcid;
+      m_xram_rsp_to_cc_send_cache_id_fifo.put_and_get(xram_rsp_to_cc_send_fifo_cache_id);
+#endif
+    }
+    else
+    {
+      m_xram_rsp_to_cc_send_inst_fifo.simple_put(xram_rsp_to_cc_send_fifo_inst);
+      m_xram_rsp_to_cc_send_srcid_fifo.simple_put(xram_rsp_to_cc_send_fifo_srcid);
 #if L1_MULTI_CACHE
-                r_cas_copy_cache = entry.owner.cache_id;
-#endif
-                r_cas_copy_inst  = entry.owner.inst;
-                r_cas_ptr        = entry.ptr;
-                r_cas_count      = entry.count;
-
-                if ( entry.valid )  r_cas_fsm = CAS_DIR_HIT_READ;
-                else                r_cas_fsm = CAS_MISS_TRT_LOCK;
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_DIR_LOCK> Directory acces"
-              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
-              << " / hit = " << std::dec << entry.valid
-              << " / count = " << entry.count
-              << " / is_cnt = " << entry.is_cnt << std::endl;
-}
-#endif
-            }
-            else
-            {
-                std::cout
-                    << "VCI_MEM_CACHE ERROR " << name()
-                    << " CAS_DIR_LOCK state" << std::endl
-                    << "Bad DIR allocation"   << std::endl;
-
-                exit(0);
-            }
-
-            break;
-        }
-
-        /////////////////////
-        case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
-                                // and check data change in cache
-        {
-            size_t way  = r_cas_way.read();
-            size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-
-            // update directory (lock & dirty bits)
-            DirectoryEntry entry;
-            entry.valid          = true;
-            entry.is_cnt         = r_cas_is_cnt.read();
-            entry.dirty          = true;
-            entry.lock           = true;
-            entry.tag            = r_cas_tag.read();
-            entry.owner.srcid    = r_cas_copy.read();
+      m_xram_rsp_to_cc_send_cache_id_fifo.simple_put(xram_rsp_to_cc_send_fifo_cache_id);
+#endif
+    }
+  }
+  else
+  {
+    if(xram_rsp_to_cc_send_fifo_get)
+    {
+      m_xram_rsp_to_cc_send_inst_fifo.simple_get();
+      m_xram_rsp_to_cc_send_srcid_fifo.simple_get();
 #if L1_MULTI_CACHE
-            entry.owner.cache_id = r_cas_copy_cache.read();
-#endif
-            entry.owner.inst     = r_cas_copy_inst.read();
-            entry.count          = r_cas_count.read();
-            entry.ptr            = r_cas_ptr.read();
-
-            m_cache_directory.write(set, way, entry);
-
-            // Stored data from cache in buffer to do the comparison in next state
-            m_cache_data.read_line(way, set, r_cas_data);
-
-            r_cas_fsm = CAS_DIR_HIT_COMPARE;
-
-#if DEBUG_MEMC_CAS
-            if(m_debug_cas_fsm)
-            {
-                std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_READ> Read data from "
-                    << " cache and store it in buffer"
-                    << std::endl;
-            }
-#endif
-            break;
-        }
-
-        case CAS_DIR_HIT_COMPARE:
-        {
-            size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-
-            // Read data in buffer & check data change
-            bool ok = (r_cas_rdata[0].read() == r_cas_data[word].read());
-
-            if(r_cas_cpt.read() == 4)     // 64 bits CAS
-                ok &= (r_cas_rdata[1] == r_cas_data[word+1]);
-
-            // to avoid livelock, force the atomic access to fail pseudo-randomly
-            bool forced_fail = ((r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS);
-            r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((- (r_cas_lfsr & 1)) & 0xd0000001);
-
-            // cas success
-            if(ok and not forced_fail)
-            {
-                r_cas_fsm = CAS_DIR_HIT_WRITE;
-            }
-            // cas failure
-            else
-            {
-                r_cas_fsm = CAS_RSP_FAIL;
-            }
-
-#if DEBUG_MEMC_CAS
-            if(m_debug_cas_fsm)
-            {
-                std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_COMPARE> Compare the old"
-                    << " and the new data"
-                    << " / expected value = " << r_cas_rdata[0].read()
-                    << " / actual value = "   << r_cas_data[word].read()
-                    << " / forced_fail = "    << forced_fail << std::endl;
-            }
-#endif
-            break;
-        }
-
-        //////////////////////
-        case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
-                                   // write data in cache if no CC request
-        {
-            // The CAS is a success => sw access to the llsc_global_table
-            m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
-
-            // test coherence request
-            if(r_cas_count.read())   // replicated line
-            {
-                if ( r_cas_is_cnt.read() )
-                {
-                    r_cas_fsm = CAS_BC_TRT_LOCK;    // broadcast invalidate required
-                }
-                else if( !r_cas_to_init_cmd_multi_req.read() &&
-                         !r_cas_to_init_cmd_brdcast_req.read()  )
-                {
-                    r_cas_fsm = CAS_UPT_LOCK;     // multi update required
-                }
-                else
-                {
-                    r_cas_fsm = CAS_WAIT;
-                }
-            }
-            else                    // no copies
-            {
-                size_t way  = r_cas_way.read();
-                size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-
-                // cache update
-                m_cache_data.write(way, set, word, r_cas_wdata.read());
-                if(r_cas_cpt.read()==4)
-                    m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
-
-                r_cas_fsm = CAS_RSP_SUCCESS;
-
-                // monitor
-                if ( m_monitor_ok )
-                {
-                    vci_addr_t address = m_cmd_cas_addr_fifo.read();
-
-                    char buf[80];
-                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d",
-                             m_cmd_cas_srcid_fifo.read());
-
-                    check_monitor( buf, address, r_cas_wdata.read() );
-                    if ( r_cas_cpt.read()==4 )
-                    check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
-                }
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> Update cache:"
-              << " way = " << std::dec << way
-              << " / set = " << set
-              << " / word = " << word
-              << " / value = " << r_cas_wdata.read()
-              << " / count = " << r_cas_count.read() << std::endl;
-    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> global_llsc_table SW access" << std::endl;
-}
-#endif
-            }
-            break;
-        }
-        /////////////////
-        case CAS_UPT_LOCK:  // try to register the transaction in UPT
-                           // and write data in cache if successful registration
-                           // releases locks to retry later if UPT full
-        {
-            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CAS )
-            {
-                bool        wok        = false;
-                size_t      index      = 0;
-                size_t      srcid      = m_cmd_cas_srcid_fifo.read();
-                size_t      trdid      = m_cmd_cas_trdid_fifo.read();
-                size_t      pktid      = m_cmd_cas_pktid_fifo.read();
-                addr_t      nline      = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                size_t      nb_copies  = r_cas_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
-                {
-                    // cache update
-                    size_t way  = r_cas_way.read();
-                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-
-                    m_cache_data.write(way, set, word, r_cas_wdata.read());
-                    if(r_cas_cpt.read()==4)
-                        m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
-
-                    // monitor
-                    if ( m_monitor_ok )
-                    {
-                        vci_addr_t address = m_cmd_cas_addr_fifo.read();
-                    char buf[80];
-                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
-                        check_monitor( buf, address, r_cas_wdata.read() );
-                        if ( r_cas_cpt.read()==4 )
-                        check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
-                    }
-
-                    r_cas_upt_index = index;
-                    r_cas_fsm = CAS_UPT_HEAP_LOCK;
-                }
-                else       //  releases the locks protecting UPT and DIR UPT full
-                {
-                    r_cas_fsm = CAS_WAIT;
-                }
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_UPT_LOCK> Register multi-update transaction in UPT"
-              << " / wok = " << wok
-              << " / nline  = " << std::hex << nline
-              << " / count = " << nb_copies << std::endl;
-}
-#endif
-            }
-            break;
-        }
-        /////////////
-        case CAS_WAIT:   // release all locks and retry from beginning
-        {
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_WAIT> Release all locks" << std::endl;
-}
-#endif
-            r_cas_fsm = CAS_DIR_REQ;
-            break;
-        }
-        //////////////////
-        case CAS_UPT_HEAP_LOCK:  // lock the heap
-        {
-            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS )
-            {
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_UPT_HEAP_LOCK> Get access to the heap" << std::endl;
-}
-#endif
-                r_cas_fsm = CAS_UPT_REQ;
-            }
-            break;
-        }
-        ////////////////
-        case CAS_UPT_REQ:  // send a first update request to INIT_CMD FSM
-        {
-            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS) and
-                   "VCI_MEM_CACHE ERROR : bad HEAP allocation");
-
-            if( !r_cas_to_init_cmd_multi_req.read() && !r_cas_to_init_cmd_brdcast_req.read() )
-            {
-                r_cas_to_init_cmd_brdcast_req  = false;
-                r_cas_to_init_cmd_trdid        = r_cas_upt_index.read();
-                r_cas_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                r_cas_to_init_cmd_index        = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                r_cas_to_init_cmd_wdata        = r_cas_wdata.read();
-
-                if(r_cas_cpt.read() == 4)
-                {
-                    r_cas_to_init_cmd_is_long    = true;
-                    r_cas_to_init_cmd_wdata_high = m_cmd_cas_wdata_fifo.read();
-                }
-                else
-                {
-                    r_cas_to_init_cmd_is_long    = false;
-                    r_cas_to_init_cmd_wdata_high = 0;
-                }
-
-                // We put the first copy in the fifo
-                cas_to_init_cmd_fifo_put     = true;
-                cas_to_init_cmd_fifo_inst    = r_cas_copy_inst.read();
-                cas_to_init_cmd_fifo_srcid   = r_cas_copy.read();
+      m_xram_rsp_to_cc_send_cache_id_fifo.simple_get();
+#endif
+    }
+  }
+  ////////////////////////////////////////////////////////////////////////////////////
+  //    CAS to CC_SEND FIFO
+  ////////////////////////////////////////////////////////////////////////////////////
+
+  if(cas_to_cc_send_fifo_put)
+  {
+    if(cas_to_cc_send_fifo_get)
+    {
+      m_cas_to_cc_send_inst_fifo.put_and_get(cas_to_cc_send_fifo_inst);
+      m_cas_to_cc_send_srcid_fifo.put_and_get(cas_to_cc_send_fifo_srcid);
 #if L1_MULTI_CACHE
-                cas_to_init_cmd_fifo_cache_id= r_cas_copy_cache.read();
-#endif
-                if(r_cas_count.read() == 1) // one single copy
-                {
-                    r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
-                                            // update responses
-                    cmd_cas_fifo_get            = true;
-                    r_cas_to_init_cmd_multi_req = true;
-                    r_cas_cpt = 0;
-                }
-                else      // several copies
-                {
-                    r_cas_fsm = CAS_UPT_NEXT;
-                }
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_UPT_REQ> Send the first update request to INIT_CMD FSM "
-              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
-              << " / wdata = " << std::hex << r_cas_wdata.read()
-              << " / srcid = " << std::dec << r_cas_copy.read()
-              << " / inst = " << std::dec << r_cas_copy_inst.read() << std::endl;
-}
-#endif
-            }
-            break;
-        }
-        /////////////////
-        case CAS_UPT_NEXT:     // send a multi-update request to INIT_CMD FSM
-        {
-            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
-                 and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
-
-            HeapEntry entry = m_heap.read(r_cas_ptr.read());
-            cas_to_init_cmd_fifo_srcid    = entry.owner.srcid;
+      m_cas_to_cc_send_cache_id_fifo.put_and_get(cas_to_cc_send_fifo_cache_id);
+#endif
+    }
+    else
+    {
+      m_cas_to_cc_send_inst_fifo.simple_put(cas_to_cc_send_fifo_inst);
+      m_cas_to_cc_send_srcid_fifo.simple_put(cas_to_cc_send_fifo_srcid);
 #if L1_MULTI_CACHE
-            cas_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
-#endif
-            cas_to_init_cmd_fifo_inst     = entry.owner.inst;
-            cas_to_init_cmd_fifo_put = true;
-
-            if( m_cas_to_init_cmd_inst_fifo.wok() ) // request accepted by INIT_CMD FSM
-            {
-                r_cas_ptr = entry.next;
-                if( entry.next == r_cas_ptr.read() )  // last copy
-                {
-                    r_cas_to_init_cmd_multi_req = true;
-                    r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
-                                            // all update responses
-                    cmd_cas_fifo_get = true;
-                    r_cas_cpt        = 0;
-                }
-            }
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_UPT_NEXT> Send the next update request to INIT_CMD FSM "
-              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
-              << " / wdata = " << std::hex << r_cas_wdata.read()
-              << " / srcid = " << std::dec << entry.owner.srcid
-              << " / inst = " << std::dec << entry.owner.inst << std::endl;
-}
-#endif
-            break;
-        }
-        /////////////////////
-        case CAS_BC_TRT_LOCK:      // check the TRT to register a PUT transaction
-        {
-            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
-            {
-                if( !r_cas_to_ixr_cmd_req )  // we can transfer the request to IXR_CMD FSM
-                {
-                    // fill the data buffer
-                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                    for(size_t i = 0; i<m_words; i++)
-                    {
-                        if (i == word)
-                        {
-                            r_cas_to_ixr_cmd_data[i] = r_cas_wdata.read();
-                        }
-                        else if ( (i == word+1) && (r_cas_cpt.read()==4) ) // 64 bit CAS
-                        {
-                            r_cas_to_ixr_cmd_data[i] = m_cmd_cas_wdata_fifo.read();
-                        }
-                        else
-                        {
-                            r_cas_to_ixr_cmd_data[i] = r_cas_data[i].read();
-                        }
-                    }
-                    size_t wok_index = 0;
-                    bool   wok       = !m_transaction_tab.full(wok_index);
-                    if ( wok )
-                    {
-                        r_cas_trt_index = wok_index;
-                        r_cas_fsm       = CAS_BC_UPT_LOCK;
-                    }
-                    else
-                    {
-                        r_cas_fsm       = CAS_WAIT;
-                    }
-                }
-                else
-                {
-                    r_cas_fsm = CAS_WAIT;
-                }
-            }
-            break;
-        }
-        ///////////////////
-        case CAS_BC_UPT_LOCK:  // register a broadcast inval transaction in UPT
-                              // write data in cache in case of successful registration
-        {
-            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CAS )
-            {
-                bool        wok       = false;
-                size_t      index     = 0;
-                size_t      srcid     = m_cmd_cas_srcid_fifo.read();
-                size_t      trdid     = m_cmd_cas_trdid_fifo.read();
-                size_t      pktid     = m_cmd_cas_pktid_fifo.read();
-                addr_t      nline     = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                size_t      nb_copies = r_cas_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
-                {
-                    // cache update
-                    size_t way  = r_cas_way.read();
-                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-
-                    m_cache_data.write(way, set, word, r_cas_wdata.read());
-                    if(r_cas_cpt.read()==4)
-                        m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
-
-                    // monitor
-                    if ( m_monitor_ok )
-                    {
-                        vci_addr_t address = m_cmd_cas_addr_fifo.read();
-                    char buf[80];
-                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
-                        check_monitor( buf, address, r_cas_wdata.read() );
-                        if ( r_cas_cpt.read()==4 )
-                        check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
-                    }
-                    r_cas_upt_index = index;
-                    r_cas_fsm = CAS_BC_DIR_INVAL;
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_BC_UPT_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_cas_fsm = CAS_WAIT;
-                }
-            }
-            break;
-        }
-        //////////////////
-        case CAS_BC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
-        {
-            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_CAS ) &&
-                 (r_alloc_upt_fsm.read() == ALLOC_UPT_CAS ) &&
-                 (r_alloc_dir_fsm.read() == ALLOC_DIR_CAS ))
-            {
-                // set TRT
-                m_transaction_tab.set(r_cas_trt_index.read(),
-                                      false,    // PUT request to XRAM
-                                      m_nline[(vci_addr_t)(m_cmd_cas_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;
+      m_cas_to_cc_send_cache_id_fifo.simple_put(cas_to_cc_send_fifo_cache_id);
+#endif
+    }
+  }
+  else
+  {
+    if(cas_to_cc_send_fifo_get)
+    {
+      m_cas_to_cc_send_inst_fifo.simple_get();
+      m_cas_to_cc_send_srcid_fifo.simple_get();
 #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_cas_addr_fifo.read())];
-                size_t way          = r_cas_way.read();
-                m_cache_directory.write(set, way, entry);
-
-                r_cas_fsm = CAS_BC_CC_SEND;
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_BC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
-              << " / nline = " << std::hex << m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())]
-              << " / set = " << std::dec << set << " / way = " << way << std::endl;
-}
-#endif
-            }
-            else
-            {
-                assert(false and "LOCK ERROR in CAS_FSM, STATE = CAS_BC_DIR_INVAL");
-            }
-            break;
-        }
-        ///////////////////
-        case CAS_BC_CC_SEND:  // Request the broadcast inval to INIT_CMD FSM
-        {
-            if ( !r_cas_to_init_cmd_multi_req.read() &&
-                 !r_cas_to_init_cmd_brdcast_req.read())
-            {
-                r_cas_to_init_cmd_multi_req    = false;
-                r_cas_to_init_cmd_brdcast_req  = true;
-                r_cas_to_init_cmd_trdid        = r_cas_upt_index.read();
-                r_cas_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                r_cas_to_init_cmd_index        = 0;
-                r_cas_to_init_cmd_wdata        = 0;
-
-                r_cas_fsm = CAS_BC_XRAM_REQ;
-            }
-            break;
-        }
-        ////////////////////
-        case CAS_BC_XRAM_REQ: // request the IXR FSM to start a put transaction
-        {
-            if ( !r_cas_to_ixr_cmd_req )
-            {
-                r_cas_to_ixr_cmd_req     = true;
-                r_cas_to_ixr_cmd_write   = true;
-                r_cas_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-                r_cas_to_ixr_cmd_trdid   = r_cas_trt_index.read();
-                r_cas_fsm                = CAS_IDLE;
-                cmd_cas_fifo_get         = true;
-                r_cas_cpt                = 0;
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_BC_XRAM_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
-              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
-              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
-}
-#endif
-            }
-            else
-            {
-               std::cout << "MEM_CACHE, CAS_BC_XRAM_REQ state : request should not have been previously set"
-                         << std::endl;
-            }
-            break;
-        }
-        /////////////////
-        case CAS_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
-        {
-            if( !r_cas_to_tgt_rsp_req )
-            {
-                cmd_cas_fifo_get     = true;
-                r_cas_cpt              = 0;
-                r_cas_to_tgt_rsp_req = true;
-                r_cas_to_tgt_rsp_data  = 1;
-                r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
-                r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
-                r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
-                r_cas_fsm              = CAS_IDLE;
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
-}
-#endif
-            }
-            break;
-        }
-        ////////////////////
-        case CAS_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
-        {
-            if( !r_cas_to_tgt_rsp_req )
-            {
-                cmd_cas_fifo_get       = true;
-                r_cas_cpt              = 0;
-                r_cas_to_tgt_rsp_req = true;
-                r_cas_to_tgt_rsp_data  = 0;
-                r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
-                r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
-                r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
-                r_cas_fsm              = CAS_IDLE;
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
-}
-#endif
-            }
-            break;
-        }
-        /////////////////////
-        case CAS_MISS_TRT_LOCK:         // cache miss : request access to transaction Table
-        {
-            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
-            {
-                size_t   index = 0;
-                bool hit_read = m_transaction_tab.hit_read(
-                                  m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()],index);
-                bool hit_write = m_transaction_tab.hit_write(
-                                   m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]);
-                bool wok = !m_transaction_tab.full(index);
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_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_cas_fsm = CAS_WAIT;
-                }
-                else
-                {
-                    r_cas_trt_index = index;
-                    r_cas_fsm       = CAS_MISS_TRT_SET;
-                }
-            }
-            break;
-        }
-        ////////////////////
-        case CAS_MISS_TRT_SET: // register the GET transaction in TRT
-        {
-            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
-            {
-                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(0);
-                    data_vector.push_back(0);
-                }
-
-                m_transaction_tab.set(r_cas_trt_index.read(),
-                                      true,   // read request
-                                      m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()],
-                                      m_cmd_cas_srcid_fifo.read(),
-                                      m_cmd_cas_trdid_fifo.read(),
-                                      m_cmd_cas_pktid_fifo.read(),
-                                      false,    // write request from processor
-                                      0,
-                                      0,
-                                      be_vector,
-                                      data_vector);
-                r_cas_fsm = CAS_MISS_XRAM_REQ;
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_SET> Register a GET transaction in TRT" << std::hex
-              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
-              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
-}
-#endif
-            }
-            break;
-        }
-        //////////////////////
-        case CAS_MISS_XRAM_REQ:  // request the IXR_CMD FSM to fetch the missing line
-        {
-            if ( !r_cas_to_ixr_cmd_req )
-            {
-                r_cas_to_ixr_cmd_req        = true;
-                r_cas_to_ixr_cmd_write      = false;
-                r_cas_to_ixr_cmd_trdid      = r_cas_trt_index.read();
-                r_cas_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()];
-                r_cas_fsm                   = CAS_WAIT;
-
-#if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_MISS_XRAM_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
-              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
-              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
-}
-#endif
-            }
-            break;
-        }
-    } // end switch r_cas_fsm
-
-
-    //////////////////////////////////////////////////////////////////////////////
-    //    INIT_CMD FSM
-    //////////////////////////////////////////////////////////////////////////////
-    // The INIT_CMD fsm controls the VCI CMD initiator port on the coherence
-    // network, used to update or invalidate cache lines in L1 caches.
-    //
-    // It implements a round-robin priority between the three possible client FSMs
-    // XRAM_RSP, WRITE and CAS. 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_cas_to_init_cmd_multi_req : multi-update
-    //   r_cas_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.
-    // 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
-    // contain the data.
-    ///////////////////////////////////////////////////////////////////////////////
-
-    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_cas_to_init_cmd_inst_fifo.rok() ||
-                      r_cas_to_init_cmd_multi_req.read()  )
-            {
-                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
-                m_cpt_update++;
-            }
-            else if( r_cas_to_init_cmd_brdcast_req.read() )
-            {
-                r_init_cmd_fsm = INIT_CMD_CAS_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_cas_to_init_cmd_inst_fifo.rok() ||
-                      r_cas_to_init_cmd_multi_req.read()  )
-            {
-                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
-                m_cpt_update++;
-            }
-            else if( r_cas_to_init_cmd_brdcast_req.read() )
-            {
-                r_init_cmd_fsm = INIT_CMD_CAS_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_CAS_UPDT_IDLE: // CAS FSM has highest priority
-        {
-            if ( m_cas_to_init_cmd_inst_fifo.rok() ||
-                 r_cas_to_init_cmd_multi_req.read()  )
-            {
-                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
-                m_cpt_update++;
-            }
-            else if( r_cas_to_init_cmd_brdcast_req.read() )
-            {
-                r_init_cmd_fsm = INIT_CMD_CAS_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 " << name() << ".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_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_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_CAS_BRDCAST: // send a broadcast-inval (from CAS FSM)
-        {
-            if( p_vci_ini.cmdack )
-            {
-                m_cpt_inval_brdcast++;
-                r_cas_to_init_cmd_brdcast_req = false;
-                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_IDLE;
-            }
-            break;
-        }
-        ////////////////////////////
-        case INIT_CMD_CAS_UPDT_NLINE:   // send nline for a multi-update (from CAS FSM)
-        {
-            if ( m_cas_to_init_cmd_inst_fifo.rok() )
-            {
-                if ( p_vci_ini.cmdack )
-                {
-                    m_cpt_update_mult++;
-                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_INDEX;
-                }
-            }
-            else
-            {
-                if( r_cas_to_init_cmd_multi_req.read() ) r_cas_to_init_cmd_multi_req = false;
-                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_IDLE;
-            }
-            break;
-        }
-        ////////////////////////////
-        case INIT_CMD_CAS_UPDT_INDEX:  // send word index for a multi-update (from CAS FSM)
-        {
-            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_CAS_UPDT_DATA;
-            break;
-        }
-        ///////////////////////////
-        case INIT_CMD_CAS_UPDT_DATA:  // send first data for a multi-update (from CAS FSM)
-        {
-            if ( p_vci_ini.cmdack )
-            {
-                if ( r_cas_to_init_cmd_is_long.read() )
-                {
-                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_DATA_HIGH;
-                }
-                else
-                {
-                    cas_to_init_cmd_fifo_get = true;
-                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
-                }
-            }
-            break;
-        }
-        ////////////////////////
-        case INIT_CMD_CAS_UPDT_DATA_HIGH:  // send second data for a multi-update (from CAS FSM)
-        {
-            if ( p_vci_ini.cmdack )
-            {
-                cas_to_init_cmd_fifo_get = true;
-                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
-            }
-            break;
-        }
-    } // end switch r_init_cmd_fsm
-
-    /////////////////////////////////////////////////////////////////////
-    //    TGT_RSP FSM
-    /////////////////////////////////////////////////////////////////////
-    // The TGT_RSP fsm sends the responses on the VCI target port
-    // with a round robin priority between six requests :
-    // - r_read_to_tgt_rsp_req
-    // - r_write_to_tgt_rsp_req
-    // - r_cas_to_tgt_rsp_req
-    // - r_cleanup_to_tgt_rsp_req
-    // - r_xram_rsp_to_tgt_rsp_req
-    // - r_init_rsp_to_tgt_rsp_req
-    // The  ordering is :  read > write > cas > xram > init > cleanup
-    /////////////////////////////////////////////////////////////////////
-
-    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_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
-          else if ( r_xram_rsp_to_tgt_rsp_req )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_XRAM;
-            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
-          }
-          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
-          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
-          else if ( r_read_to_tgt_rsp_req     )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_READ;
-            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
-          }
-          break;
-        }
-        ////////////////////////
-        case TGT_RSP_WRITE_IDLE:  // cas requests have the highest priority
-        {
-          if      ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS;
-          else if ( r_xram_rsp_to_tgt_rsp_req )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_XRAM;
-            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
-          }
-          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
-          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
-          else if ( r_read_to_tgt_rsp_req     )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_READ;
-            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
-          }
-
-          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
-          break;
-        }
-        ///////////////////////
-        case TGT_RSP_CAS_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();
-          }
-          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
-          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
-          else if ( r_read_to_tgt_rsp_req     )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_READ;
-            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
-          }
-          else if ( r_write_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
-          else if ( r_cas_to_tgt_rsp_req   ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
-          break;
-        }
-        ///////////////////////
-        case TGT_RSP_XRAM_IDLE:   // init requests have the highest priority
-        {
-
-          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
-          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
-          else if ( r_read_to_tgt_rsp_req     )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_READ;
-            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
-          }
-          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
-          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
-          else if ( r_xram_rsp_to_tgt_rsp_req )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_XRAM;
-            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
-          }
-          break;
-        }
-        ///////////////////////
-        case TGT_RSP_INIT_IDLE:   // cleanup requests have the highest priority
-        {
-          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
-          else if ( r_read_to_tgt_rsp_req     )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_READ;
-            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
-          }
-          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
-          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
-          else if ( r_xram_rsp_to_tgt_rsp_req )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_XRAM;
-            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
-          }
-          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
-          break;
-        }
-        ///////////////////////
-        case TGT_RSP_CLEANUP_IDLE:    // read requests have the highest priority
-        {
-          if      ( r_read_to_tgt_rsp_req     )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_READ;
-            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
-          }
-          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
-          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
-          else if ( r_xram_rsp_to_tgt_rsp_req )
-          {
-            r_tgt_rsp_fsm = TGT_RSP_XRAM;
-            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
-          }
-          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
-          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
-          break;
-        }
-        //////////////////
-        case TGT_RSP_READ:    // send the response to a read
-        {
-            if ( p_vci_tgt.rspack )
-            {
-
-#if DEBUG_MEMC_TGT_RSP
-if( m_debug_tgt_rsp_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".TGT_RSP_READ> Read response"
-              << " / rsrcid = " << std::dec << r_read_to_tgt_rsp_srcid.read()
-              << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
-              << " / rpktid = " << r_read_to_tgt_rsp_pktid.read()
-              << " / rdata = " << std::hex << 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 " << name() << ".TGT_RSP_WRITE> Write response"
-              << " / rsrcid = " << std::dec << r_write_to_tgt_rsp_srcid.read()
-              << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read()
-              << " / rpktid = " << r_write_to_tgt_rsp_pktid.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 " << name() << ".TGT_RSP_CLEANUP> Cleanup response"
-              << " / rsrcid = " << std::dec << r_cleanup_to_tgt_rsp_srcid.read()
-              << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read()
-              << " / rpktid = " << r_cleanup_to_tgt_rsp_pktid.read() << std::endl;
-}
-#endif
-                r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
-                r_cleanup_to_tgt_rsp_req = false;
-            }
-            break;
-        }
-        //////////////////
-        case TGT_RSP_CAS:    // send one atomic word response
-        {
-            if ( p_vci_tgt.rspack )
-            {
-
-#if DEBUG_MEMC_TGT_RSP
-if( m_debug_tgt_rsp_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".TGT_RSP_CAS> CAS response"
-              << " / rsrcid = " << std::dec << r_cas_to_tgt_rsp_srcid.read()
-              << " / rtrdid = " << r_cas_to_tgt_rsp_trdid.read()
-              << " / rpktid = " << r_cas_to_tgt_rsp_pktid.read() << std::endl;
-}
-#endif
-                r_tgt_rsp_fsm = TGT_RSP_CAS_IDLE;
-                r_cas_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 " << name() << ".TGT_RSP_XRAM> Response following XRAM access"
-              << " / rsrcid = " << std::dec << r_xram_rsp_to_tgt_rsp_srcid.read()
-              << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
-              << " / rpktid = " << r_xram_rsp_to_tgt_rsp_pktid.read()
-              << " / rdata = " << std::hex << r_xram_rsp_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_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 write response after coherence transaction
-        {
-            if ( p_vci_tgt.rspack )
-            {
-
-#if DEBUG_MEMC_TGT_RSP
-if( m_debug_tgt_rsp_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".TGT_RSP_INIT> Write response after coherence transaction"
-              << " / rsrcid = " << std::dec << r_init_rsp_to_tgt_rsp_srcid.read()
-              << " / rtrdid = " << r_init_rsp_to_tgt_rsp_trdid.read()
-              << " / rpktid = " << r_init_rsp_to_tgt_rsp_pktid.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
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    ALLOC_UPT FSM
-    ////////////////////////////////////////////////////////////////////////////////////
-    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
-    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP
-    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
-    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
-    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
-    // - The CLEANUP  FSM decrement an entry in UPT.
-    // The resource is always allocated.
-    /////////////////////////////////////////////////////////////////////////////////////
-
-    switch ( r_alloc_upt_fsm.read() )
-    {
-
-      ////////////////////////
-      case ALLOC_UPT_INIT_RSP:
-        if (( r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK  ) &&
-            ( r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR ))
-        {
-          if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
-              ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
-            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
-
-          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
-
-          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
-
-          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
-                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
-            r_alloc_upt_fsm = ALLOC_UPT_CAS;
-        }
-        break;
-
-        /////////////////////
-      case ALLOC_UPT_WRITE:
-        if (( r_write_fsm.read() != WRITE_UPT_LOCK    ) &&
-            ( r_write_fsm.read() != WRITE_BC_UPT_LOCK ))
-        {
-          if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
-
-          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
-
-          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
-                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
-            r_alloc_upt_fsm = ALLOC_UPT_CAS;
-
-          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
-        }
-        break;
-
-        ////////////////////////
-      case ALLOC_UPT_XRAM_RSP:
-        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)
-        {
-          if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
-
-          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
-                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
-            r_alloc_upt_fsm = ALLOC_UPT_CAS;
-
-          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
-
-          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    )   ||
-                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
-            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
-        }
-        break;
-
-        //////////////////////////
-      case ALLOC_UPT_CLEANUP:
-        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
-        {
-          if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
-              ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
-            r_alloc_upt_fsm = ALLOC_UPT_CAS;
-
-          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
-
-          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
-                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
-            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
-
-          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
-        }
-        break;
-
-        //////////////////////////
-      case ALLOC_UPT_CAS:
-        if (( r_cas_fsm.read() != CAS_UPT_LOCK    ) &&
-            ( r_cas_fsm.read() != CAS_BC_UPT_LOCK ))
-        {
-          if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
-
-          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
-                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
-            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
-
-          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
-
-          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
-            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
-        }
-        break;
-
-    } // end switch r_alloc_upt_fsm
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    ALLOC_DIR FSM
-    ////////////////////////////////////////////////////////////////////////////////////
-    // The ALLOC_DIR FSM allocates the access to the directory and
-    // the data cache with a round robin priority between 5 user FSMs :
-    // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
-    // The ressource is always allocated.
-    /////////////////////////////////////////////////////////////////////////////////////
-
-    switch ( r_alloc_dir_fsm.read() )
-    {
-      case ALLOC_DIR_RESET:
-        // Initializes the directory one SET each cycle. All the WAYS of a SET are
-        // initialize in parallel
-
-        r_alloc_dir_reset_cpt.write(r_alloc_dir_reset_cpt.read() + 1);
-
-        if (r_alloc_dir_reset_cpt.read() == (m_sets - 1)) {
-          m_cache_directory.init();
-
-          r_alloc_dir_fsm = ALLOC_DIR_READ;
-        }
-        break;
-
-      ////////////////////
-      case ALLOC_DIR_READ:
-        if ((( r_read_fsm.read()       != READ_DIR_REQ    )   &&
-             ( r_read_fsm.read()       != READ_DIR_LOCK   )   &&
-             ( r_read_fsm.read()       != READ_TRT_LOCK   )   &&
-             ( r_read_fsm.read()       != READ_HEAP_REQ   ))
-            ||
-            (( r_read_fsm.read()       == READ_TRT_LOCK   )   &&
-             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_READ  )))
-        {
-          if (r_write_fsm.read() == WRITE_DIR_REQ)
-            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
-
-          else if (r_cas_fsm.read() == CAS_DIR_REQ)
-            r_alloc_dir_fsm = ALLOC_DIR_CAS;
-
-          else if (r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
-
-          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
-            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
-        }
-        break;
-
-        /////////////////////
-      case ALLOC_DIR_WRITE:
-        if ((( r_write_fsm.read()      != WRITE_DIR_REQ       )  &&
-             ( r_write_fsm.read()      != WRITE_DIR_LOCK      )  &&
-             ( r_write_fsm.read()      != WRITE_DIR_READ      )  &&
-             ( r_write_fsm.read()      != WRITE_DIR_HIT       )  &&
-             ( r_write_fsm.read()      != WRITE_BC_TRT_LOCK   )  &&
-             ( r_write_fsm.read()      != WRITE_BC_UPT_LOCK   )  &&
-             ( r_write_fsm.read()      != WRITE_MISS_TRT_LOCK )  &&
-             ( r_write_fsm.read()      != WRITE_UPT_LOCK      )  &&
-             ( r_write_fsm.read()      != WRITE_UPT_HEAP_LOCK ))
-            ||
-            (( r_write_fsm.read()      == WRITE_UPT_HEAP_LOCK )  &&
-             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE    ))
-            ||
-            (( r_write_fsm.read()      == WRITE_MISS_TRT_LOCK )  &&
-             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_WRITE     )))
-        {
-          if ( r_cas_fsm.read() == CAS_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_CAS;
-
-          else if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
-
-          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
-            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
-
-          else if ( r_read_fsm.read() == READ_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_READ;
-        }
-        break;
-
-        ////////////////////
-        case ALLOC_DIR_CAS:
-        if ((( r_cas_fsm.read()        != CAS_DIR_REQ         )  &&
-             ( r_cas_fsm.read()        != CAS_DIR_LOCK        )  &&
-             ( r_cas_fsm.read()        != CAS_DIR_HIT_READ    )  &&
-             ( r_cas_fsm.read()        != CAS_DIR_HIT_COMPARE )  &&
-             ( r_cas_fsm.read()        != CAS_DIR_HIT_WRITE   )  &&
-             ( r_cas_fsm.read()        != CAS_BC_TRT_LOCK     )  &&
-             ( r_cas_fsm.read()        != CAS_BC_UPT_LOCK     )  &&
-             ( r_cas_fsm.read()        != CAS_MISS_TRT_LOCK   )  &&
-             ( r_cas_fsm.read()        != CAS_UPT_LOCK        )  &&
-             ( r_cas_fsm.read()        != CAS_UPT_HEAP_LOCK   ))
-            ||
-            (( r_cas_fsm.read()        == CAS_UPT_HEAP_LOCK   )  &&
-             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS      ))
-            ||
-            (( r_cas_fsm.read()        == CAS_MISS_TRT_LOCK   )  &&
-             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_CAS       )))
-        {
-          if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
-
-          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
-            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
-
-          else if ( r_read_fsm.read() == READ_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_READ;
-
-          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
-        }
-        break;
-
-        ///////////////////////
-        case ALLOC_DIR_CLEANUP:
-        if (( r_cleanup_fsm.read() != CLEANUP_DIR_REQ   ) &&
-            ( r_cleanup_fsm.read() != CLEANUP_DIR_LOCK  ) &&
-            ( r_cleanup_fsm.read() != CLEANUP_HEAP_REQ  ) &&
-            ( r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK ))
-        {
-          if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
-            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
-
-          else if ( r_read_fsm.read() == READ_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_READ;
-
-          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
-
-          else if ( r_cas_fsm.read() == CAS_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_CAS;
-        }
-        break;
-
-        ////////////////////////
-        case ALLOC_DIR_XRAM_RSP:
-        if (( r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK   ) &&
-            ( r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY   ) &&
-            ( r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK ))
-        {
-          if ( r_read_fsm.read() == READ_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_READ;
-
-          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
-
-          else if ( r_cas_fsm.read() == CAS_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_CAS;
-
-          else if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
-            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
-        }
-        break;
-
-    } // end switch alloc_dir_fsm
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    ALLOC_TRT FSM
-    ////////////////////////////////////////////////////////////////////////////////////
-    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
-    // with a round robin priority between 4 user FSMs :
-    // The cyclic priority is READ > WRITE > CAS > XRAM_RSP
-    // The ressource is always allocated.
-    ///////////////////////////////////////////////////////////////////////////////////
-
-    switch ( r_alloc_trt_fsm.read() )
-    {
-      ////////////////////
-      case ALLOC_TRT_READ:
-        if ( r_read_fsm.read() != READ_TRT_LOCK )
-        {
-          if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
-              ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
-            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
-
-          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
-                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
-            r_alloc_trt_fsm = ALLOC_TRT_CAS;
-
-          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
-                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
-            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
-
-          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
-                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
-            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
-        }
-        break;
-
-      /////////////////////
-      case ALLOC_TRT_WRITE:
-        if (( r_write_fsm.read() != WRITE_MISS_TRT_LOCK ) &&
-            ( r_write_fsm.read() != WRITE_BC_TRT_LOCK   ) &&
-            ( r_write_fsm.read() != WRITE_BC_UPT_LOCK   ))
-        {
-          if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
-              ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
-            r_alloc_trt_fsm = ALLOC_TRT_CAS;
-
-          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
-                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
-            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
-
-          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
-                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
-            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
-
-          else if ( r_read_fsm.read() == READ_TRT_LOCK )
-            r_alloc_trt_fsm = ALLOC_TRT_READ;
-        }
-        break;
-
-      ////////////////////
-      case ALLOC_TRT_CAS:
-        if (( r_cas_fsm.read() != CAS_MISS_TRT_LOCK ) &&
-            ( r_cas_fsm.read() != CAS_BC_TRT_LOCK   ) &&
-            ( r_cas_fsm.read() != CAS_BC_UPT_LOCK   ))
-        {
-          if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
-              ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
-            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
-
-          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
-                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
-            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
-
-          else if ( r_read_fsm.read() == READ_TRT_LOCK )
-            r_alloc_trt_fsm = ALLOC_TRT_READ;
-
-          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
-                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
-            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
-        }
-        break;
-
-      ////////////////////////
-      case ALLOC_TRT_XRAM_RSP:
-        if ((( r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_LOCK   )  ||
-             ( r_alloc_dir_fsm.read() != ALLOC_DIR_XRAM_RSP  )) &&
-             ( r_xram_rsp_fsm.read()  != XRAM_RSP_TRT_COPY   )  &&
-             ( r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_UPDT   )  &&
-             ( r_xram_rsp_fsm.read()  != XRAM_RSP_INVAL_LOCK ))
-        {
-          if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
-              ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
-            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
-
-          else if ( r_read_fsm.read() == READ_TRT_LOCK )
-            r_alloc_trt_fsm = ALLOC_TRT_READ;
-
-          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
-                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
-            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
-
-          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
-                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
-            r_alloc_trt_fsm = ALLOC_TRT_CAS;
-        }
-        break;
-
-      ////////////////////////
-      case ALLOC_TRT_IXR_RSP:
-        if (( r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE ) &&
-            ( r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ  ))
-        {
-          if ( r_read_fsm.read() == READ_TRT_LOCK )
-            r_alloc_trt_fsm = ALLOC_TRT_READ;
-
-          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
-                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
-            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
-
-          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
-                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
-            r_alloc_trt_fsm = ALLOC_TRT_CAS;
-
-          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
-                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
-            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
-        }
-        break;
-
-    } // end switch alloc_trt_fsm
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    ALLOC_HEAP FSM
-    ////////////////////////////////////////////////////////////////////////////////////
-    // 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 > CAS > CLEANUP > XRAM_RSP
-    // The ressource is always allocated.
-    /////////////////////////////////////////////////////////////////////////////////////
-
-    switch ( r_alloc_heap_fsm.read() )
-    {
-        ////////////////////
-        case ALLOC_HEAP_RESET:
-          // Initializes the heap one ENTRY each cycle.
-
-          r_alloc_heap_reset_cpt.write(r_alloc_heap_reset_cpt.read() + 1);
-
-          if(r_alloc_heap_reset_cpt.read() == (m_heap_size-1)) {
-            m_heap.init();
-
-            r_alloc_heap_fsm = ALLOC_HEAP_READ;
-          }
-          break;
-
-        ////////////////////
-        case ALLOC_HEAP_READ:
-        if (( r_read_fsm.read() != READ_HEAP_REQ   ) &&
-            ( r_read_fsm.read() != READ_HEAP_LOCK  ) &&
-            ( r_read_fsm.read() != READ_HEAP_ERASE ))
-        {
-          if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
-            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
-
-          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
-            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
-
-          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
-
-          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
-        }
-        break;
-
-        /////////////////////
-        case ALLOC_HEAP_WRITE:
-        if (( r_write_fsm.read() != WRITE_UPT_HEAP_LOCK ) &&
-            ( r_write_fsm.read() != WRITE_UPT_REQ       ) &&
-            ( r_write_fsm.read() != WRITE_UPT_NEXT      ))
-        {
-          if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
-            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
-
-          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
-
-          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
-
-          else if ( r_read_fsm.read() == READ_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_READ;
-        }
-        break;
-
-        ////////////////////
-        case ALLOC_HEAP_CAS:
-        if (( r_cas_fsm.read() != CAS_UPT_HEAP_LOCK ) &&
-            ( r_cas_fsm.read() != CAS_UPT_REQ       ) &&
-            ( r_cas_fsm.read() != CAS_UPT_NEXT      ))
-        {
-          if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
-
-          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
-
-          else if ( r_read_fsm.read() == READ_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_READ;
-
-          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
-            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
-        }
-        break;
-
-        ///////////////////////
-        case ALLOC_HEAP_CLEANUP:
-        if (( r_cleanup_fsm.read() != CLEANUP_HEAP_REQ    ) &&
-            ( r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK   ) &&
-            ( r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH ) &&
-            ( r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN  ))
-        {
-          if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
-
-          else if ( r_read_fsm.read() == READ_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_READ;
-
-          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
-            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
-
-          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
-            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
-        }
-        break;
-
-        ////////////////////////
-        case ALLOC_HEAP_XRAM_RSP:
-        if (( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_REQ   ) &&
-            ( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE ))
-        {
-          if  ( r_read_fsm.read() == READ_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_READ;
-
-          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
-            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
-
-          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
-            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
-
-          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
-            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
-
-        }
-        break;
-
-    } // end switch alloc_heap_fsm
-
-
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    TGT_CMD to READ FIFO
-    ////////////////////////////////////////////////////////////////////////////////////
-
-    if ( cmd_read_fifo_put ) {
-      if ( cmd_read_fifo_get ) {
-        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
-        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
-        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
-        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
-        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
-      } else {
-        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
-        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
-        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
-        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
-        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
-      }
-    } else {
-      if ( cmd_read_fifo_get ) {
-        m_cmd_read_addr_fifo.simple_get();
-        m_cmd_read_length_fifo.simple_get();
-        m_cmd_read_srcid_fifo.simple_get();
-        m_cmd_read_trdid_fifo.simple_get();
-        m_cmd_read_pktid_fifo.simple_get();
-      }
-    }
-    /////////////////////////////////////////////////////////////////////
-    //    TGT_CMD to WRITE FIFO
-    /////////////////////////////////////////////////////////////////////
-
-    if ( cmd_write_fifo_put ) {
-      if ( cmd_write_fifo_get ) {
-        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
-        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
-        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
-        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
-        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
-        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
-        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
-      } else {
-        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
-        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
-        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
-        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
-        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
-        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
-        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
-      }
-    } else {
-      if ( cmd_write_fifo_get ) {
-        m_cmd_write_addr_fifo.simple_get();
-        m_cmd_write_eop_fifo.simple_get();
-        m_cmd_write_srcid_fifo.simple_get();
-        m_cmd_write_trdid_fifo.simple_get();
-        m_cmd_write_pktid_fifo.simple_get();
-        m_cmd_write_data_fifo.simple_get();
-        m_cmd_write_be_fifo.simple_get();
-      }
-    }
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    TGT_CMD to CAS FIFO
-    ////////////////////////////////////////////////////////////////////////////////////
-
-    if ( cmd_cas_fifo_put ) {
-      if ( cmd_cas_fifo_get ) {
-        m_cmd_cas_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
-        m_cmd_cas_eop_fifo.put_and_get(p_vci_tgt.eop.read());
-        m_cmd_cas_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
-        m_cmd_cas_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
-        m_cmd_cas_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
-        m_cmd_cas_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
-      } else {
-        m_cmd_cas_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
-        m_cmd_cas_eop_fifo.simple_put(p_vci_tgt.eop.read());
-        m_cmd_cas_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
-        m_cmd_cas_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
-        m_cmd_cas_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
-        m_cmd_cas_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
-      }
-    } else {
-      if ( cmd_cas_fifo_get ) {
-        m_cmd_cas_addr_fifo.simple_get();
-        m_cmd_cas_eop_fifo.simple_get();
-        m_cmd_cas_srcid_fifo.simple_get();
-        m_cmd_cas_trdid_fifo.simple_get();
-        m_cmd_cas_pktid_fifo.simple_get();
-        m_cmd_cas_wdata_fifo.simple_get();
-      }
-    }
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    WRITE to INIT_CMD FIFO
-    ////////////////////////////////////////////////////////////////////////////////////
-
-    if ( write_to_init_cmd_fifo_put ) {
-      if ( write_to_init_cmd_fifo_get ) {
-        m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
-        m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
-#if L1_MULTI_CACHE
-        m_write_to_init_cmd_cache_id_fifo.put_and_get(write_to_init_cmd_fifo_cache_id);
-#endif
-      } else {
-        m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
-        m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
-#if L1_MULTI_CACHE
-        m_write_to_init_cmd_cache_id_fifo.simple_put(write_to_init_cmd_fifo_cache_id);
-#endif
-      }
-    } else {
-      if ( write_to_init_cmd_fifo_get ) {
-        m_write_to_init_cmd_inst_fifo.simple_get();
-        m_write_to_init_cmd_srcid_fifo.simple_get();
-#if L1_MULTI_CACHE
-        m_write_to_init_cmd_cache_id_fifo.simple_get();
-#endif
-      }
-    }
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    XRAM_RSP to INIT_CMD FIFO
-    ////////////////////////////////////////////////////////////////////////////////////
-
-    if ( xram_rsp_to_init_cmd_fifo_put ) {
-      if ( xram_rsp_to_init_cmd_fifo_get ) {
-        m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
-        m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
-#if L1_MULTI_CACHE
-        m_xram_rsp_to_init_cmd_cache_id_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_cache_id);
-#endif
-      } else {
-        m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
-        m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
-#if L1_MULTI_CACHE
-        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_put(xram_rsp_to_init_cmd_fifo_cache_id);
-#endif
-      }
-    } else {
-      if ( xram_rsp_to_init_cmd_fifo_get ) {
-        m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
-        m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
-#if L1_MULTI_CACHE
-        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_get();
-#endif
-      }
-    }
-    ////////////////////////////////////////////////////////////////////////////////////
-    //    CAS to INIT_CMD FIFO
-    ////////////////////////////////////////////////////////////////////////////////////
-
-    if ( cas_to_init_cmd_fifo_put ) {
-      if ( cas_to_init_cmd_fifo_get ) {
-        m_cas_to_init_cmd_inst_fifo.put_and_get(cas_to_init_cmd_fifo_inst);
-        m_cas_to_init_cmd_srcid_fifo.put_and_get(cas_to_init_cmd_fifo_srcid);
-#if L1_MULTI_CACHE
-        m_cas_to_init_cmd_cache_id_fifo.put_and_get(cas_to_init_cmd_fifo_cache_id);
-#endif
-      } else {
-          m_cas_to_init_cmd_inst_fifo.simple_put(cas_to_init_cmd_fifo_inst);
-          m_cas_to_init_cmd_srcid_fifo.simple_put(cas_to_init_cmd_fifo_srcid);
-#if L1_MULTI_CACHE
-          m_cas_to_init_cmd_cache_id_fifo.simple_put(cas_to_init_cmd_fifo_cache_id);
-#endif
-      }
-    } else {
-        if ( cas_to_init_cmd_fifo_get ) {
-            m_cas_to_init_cmd_inst_fifo.simple_get();
-            m_cas_to_init_cmd_srcid_fifo.simple_get();
-#if L1_MULTI_CACHE
-            m_cas_to_init_cmd_cache_id_fifo.simple_get();
-#endif
-      }
-    }
-
-    m_cpt_cycles++;
+      m_cas_to_cc_send_cache_id_fifo.simple_get();
+#endif
+    }
+  }
+
+  m_cpt_cycles++;
 
 } // end transition()
@@ -6377,493 +7134,694 @@
 /////////////////////////////
 {
-    ////////////////////////////////////////////////////////////
-    // Command signals on the p_vci_ixr port
-    ////////////////////////////////////////////////////////////
-
-    p_vci_ixr.be      = 0xF;
-    p_vci_ixr.pktid   = 0;
-    p_vci_ixr.srcid   = m_srcid_ixr;
-    p_vci_ixr.cons    = false;
-    p_vci_ixr.wrap    = false;
-    p_vci_ixr.contig  = true;
-    p_vci_ixr.clen    = 0;
-    p_vci_ixr.cfixed  = false;
-
-    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
+  ////////////////////////////////////////////////////////////
+  // Command signals on the p_vci_ixr port
+  ////////////////////////////////////////////////////////////
+
+  p_vci_ixr.be      = 0xF;
+  p_vci_ixr.pktid   = 0;
+  p_vci_ixr.srcid   = m_srcid_x;
+  p_vci_ixr.cons    = false;
+  p_vci_ixr.wrap    = false;
+  p_vci_ixr.contig  = true;
+  p_vci_ixr.clen    = 0;
+  p_vci_ixr.cfixed  = false;
+
+  if(r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE)
+  {
+    p_vci_ixr.cmd     = vci_param::CMD_READ;
+    p_vci_ixr.cmdval  = true;
+    p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read() *m_words*4);
+    p_vci_ixr.plen    = m_words*4;
+    p_vci_ixr.wdata   = 0x00000000;
+    p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
+    p_vci_ixr.eop     = true;
+  }
+  else if(r_ixr_cmd_fsm.read() == IXR_CMD_CAS_NLINE)
+  {
+    if(r_cas_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_cas_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_cas_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+      p_vci_ixr.trdid   = r_cas_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_read_to_ixr_cmd_nline.read()*m_words*4);
+      p_vci_ixr.address = (addr_t)(r_cas_to_ixr_cmd_nline.read() *m_words*4);
       p_vci_ixr.plen    = m_words*4;
       p_vci_ixr.wdata   = 0x00000000;
-      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
+      p_vci_ixr.trdid   = r_cas_to_ixr_cmd_trdid.read();
       p_vci_ixr.eop     = true;
     }
-    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_CAS_NLINE ) {
-      if(r_cas_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_cas_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_cas_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
-        p_vci_ixr.trdid   = r_cas_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_cas_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_cas_to_ixr_cmd_trdid.read();
-        p_vci_ixr.eop     = true;
-      }
-    }
-    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
-      if(r_write_to_ixr_cmd_write.read()){
-        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
-        p_vci_ixr.cmdval  = true;
-        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
-        p_vci_ixr.plen    = m_words*4;
-        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
-        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
-        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
-      } else {
-        p_vci_ixr.cmd     = vci_param::CMD_READ;
-        p_vci_ixr.cmdval  = true;
-        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
-        p_vci_ixr.plen    = m_words*4;
-        p_vci_ixr.wdata   = 0x00000000;
-        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
-        p_vci_ixr.eop     = true;
-      }
-    }
-    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
+  }
+  else if(r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE)
+  {
+    if(r_write_to_ixr_cmd_write.read())
+    {
       p_vci_ixr.cmd     = vci_param::CMD_WRITE;
       p_vci_ixr.cmdval  = true;
-      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+      p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read() *m_words+r_ixr_cmd_cpt.read()) *4);
       p_vci_ixr.plen    = m_words*4;
-      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
-      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
+      p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+      p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
       p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
-    } else {
-      p_vci_ixr.cmdval  = false;
-      p_vci_ixr.address = 0;
-      p_vci_ixr.plen    = 0;
-      p_vci_ixr.wdata   = 0;
-      p_vci_ixr.trdid   = 0;
-      p_vci_ixr.eop = false;
-    }
-
-    ////////////////////////////////////////////////////
-    // Response signals on the p_vci_ixr port
-    ////////////////////////////////////////////////////
-
-    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
-          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) ||
-        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
-    else                                        p_vci_ixr.rspack = false;
-
-    ////////////////////////////////////////////////////
-    // Command signals on the p_vci_tgt port
-    ////////////////////////////////////////////////////
-
-    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
-      case TGT_CMD_IDLE:
-        p_vci_tgt.cmdack  = false;
+    }
+    else
+    {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read() *m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    }
+  }
+  else if(r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA)
+  {
+    p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+    p_vci_ixr.cmdval  = true;
+    p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read() *m_words+r_ixr_cmd_cpt.read()) *4);
+    p_vci_ixr.plen    = m_words*4;
+    p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+    p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
+    p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+  }
+  else
+  {
+    p_vci_ixr.cmdval  = false;
+    p_vci_ixr.address = 0;
+    p_vci_ixr.plen    = 0;
+    p_vci_ixr.wdata   = 0;
+    p_vci_ixr.trdid   = 0;
+    p_vci_ixr.eop = false;
+  }
+
+  ////////////////////////////////////////////////////
+  // Response signals on the p_vci_ixr port
+  ////////////////////////////////////////////////////
+
+  if(((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
+      (r_ixr_rsp_fsm.read()   == IXR_RSP_TRT_READ)) ||
+      (r_ixr_rsp_fsm.read()   == IXR_RSP_ACK))
+    
+    p_vci_ixr.rspack = true;
+
+  else
+    p_vci_ixr.rspack = false;
+
+  ////////////////////////////////////////////////////
+  // Command signals on the p_vci_tgt port
+  ////////////////////////////////////////////////////
+
+  switch((tgt_cmd_fsm_state_e) r_tgt_cmd_fsm.read())
+  {
+    case TGT_CMD_IDLE:
+      p_vci_tgt.cmdack  = false;
+      break;
+
+    case TGT_CMD_READ:
+      p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
+      break;
+
+    case TGT_CMD_WRITE:
+      p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
+      break;
+
+    case TGT_CMD_CAS:
+      p_vci_tgt.cmdack  = m_cmd_cas_addr_fifo.wok();
+      break;
+
+    default:
+      p_vci_tgt.cmdack  = false;
+      break;
+  }
+
+  ////////////////////////////////////////////////////
+  // Response signals on the p_vci_tgt port
+  ////////////////////////////////////////////////////
+
+  switch(r_tgt_rsp_fsm.read())
+  {
+    case TGT_RSP_READ_IDLE:
+    case TGT_RSP_WRITE_IDLE:
+    case TGT_RSP_CAS_IDLE:
+    case TGT_RSP_XRAM_IDLE:
+    case TGT_RSP_INIT_IDLE:
+    case TGT_RSP_CLEANUP_IDLE:
+      p_vci_tgt.rspval  = false;
+      p_vci_tgt.rsrcid  = 0;
+      p_vci_tgt.rdata   = 0;
+      p_vci_tgt.rpktid  = 0;
+      p_vci_tgt.rtrdid  = 0;
+      p_vci_tgt.rerror  = 0;
+      p_vci_tgt.reop    = false;
+      break;
+
+    case TGT_RSP_READ:
+      p_vci_tgt.rspval   = true;
+      if(((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
+          && (r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read() +r_read_to_tgt_rsp_length-1)))
+        p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()-1].read();
+      else if((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
+        p_vci_tgt.rdata  = r_read_to_tgt_rsp_ll_key.read();
+      else
+        p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
+      p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
+      p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
+      p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
+      p_vci_tgt.rerror   = 0;
+      p_vci_tgt.reop     = (r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read() +r_read_to_tgt_rsp_length-1));
+      break;
+
+    case TGT_RSP_WRITE:
+      p_vci_tgt.rspval   = true;
+      if(((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) && r_write_to_tgt_rsp_sc_fail.read())
+        p_vci_tgt.rdata  = 1;
+      else
+        p_vci_tgt.rdata  = 0;
+      p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
+      p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
+      p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
+      p_vci_tgt.rerror   = 0;
+      p_vci_tgt.reop     = true;
+      break;
+
+    case TGT_RSP_CLEANUP:
+      p_vci_tgt.rspval   = true;
+      p_vci_tgt.rdata    = 0;
+      p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
+      p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
+      p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
+      p_vci_tgt.rerror   = 0; // Can be a CAS rsp
+      p_vci_tgt.reop     = true;
+      break;
+
+    case TGT_RSP_CAS:
+      p_vci_tgt.rspval   = true;
+      p_vci_tgt.rdata    = r_cas_to_tgt_rsp_data.read();
+      p_vci_tgt.rsrcid   = r_cas_to_tgt_rsp_srcid.read();
+      p_vci_tgt.rtrdid   = r_cas_to_tgt_rsp_trdid.read();
+      p_vci_tgt.rpktid   = r_cas_to_tgt_rsp_pktid.read();
+      p_vci_tgt.rerror   = 0;
+      p_vci_tgt.reop     = true;
+      break;
+
+    case TGT_RSP_XRAM:
+      p_vci_tgt.rspval   = true;
+      if(((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
+          && (r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read() +r_xram_rsp_to_tgt_rsp_length-1)))
+        p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_ll_key.read();
+      else
+        p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
+      p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
+      p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
+      p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
+      p_vci_tgt.rerror   = 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))
+                            || r_xram_rsp_to_tgt_rsp_rerror.read());
+      break;
+
+    case TGT_RSP_INIT:
+      p_vci_tgt.rspval   = true;
+      p_vci_tgt.rdata    = 0; // Can be a CAS or SC rsp
+      p_vci_tgt.rsrcid   = r_multi_ack_to_tgt_rsp_srcid.read();
+      p_vci_tgt.rtrdid   = r_multi_ack_to_tgt_rsp_trdid.read();
+      p_vci_tgt.rpktid   = r_multi_ack_to_tgt_rsp_pktid.read();
+      p_vci_tgt.rerror   = 0;
+      p_vci_tgt.reop     = true;
+      break;
+  } // end switch r_tgt_rsp_fsm
+
+  ////////////////////////////////////////////////////////////////////
+  // Initiator command signals on the p_dspin_out port (CC_SEND FSM)
+  ////////////////////////////////////////////////////////////////////
+
+  p_dspin_out.write = false;
+  p_dspin_out.data  = 0;
+
+  switch(r_cc_send_fsm.read())
+  {
+  
+    case CC_SEND_XRAM_RSP_IDLE:
+    case CC_SEND_WRITE_IDLE:
+    case CC_SEND_CAS_IDLE:
+    case CC_SEND_CLEANUP_IDLE:
         break;
-      case TGT_CMD_READ:
-        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
+
+    case CC_SEND_CLEANUP_ACK:
+      {
+        uint64_t flit = 0;
+  
+        uint8_t cleanup_ack_type;
+        if(r_cleanup_to_cc_send_inst.read())
+        {
+          cleanup_ack_type = DspinDhccpParam::TYPE_CLEANUP_ACK_INST;
+        }
+        else 
+        {
+          cleanup_ack_type = DspinDhccpParam::TYPE_CLEANUP_ACK_DATA;
+        }
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            1ULL,
+            DspinDhccpParam::FROM_MC_EOP);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_cleanup_to_cc_send_srcid.read(),
+            DspinDhccpParam::CLEANUP_ACK_DEST);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_cleanup_to_cc_send_set_index.read(),
+            DspinDhccpParam::CLEANUP_ACK_SET);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_cleanup_to_cc_send_way_index.read(),
+            DspinDhccpParam::CLEANUP_ACK_WAY);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            cleanup_ack_type,
+            DspinDhccpParam::FROM_MC_TYPE);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
         break;
-      case TGT_CMD_WRITE:
-        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
+      }
+
+    case CC_SEND_XRAM_RSP_INVAL_HEADER:
+      {
+        if(not m_xram_rsp_to_cc_send_inst_fifo.rok()) break;
+
+        uint8_t multi_inval_type;
+        if(m_xram_rsp_to_cc_send_inst_fifo.read())
+        {
+          multi_inval_type = DspinDhccpParam::TYPE_MULTI_INVAL_INST;
+        }
+        else 
+        {
+          multi_inval_type = DspinDhccpParam::TYPE_MULTI_INVAL_DATA;
+        }
+
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            m_xram_rsp_to_cc_send_srcid_fifo.read(),
+            DspinDhccpParam::MULTI_INVAL_DEST);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            m_cc_global_id,
+            DspinDhccpParam::MULTI_INVAL_SRCID);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_xram_rsp_to_cc_send_trdid.read(),
+            DspinDhccpParam::MULTI_INVAL_UPDT_INDEX);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            multi_inval_type,
+            DspinDhccpParam::FROM_MC_TYPE);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit; 
+
         break;
-      case TGT_CMD_CAS:
-        p_vci_tgt.cmdack  = m_cmd_cas_addr_fifo.wok();
+      }
+
+    case CC_SEND_XRAM_RSP_INVAL_NLINE:
+      {
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            1ULL,
+            DspinDhccpParam::FROM_MC_EOP);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_xram_rsp_to_cc_send_nline.read(),
+            DspinDhccpParam::MULTI_INVAL_NLINE);
+        
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
         break;
-      default:
-        p_vci_tgt.cmdack  = false;
+      }
+
+    case CC_SEND_XRAM_RSP_BRDCAST_HEADER:
+    case CC_SEND_WRITE_BRDCAST_HEADER:
+    case CC_SEND_CAS_BRDCAST_HEADER:
+      {
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            m_broadcast_address,
+            DspinDhccpParam::BROADCAST_BOX);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            m_cc_global_id,
+            DspinDhccpParam::BROADCAST_SRCID);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            1ULL,
+            DspinDhccpParam::FROM_MC_BC);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
         break;
-    }
-
-    ////////////////////////////////////////////////////
-    // Response signals on the p_vci_tgt port
-    ////////////////////////////////////////////////////
-    switch ( r_tgt_rsp_fsm.read() ) {
-
-      case TGT_RSP_READ_IDLE:
-      case TGT_RSP_WRITE_IDLE:
-      case TGT_RSP_CAS_IDLE:
-      case TGT_RSP_XRAM_IDLE:
-      case TGT_RSP_INIT_IDLE:
-      case TGT_RSP_CLEANUP_IDLE:
-        p_vci_tgt.rspval  = false;
-        p_vci_tgt.rsrcid  = 0;
-        p_vci_tgt.rdata   = 0;
-        p_vci_tgt.rpktid  = 0;
-        p_vci_tgt.rtrdid  = 0;
-        p_vci_tgt.rerror  = 0;
-        p_vci_tgt.reop    = false;
+      }
+
+    case CC_SEND_XRAM_RSP_BRDCAST_NLINE:
+      {
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            1ULL,
+            DspinDhccpParam::FROM_MC_EOP);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_xram_rsp_to_cc_send_nline.read(),
+            DspinDhccpParam::BROADCAST_NLINE);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
         break;
-      case TGT_RSP_READ:
-        p_vci_tgt.rspval   = true;
-        if( ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
-            && (r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1)) )
-          p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()-1].read();
-        else if ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
-          p_vci_tgt.rdata  = r_read_to_tgt_rsp_ll_key.read();
+      }
+
+    case CC_SEND_WRITE_BRDCAST_NLINE:
+      {
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            1ULL,
+            DspinDhccpParam::FROM_MC_EOP);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_write_to_cc_send_nline.read(),
+            DspinDhccpParam::BROADCAST_NLINE);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
+        break;
+      }
+
+    case CC_SEND_CAS_BRDCAST_NLINE:
+      {
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            1ULL,
+            DspinDhccpParam::FROM_MC_EOP);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_cas_to_cc_send_nline.read(),
+            DspinDhccpParam::BROADCAST_NLINE);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
+        break;
+      }
+
+    case CC_SEND_WRITE_UPDT_HEADER:
+      {
+        if(not m_write_to_cc_send_inst_fifo.rok()) break;
+
+        uint8_t multi_updt_type;
+        if(m_write_to_cc_send_inst_fifo.read())
+        {
+          multi_updt_type = DspinDhccpParam::TYPE_MULTI_UPDT_INST;
+        }
+        else 
+        {
+          multi_updt_type = DspinDhccpParam::TYPE_MULTI_UPDT_DATA;
+        }
+
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            m_write_to_cc_send_srcid_fifo.read(),
+            DspinDhccpParam::MULTI_UPDT_DEST);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            m_cc_global_id,
+            DspinDhccpParam::MULTI_UPDT_SRCID);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_write_to_cc_send_trdid.read(),
+            DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            multi_updt_type,
+            DspinDhccpParam::FROM_MC_TYPE);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
+        break;
+      }
+
+    case CC_SEND_WRITE_UPDT_NLINE:
+      {
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_write_to_cc_send_index.read(),
+            DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_write_to_cc_send_nline.read(),
+            DspinDhccpParam::MULTI_UPDT_NLINE);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
+        break;
+      }
+
+    case CC_SEND_WRITE_UPDT_DATA:
+      {
+        uint8_t multi_updt_eop;
+        if(  r_cc_send_cpt.read() ==
+            (r_write_to_cc_send_count.read()-1))
+        {
+          multi_updt_eop = 1;
+        }
         else
-          p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
-        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
-        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
-        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
-        p_vci_tgt.rerror   = 0;
-        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
+        {
+          multi_updt_eop = 0;
+        }
+
+        uint8_t multi_updt_cpt  = 
+          r_cc_send_cpt.read() + r_write_to_cc_send_index.read();
+
+        uint8_t  multi_updt_be   = r_write_to_cc_send_be[multi_updt_cpt].read();
+        uint32_t multi_updt_data = r_write_to_cc_send_data[multi_updt_cpt].read();
+
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            (uint64_t)multi_updt_eop,
+            DspinDhccpParam::FROM_MC_EOP);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            multi_updt_be,
+            DspinDhccpParam::MULTI_UPDT_BE);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            multi_updt_data,
+            DspinDhccpParam::MULTI_UPDT_DATA);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
         break;
-      case TGT_RSP_WRITE:
-        /*if( ((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) )
-            {
-              std::cout << "SC RSP / rsrcid = " << r_write_to_tgt_rsp_srcid.read() << " / rdata = " << r_write_to_tgt_rsp_sc_fail.read() << std::endl;
-            }*/
-        p_vci_tgt.rspval   = true;
-        if( ((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) && r_write_to_tgt_rsp_sc_fail.read() )
-          p_vci_tgt.rdata  = 1;
+      }
+
+    case CC_SEND_CAS_UPDT_HEADER:
+      {
+        if (not m_cas_to_cc_send_inst_fifo.rok()) break;
+
+        uint8_t multi_updt_type;
+        if(m_cas_to_cc_send_inst_fifo.read())
+        {
+          multi_updt_type = DspinDhccpParam::TYPE_MULTI_UPDT_INST;
+        }
+        else 
+        {
+          multi_updt_type = DspinDhccpParam::TYPE_MULTI_UPDT_DATA;
+        }
+
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            m_cas_to_cc_send_srcid_fifo.read(),
+            DspinDhccpParam::MULTI_UPDT_DEST);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            m_cc_global_id,
+            DspinDhccpParam::MULTI_UPDT_SRCID);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_cas_to_cc_send_trdid.read(),
+            DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            multi_updt_type,
+            DspinDhccpParam::FROM_MC_TYPE);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
+        break;
+      }
+
+    case CC_SEND_CAS_UPDT_NLINE:
+      {
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_cas_to_cc_send_index.read(),
+            DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_cas_to_cc_send_nline.read(),
+            DspinDhccpParam::MULTI_UPDT_NLINE);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
+        break;
+      }
+
+    case CC_SEND_CAS_UPDT_DATA:
+      {
+        uint8_t multi_updt_eop;
+        if(not r_cas_to_cc_send_is_long.read())
+        {
+          multi_updt_eop = 1;
+        }
         else
-          p_vci_tgt.rdata  = 0;
-        p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
-        p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
-        p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
-        //p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1);
-        p_vci_tgt.rerror   = 0;
-        p_vci_tgt.reop     = true;
+        {
+          multi_updt_eop = 0;
+        }
+
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            (uint64_t)multi_updt_eop,
+            DspinDhccpParam::FROM_MC_EOP);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            0xF,
+            DspinDhccpParam::MULTI_UPDT_BE);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_cas_to_cc_send_wdata.read(),
+            DspinDhccpParam::MULTI_UPDT_DATA);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
         break;
-      case TGT_RSP_CLEANUP:
-        p_vci_tgt.rspval   = true;
-        p_vci_tgt.rdata    = 0;
-        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
-        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
-        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
-        p_vci_tgt.rerror   = 0; // Can be a CAS rsp
-        p_vci_tgt.reop     = true;
+      }
+
+    case CC_SEND_CAS_UPDT_DATA_HIGH:
+      {
+        uint64_t flit = 0;
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            1ULL,
+            DspinDhccpParam::FROM_MC_EOP);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            0xF,
+            DspinDhccpParam::MULTI_UPDT_BE);
+
+        DspinDhccpParam::dspin_set(
+            flit,
+            r_cas_to_cc_send_wdata_high.read(),
+            DspinDhccpParam::MULTI_UPDT_DATA);
+
+        p_dspin_out.write = true;
+        p_dspin_out.data  = flit;
+
         break;
-      case TGT_RSP_CAS:
-        p_vci_tgt.rspval   = true;
-        p_vci_tgt.rdata    = r_cas_to_tgt_rsp_data.read();
-        p_vci_tgt.rsrcid   = r_cas_to_tgt_rsp_srcid.read();
-        p_vci_tgt.rtrdid   = r_cas_to_tgt_rsp_trdid.read();
-        p_vci_tgt.rpktid   = r_cas_to_tgt_rsp_pktid.read();
-        p_vci_tgt.rerror   = 0;
-        p_vci_tgt.reop     = true;
+      }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Target command signals from the p_dspin_in port (CC_RECEIVE FSM)
+  ///////////////////////////////////////////////////////////////////
+  p_dspin_in.read = false;
+  switch(r_cc_receive_fsm.read())
+  {
+    case CC_RECEIVE_IDLE:
+      {
         break;
-      case TGT_RSP_XRAM:
-        p_vci_tgt.rspval   = true;
-        if( ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
-            && (r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length-1)) )
-          p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_ll_key.read();
-        else
-          p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
-        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
-        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
-        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
-        p_vci_tgt.rerror   = 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))
-            || r_xram_rsp_to_tgt_rsp_rerror.read());
+      }
+    case CC_RECEIVE_CLEANUP:
+      {
+        p_dspin_in.read = m_cc_receive_to_cleanup_fifo.wok();
         break;
-      case TGT_RSP_INIT:
-        p_vci_tgt.rspval   = true;
-        p_vci_tgt.rdata    = 0; // Can be a CAS or SC rsp
-        p_vci_tgt.rsrcid   = r_init_rsp_to_tgt_rsp_srcid.read();
-        p_vci_tgt.rtrdid   = r_init_rsp_to_tgt_rsp_trdid.read();
-        p_vci_tgt.rpktid   = r_init_rsp_to_tgt_rsp_pktid.read();
-        p_vci_tgt.rerror   = 0;
-        p_vci_tgt.reop     = true;
+      }
+    case CC_RECEIVE_MULTI_ACK:
+      {
+        p_dspin_in.read = m_cc_receive_to_multi_ack_fifo.wok();
         break;
-    } // end switch r_tgt_rsp_fsm
-
-    ///////////////////////////////////////////////////
-    // Command signals on the p_vci_ini port
-    ///////////////////////////////////////////////////
-
-    p_vci_ini.cmd     = vci_param::CMD_WRITE;
-    p_vci_ini.srcid   = m_srcid_ini;
-    p_vci_ini.cons    = true;
-    p_vci_ini.wrap    = false;
-    p_vci_ini.contig  = false;
-    p_vci_ini.clen    = 0;
-    p_vci_ini.cfixed  = false;
-
-    vci_addr_t vci_ini_address = 0;
-    switch ( r_init_cmd_fsm.read() ) {
-
-      case INIT_CMD_UPDT_IDLE:
-      case INIT_CMD_INVAL_IDLE:
-      case INIT_CMD_CAS_UPDT_IDLE:
-        p_vci_ini.cmdval  = false;
-        p_vci_ini.address = 0;
-        p_vci_ini.wdata   = 0;
-        p_vci_ini.be      = 0;
-        p_vci_ini.plen    = 0;
-        p_vci_ini.trdid   = 0;
-        p_vci_ini.pktid   = 0;
-        p_vci_ini.eop     = false;
-        break;
-      case INIT_CMD_INVAL_NLINE:
-      {
-        vci_ini_address = (vci_addr_t)
-            m_xram_rsp_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
-
-        p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
-        if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
-          if(m_xram_rsp_to_init_cmd_inst_fifo.read()) {
-              p_vci_ini.address = (addr_t) (vci_ini_address+4);
-          } else {
-              p_vci_ini.address = (addr_t) (vci_ini_address);
-          }
-        } else p_vci_ini.address = 0; // prevent segmentation faults by reading an empty fifo
-        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
-        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
-        p_vci_ini.plen    = 4;
-        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
-#if L1_MULTI_CACHE
-        p_vci_ini.pktid   = m_xram_rsp_to_init_cmd_cache_id_fifo.read();
-#endif
-        p_vci_ini.eop     = true;
-        break;
-      }
-      case INIT_CMD_XRAM_BRDCAST:
-        p_vci_ini.cmdval  = true;
-        p_vci_ini.address = m_broadcast_address;
-        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
-        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
-        p_vci_ini.plen    = 4;
-        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
-        p_vci_ini.pktid   = 0;
-        p_vci_ini.eop     = true;
-        break;
-
-      case INIT_CMD_WRITE_BRDCAST:
-        p_vci_ini.cmdval  = true;
-        p_vci_ini.address = m_broadcast_address;
-        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
-        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
-        p_vci_ini.plen    = 4 ;
-        p_vci_ini.eop     = true;
-        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
-        p_vci_ini.pktid   = 0;
-        break;
-      case INIT_CMD_UPDT_NLINE:
-        vci_ini_address = (vci_addr_t)
-            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
-
-        p_vci_ini.cmdval  = m_write_to_init_cmd_inst_fifo.rok();
-        if(m_write_to_init_cmd_inst_fifo.rok()){
-          if(m_write_to_init_cmd_inst_fifo.read()) {
-            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
-          } else {
-            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
-          }
-        } else {
-          p_vci_ini.address = 0;
-        }
-        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
-        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
-        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
-        p_vci_ini.eop     = false;
-        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
-#if L1_MULTI_CACHE
-        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
-#endif
-        break;
-      case INIT_CMD_UPDT_INDEX:
-        vci_ini_address = (vci_addr_t)
-            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
-
-        p_vci_ini.cmdval  = true;
-        if(m_write_to_init_cmd_inst_fifo.read()) {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
-        } else {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
-        }
-        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
-        p_vci_ini.be      = 0xF;
-        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
-        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
-#if L1_MULTI_CACHE
-        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
-#endif
-        p_vci_ini.eop     = false;
-        break;
-      case INIT_CMD_UPDT_DATA:
-        vci_ini_address = (vci_addr_t)
-            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
-
-        p_vci_ini.cmdval  = true;
-        if(m_write_to_init_cmd_inst_fifo.read()) {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
-        } else {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
-        }
-        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
-          r_write_to_init_cmd_index.read()].read();
-        p_vci_ini.be      = r_write_to_init_cmd_be[r_init_cmd_cpt.read() +
-            r_write_to_init_cmd_index.read()].read()  ;
-        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
-        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
-#if L1_MULTI_CACHE
-        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
-#endif
-        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
-        break;
-
-      case INIT_CMD_CAS_BRDCAST:
-        p_vci_ini.cmdval  = true;
-        p_vci_ini.address = m_broadcast_address;
-        p_vci_ini.wdata   = (addr_t)r_cas_to_init_cmd_nline.read();
-        p_vci_ini.be      = ((r_cas_to_init_cmd_nline.read() >> 32) & 0x3);
-        p_vci_ini.plen    = 4 ;
-        p_vci_ini.eop     = true;
-        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
-        p_vci_ini.pktid   = 0;
-        break;
-      case INIT_CMD_CAS_UPDT_NLINE:
-        vci_ini_address = (vci_addr_t)
-            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
-
-        p_vci_ini.cmdval  = m_cas_to_init_cmd_inst_fifo.rok();
-        if(m_cas_to_init_cmd_inst_fifo.rok()){
-          if( m_cas_to_init_cmd_inst_fifo.read() ) {
-            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
-          } else {
-            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
-          }
-        } else {
-          p_vci_ini.address = 0;
-        }
-        p_vci_ini.wdata   = (uint32_t)r_cas_to_init_cmd_nline.read();
-        p_vci_ini.be      = ((r_cas_to_init_cmd_nline.read() >> 32 ) & 0x3);
-        if(r_cas_to_init_cmd_is_long.read()){
-            p_vci_ini.plen    = 4 * 4;
-        } else {
-            p_vci_ini.plen    = 4 * 3;
-        }
-        p_vci_ini.eop     = false;
-        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
-#if L1_MULTI_CACHE
-        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
-#endif
-        break;
-      case INIT_CMD_CAS_UPDT_INDEX:
-        vci_ini_address = (vci_addr_t)
-            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
-
-        p_vci_ini.cmdval  = true;
-        if( m_cas_to_init_cmd_inst_fifo.read() ) {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
-        } else {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
-        }
-        p_vci_ini.wdata   = r_cas_to_init_cmd_index.read();
-        p_vci_ini.be      = 0xF;
-        if(r_cas_to_init_cmd_is_long.read()){
-            p_vci_ini.plen    = 4 * 4;
-        } else {
-            p_vci_ini.plen    = 4 * 3;
-        }
-        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
-#if L1_MULTI_CACHE
-        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
-#endif
-        p_vci_ini.eop     = false;
-        break;
-      case INIT_CMD_CAS_UPDT_DATA:
-        vci_ini_address = (vci_addr_t)
-            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
-
-        p_vci_ini.cmdval  = true;
-        if( m_cas_to_init_cmd_inst_fifo.read() ) {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
-        } else {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
-        }
-        p_vci_ini.wdata   = r_cas_to_init_cmd_wdata.read();
-        p_vci_ini.be      = 0xF;
-        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
-#if L1_MULTI_CACHE
-        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
-#endif
-        if(r_cas_to_init_cmd_is_long.read()){
-            p_vci_ini.plen    = 4 * 4;
-            p_vci_ini.eop     = false;
-        } else {
-            p_vci_ini.plen    = 4 * 3;
-            p_vci_ini.eop     = true;
-        }
-        break;
-      case INIT_CMD_CAS_UPDT_DATA_HIGH:
-        vci_ini_address = (vci_addr_t)
-            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
-
-        p_vci_ini.cmdval  = true;
-        if( m_cas_to_init_cmd_inst_fifo.read() ) {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
-        } else {
-          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
-        }
-        p_vci_ini.wdata   = r_cas_to_init_cmd_wdata_high.read();
-        p_vci_ini.be      = 0xF;
-        p_vci_ini.plen    = 4 * 4;
-        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
-#if L1_MULTI_CACHE
-        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
-#endif
-        p_vci_ini.eop     = true;
-        break;
-
-    } // end switch r_init_cmd_fsm
-
-    //////////////////////////////////////////////////////
-    // Response signals on the p_vci_ini port
-    //////////////////////////////////////////////////////
-
-    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
-    else                                          p_vci_ini.rspack  = false;
-
-    //////////////////////////////////////////////////////
-    // Response signals on the p_vci_tgt_cleanup port
-    //////////////////////////////////////////////////////
-    p_vci_tgt_cleanup.rspval = false;
-    p_vci_tgt_cleanup.rsrcid = 0;
-    p_vci_tgt_cleanup.rdata  = 0;
-    p_vci_tgt_cleanup.rpktid = 0;
-    p_vci_tgt_cleanup.rtrdid = 0;
-    p_vci_tgt_cleanup.rerror = 0;
-    p_vci_tgt_cleanup.reop   = false;
-    p_vci_tgt_cleanup.cmdack = false ;
-
-    switch(r_cleanup_fsm.read()){
-      case CLEANUP_IDLE:
-        {
-          p_vci_tgt_cleanup.cmdack = true ;
-          break;
-        }
-      case CLEANUP_RSP:
-        {
-          /////////////////////////////////////////////////////////////////////
-          // Returning L1 cache SET index in RDATA.
-          // The maximum SET index width of a L1 cache must be 16 bits.
-          p_vci_tgt_cleanup.rspval = true;
-          p_vci_tgt_cleanup.rdata  = r_cleanup_nline.read() & 0xFFFF;
-          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
-          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
-          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
-          p_vci_tgt_cleanup.rerror = 0x2 & ( (1 << vci_param::E) - 1);
-          p_vci_tgt_cleanup.reop   = 1;
-          break;
-        }
-
-    }
-
+      }
+  }
+  // end switch r_cc_send_fsm
 } // end genMoore()
 
-}} // end name space
+}
+} // end name space
 
 // Local Variables:
