Index: branches/RWT/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp
===================================================================
--- trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 468)
+++ branches/RWT/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 477)
@@ -107,4 +107,8 @@
   "CC_SEND_XRAM_RSP_INVAL_HEADER",
   "CC_SEND_XRAM_RSP_INVAL_NLINE",
+  "CC_SEND_READ_NCC_INVAL_HEADER",
+  "CC_SEND_READ_NCC_INVAL_NLINE",
+  "CC_SEND_WRITE_NCC_INVAL_HEADER",
+  "CC_SEND_WRITE_NCC_INVAL_NLINE",
   "CC_SEND_WRITE_BRDCAST_HEADER",
   "CC_SEND_WRITE_BRDCAST_NLINE",
@@ -148,4 +152,6 @@
   "READ_DIR_REQ",
   "READ_DIR_LOCK",
+  "READ_IVT_LOCK",
+  "READ_WAIT",
   "READ_DIR_HIT",
   "READ_HEAP_REQ",
@@ -165,4 +171,5 @@
   "WRITE_DIR_REQ",
   "WRITE_DIR_LOCK",
+  "WRITE_IVT_LOCK_HIT_WB",
   "WRITE_DIR_READ",
   "WRITE_DIR_HIT",
@@ -173,4 +180,5 @@
   "WRITE_UPT_DEC",
   "WRITE_RSP",
+  "WRITE_MISS_IVT_LOCK",
   "WRITE_MISS_TRT_LOCK",
   "WRITE_MISS_TRT_DATA",
@@ -215,8 +223,10 @@
   "IXR_CMD_CAS_IDLE",
   "IXR_CMD_XRAM_IDLE",
+  "IXR_CMD_CLEANUP_IDLE",
   "IXR_CMD_READ",
   "IXR_CMD_WRITE",
   "IXR_CMD_CAS",
-  "IXR_CMD_XRAM"
+  "IXR_CMD_XRAM",
+  "IXR_CMD_CLEANUP_DATA"
 };
 const char *cas_fsm_str[] =
@@ -248,7 +258,11 @@
   "CLEANUP_IDLE",
   "CLEANUP_GET_NLINE",
+  "CLEANUP_GET_DATA",
   "CLEANUP_DIR_REQ",
   "CLEANUP_DIR_LOCK",
   "CLEANUP_DIR_WRITE",
+  "CLEANUP_IVT_LOCK_DATA",
+  "CLEANUP_IVT_CLEAR_DATA",
+  "CLEANUP_READ_RSP",
   "CLEANUP_HEAP_REQ",
   "CLEANUP_HEAP_LOCK",
@@ -260,4 +274,6 @@
   "CLEANUP_IVT_CLEAR",
   "CLEANUP_WRITE_RSP",
+  "CLEANUP_IXR_REQ",
+  "CLEANUP_WAIT",
   "CLEANUP_CONFIG_ACK",
   "CLEANUP_SEND_CLACK"
@@ -279,5 +295,6 @@
   "ALLOC_TRT_CAS",
   "ALLOC_TRT_XRAM_RSP",
-  "ALLOC_TRT_IXR_RSP"
+  "ALLOC_TRT_IXR_RSP",
+  "ALLOC_TRT_CLEANUP"
 };
 const char *alloc_upt_fsm_str[] =
@@ -290,4 +307,5 @@
 {
   "ALLOC_IVT_WRITE",
+  "ALLOC_IVT_READ",
   "ALLOC_IVT_XRAM_RSP",
   "ALLOC_IVT_CLEANUP",
@@ -339,4 +357,5 @@
   : soclib::caba::BaseModule(name),
 
+    m_monitor_ok(false),
     p_clk( "p_clk" ),
     p_resetn( "p_resetn" ),
@@ -526,4 +545,10 @@
     r_cas_data                 = new sc_signal<data_t>[nwords];
     r_cas_rdata                = new sc_signal<data_t>[2];
+
+    // Allocation for ODCCP
+    r_cleanup_data             = new sc_signal<data_t>[nwords];
+    r_cleanup_to_ixr_cmd_data  = new sc_signal<data_t>[nwords];
+    r_cleanup_to_tgt_rsp_data  = new sc_signal<data_t>[nwords];
+    r_cleanup_old_data         = new sc_signal<data_t>[nwords];
 
     // Allocation for debug
@@ -641,4 +666,76 @@
 
 /////////////////////////////////////////
+tmpl(void) ::clear_stats()
+/////////////////////////////////////////
+{
+
+    m_cpt_cycles                  = 0;
+    m_cpt_read                    = 0;
+    m_cpt_read_miss               = 0;
+    m_cpt_write                   = 0;
+    m_cpt_write_miss              = 0;
+    m_cpt_write_cells             = 0;
+    m_cpt_write_dirty             = 0;
+    m_cpt_update                  = 0;
+    m_cpt_update_mult             = 0;
+    m_cpt_inval_brdcast           = 0;
+    m_cpt_inval                   = 0;
+    m_cpt_inval_mult              = 0;
+    m_cpt_cleanup                 = 0;
+    m_cpt_ll                      = 0;
+    m_cpt_sc                      = 0;
+    m_cpt_cas                     = 0;
+    m_cpt_trt_full                = 0;
+    m_cpt_trt_rb                  = 0;
+    m_cpt_dir_unused              = 0;
+    m_cpt_ivt_unused              = 0;
+    m_cpt_upt_unused              = 0;
+    m_cpt_heap_unused             = 0;
+    m_cpt_trt_unused              = 0;
+    m_cpt_read_fsm_n_dir_lock     = 0;
+    m_cpt_read_fsm_dir_lock       = 0;
+    m_cpt_read_fsm_dir_used       = 0;
+    m_cpt_read_fsm_trt_lock       = 0;
+    m_cpt_read_fsm_heap_lock      = 0;
+    m_cpt_write_fsm_dir_lock      = 0;
+    m_cpt_write_fsm_n_dir_lock    = 0;
+    m_cpt_write_fsm_upt_lock      = 0;
+    m_cpt_write_fsm_heap_lock     = 0;
+    m_cpt_write_fsm_dir_used      = 0;
+    m_cpt_write_fsm_trt_lock      = 0;
+    m_cpt_cas_fsm_n_dir_lock      = 0;
+    m_cpt_cas_fsm_dir_lock        = 0;
+    m_cpt_cas_fsm_upt_lock        = 0;
+    m_cpt_cas_fsm_heap_lock       = 0;
+    m_cpt_cas_fsm_trt_lock        = 0;
+    m_cpt_cas_fsm_dir_used        = 0;
+    m_cpt_xram_rsp_fsm_n_dir_lock = 0;
+    m_cpt_xram_rsp_fsm_dir_lock   = 0;
+    m_cpt_xram_rsp_fsm_trt_lock   = 0;
+    m_cpt_xram_rsp_fsm_upt_lock   = 0;
+    m_cpt_xram_rsp_fsm_heap_lock  = 0;
+    m_cpt_xram_rsp_fsm_dir_used   = 0;
+    m_cpt_cleanup_fsm_dir_lock    = 0;
+    m_cpt_cleanup_fsm_n_dir_lock  = 0;
+    m_cpt_cleanup_fsm_heap_lock   = 0;
+    m_cpt_cleanup_fsm_ivt_lock    = 0;
+    m_cpt_cleanup_fsm_dir_used    = 0;
+    m_cpt_ixr_fsm_trt_lock        = 0;
+    m_cpt_multi_ack_fsm_upt_lock  = 0;
+    m_cpt_read_data_unc           = 0;   
+    m_cpt_read_data_miss_CC       = 0;   
+    m_cpt_read_ins_unc            = 0;        
+    m_cpt_read_ins_miss           = 0;      
+    m_cpt_read_ll_CC              = 0;       
+    m_cpt_read_data_miss_NCC      = 0;        
+    m_cpt_read_ll_NCC             = 0;    
+    m_cpt_read_WTF                = 0;   
+    m_cpt_cleanup_data            = 0;      
+    m_cpt_ncc_to_cc_read          = 0;      
+    m_cpt_ncc_to_cc_write         = 0;       
+    m_cpt_ncc_to_cc               = 0;        
+}
+
+/////////////////////////////////////////
 tmpl(void) ::print_stats()
 /////////////////////////////////////////
@@ -647,24 +744,86 @@
   std::cout
       << "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;
+      << "- 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 << std::endl
+
+      << "- WAIT DIR LOCK in READ_FSM              = " << (double) m_cpt_read_fsm_dir_lock/m_cpt_read_fsm_n_dir_lock << std::endl
+      << "- NB CYCLES IN DIR LOCK in READ_FSM      = " << (double) m_cpt_read_fsm_dir_used/m_cpt_read_fsm_n_dir_lock << std::endl
+      << "- WAIT DIR LOCK in WRITE_FSM             = " << (double) m_cpt_write_fsm_dir_lock/m_cpt_write_fsm_n_dir_lock << std::endl
+      << "- NB CYCLES IN DIR LOCK in WRITE_FSM     = " << (double) m_cpt_write_fsm_dir_used/m_cpt_write_fsm_n_dir_lock << std::endl
+      << "- WAIT DIR LOCK in XRAM_FSM              = " << (double) m_cpt_xram_rsp_fsm_dir_lock/m_cpt_xram_rsp_fsm_n_dir_lock << std::endl
+      << "- NB CYCLES IN DIR LOCK in XRAM_FSM      = " << (double) m_cpt_xram_rsp_fsm_dir_used/m_cpt_xram_rsp_fsm_n_dir_lock << std::endl
+      << "- WAIT DIR LOCK in CLEANUP_FSM           = " << (double) m_cpt_cleanup_fsm_dir_lock/m_cpt_cleanup_fsm_n_dir_lock << std::endl
+      << "- NB CYCLES IN DIR LOCK in CLEANUP_FSM   = " << (double) m_cpt_cleanup_fsm_dir_used/m_cpt_cleanup_fsm_n_dir_lock << std::endl
+      << "- WAIT DIR LOCK in CAS_FSM               = " << (double) m_cpt_cas_fsm_dir_lock/m_cpt_cas_fsm_n_dir_lock << std::endl
+      << "- NB CYCLES IN LOCK in CAS_FSM           = " << (double) m_cpt_cas_fsm_dir_used/m_cpt_cas_fsm_n_dir_lock << std::endl
+      << "- DIR UNUSED RATE                        = " << (double) m_cpt_dir_unused/m_cpt_cycles << std::endl << std::endl
+      
+      << "- WAIT TRT LOCK in READ_FSM              = " << (double) m_cpt_read_fsm_trt_lock/m_cpt_read_fsm_n_trt_lock << std::endl
+      << "- NB CYCLES IN TRT LOCK in READ_FSM      = " << (double) m_cpt_read_fsm_trt_used/m_cpt_read_fsm_n_trt_lock << std::endl
+      << "- WAIT TRT LOCK in WRITE_FSM             = " << (double) m_cpt_write_fsm_trt_lock/m_cpt_write_fsm_n_trt_lock << std::endl
+      << "- NB CYCLES IN TRT LOCK in WRITE_FSM     = " << (double) m_cpt_write_fsm_trt_used/m_cpt_write_fsm_n_trt_lock << std::endl
+      << "- WAIT TRT LOCK in CAS_FSM               = " << (double) m_cpt_cas_fsm_trt_lock/m_cpt_cas_fsm_n_trt_lock << std::endl
+      << "- NB CYCLES IN TRT LOCK in CAS_FSM       = " << (double) m_cpt_cas_fsm_trt_used/m_cpt_cas_fsm_n_trt_lock << std::endl
+      << "- WAIT TRT LOCK in XRAM_FSM              = " << (double) m_cpt_xram_rsp_fsm_trt_lock/m_cpt_xram_rsp_fsm_n_trt_lock << std::endl
+      << "- NB CYCLES IN TRT LOCK in XRAM_FSM      = " << (double) m_cpt_xram_rsp_fsm_trt_used/m_cpt_xram_rsp_fsm_n_trt_lock << std::endl
+      << "- WAIT TRT LOCK in IXR_FSM               = " << (double) m_cpt_ixr_fsm_trt_lock/m_cpt_ixr_fsm_n_trt_lock << std::endl
+      << "- NB CYCLES IN TRT LOCK in IXR_FSM       = " << (double) m_cpt_ixr_fsm_trt_used/m_cpt_ixr_fsm_n_trt_lock << std::endl
+      << "- TRT UNUSED RATE                        = " << (double) m_cpt_trt_unused/m_cpt_cycles << std::endl << std::endl
+      
+      << "- WAIT UPT LOCK in WRITE_FSM             = " << (double) m_cpt_write_fsm_upt_lock/m_cpt_write_fsm_n_upt_lock << std::endl
+      << "- NB CYCLES IN UPT LOCK in WRITE_FSM     = " << (double) m_cpt_write_fsm_upt_used/m_cpt_write_fsm_n_upt_lock << std::endl
+      << "- WAIT UPT LOCK in XRAM_FSM              = " << (double) m_cpt_xram_rsp_fsm_upt_lock/m_cpt_xram_rsp_fsm_n_upt_lock << std::endl
+      << "- NB CYCLES IN UPT LOCK in XRAM_FSM      = " << (double) m_cpt_xram_rsp_fsm_upt_used/m_cpt_xram_rsp_fsm_n_upt_lock << std::endl
+      << "- WAIT UPT LOCK in MULTIACK_FSM          = " << (double) m_cpt_multi_ack_fsm_upt_lock/m_cpt_multi_ack_fsm_n_upt_lock << std::endl
+      << "- NB CYCLES IN UPT LOCK in MULTIACK_FSM  = " << (double) m_cpt_multi_ack_fsm_upt_used/m_cpt_multi_ack_fsm_n_upt_lock << std::endl
+      << "- WAIT UPT LOCK in CLEANUP_FSM           = " << (double) m_cpt_cleanup_fsm_ivt_lock/m_cpt_cleanup_fsm_n_upt_lock << std::endl
+      << "- NB CYCLES IN UPT LOCK in CLEANUP_FSM   = " << (double) m_cpt_cleanup_fsm_ivt_used/m_cpt_cleanup_fsm_n_upt_lock << std::endl
+      << "- WAIT UPT LOCK in CAS_FSM               = " << (double) m_cpt_cas_fsm_upt_lock/m_cpt_cas_fsm_n_upt_lock << std::endl
+      << "- NB CYCLES IN UPT LOCK in CAS_FSM       = " << (double) m_cpt_cas_fsm_upt_used/m_cpt_cas_fsm_n_upt_lock << std::endl
+      << "- UPT UNUSED RATE                        = " << (double) m_cpt_upt_unused/m_cpt_cycles << std::endl << std::endl
+      << "- IVT UNUSED RATE                        = " << (double) m_cpt_ivt_unused/m_cpt_cycles << std::endl << std::endl
+      
+      << "- WAIT HEAP LOCK in READ_FSM             = " << (double) m_cpt_read_fsm_heap_lock/m_cpt_read_fsm_n_heap_lock << std::endl
+      << "- NB CYCLES IN HEAP LOCK in READ_FSM     = " << (double) m_cpt_read_fsm_heap_used/m_cpt_read_fsm_n_heap_lock << std::endl
+      << "- WAIT HEAP LOCK in WRITE_FSM            = " << (double) m_cpt_write_fsm_heap_lock/m_cpt_write_fsm_n_heap_lock << std::endl
+      << "- NB CYCLES IN HEAP LOCK in WRITE_FSM    = " << (double) m_cpt_write_fsm_heap_used/m_cpt_write_fsm_n_heap_lock << std::endl
+      << "- WAIT HEAP LOCK in XRAM_FSM             = " << (double) m_cpt_xram_rsp_fsm_heap_lock/m_cpt_xram_rsp_fsm_n_heap_lock << std::endl
+      << "- NB CYCLES IN HEAP LOCK in XRAM_FSM     = " << (double) m_cpt_xram_rsp_fsm_heap_used/m_cpt_xram_rsp_fsm_n_heap_lock << std::endl
+      << "- WAIT HEAP LOCK in CLEANUP_FSM          = " << (double) m_cpt_cleanup_fsm_heap_lock/m_cpt_cleanup_fsm_n_heap_lock << std::endl
+      << "- NB CYCLES IN HEAP LOCK in CLEANUP_FSM  = " << (double) m_cpt_cleanup_fsm_heap_used/m_cpt_cleanup_fsm_n_heap_lock << std::endl
+      << "- WAIT HEAP LOCK in CAS_FSM              = " << (double) m_cpt_cas_fsm_heap_lock/m_cpt_cas_fsm_n_heap_lock << std::endl
+      << "- NB CYCLES IN HEAP LOCK in CAS_FSM      = " << (double) m_cpt_cas_fsm_heap_used/m_cpt_cas_fsm_n_heap_lock << std::endl
+      << "- HEAP UNUSED RATE                       = " << (double) m_cpt_heap_unused/m_cpt_cycles << std::endl
+
+      << "- READ DATA UNC                          = " << (double) m_cpt_read_data_unc << std::endl
+      << "- READ DATA MISS CC                      = " << (double) m_cpt_read_data_miss_CC << std::endl
+      << "- READ INS UNC                           = " << (double) m_cpt_read_ins_unc << std::endl
+      << "- READ INS MISS                          = " << (double) m_cpt_read_ins_miss << std::endl
+      << "- READ LL CC                             = " << (double) m_cpt_read_ll_CC << std::endl
+      << "- READ DATA MISS NCC                     = " << (double) m_cpt_read_data_miss_NCC << std::endl
+      << "- READ LL NCC                            = " << (double) m_cpt_read_ll_NCC << std::endl
+      << "- READ OTHER                             = " << (double) m_cpt_read_WTF << std::endl
+      << "- CLEANUP + DATA                         = " << (double) m_cpt_cleanup_data << std::endl
+      << "- NCC TO CC READ                         = " << (double) m_cpt_ncc_to_cc_read << std::endl
+      << "- NCC TO CC WRITE                        = " << (double) m_cpt_ncc_to_cc_write << std::endl
+      << "- NCC TO CC                              = " << (double) m_cpt_ncc_to_cc << std::endl;
 }
 
@@ -685,4 +844,9 @@
   delete [] r_write_be;
   delete [] r_write_to_cc_send_data;
+
+  delete [] r_cleanup_data;
+  delete [] r_cleanup_to_ixr_cmd_data;
+  delete [] r_cleanup_to_tgt_rsp_data;
+  delete [] r_cleanup_old_data;
 }
 
@@ -763,4 +927,6 @@
     r_read_to_tgt_rsp_req = false;
     r_read_to_ixr_cmd_req = false;
+    r_read_to_cc_send_req = false;
+    r_read_to_cleanup_req = false;
 
     r_write_to_tgt_rsp_req          = false;
@@ -820,24 +986,90 @@
     r_tgt_rsp_key_sent  = false;
 
+    // ODCCP
+    r_cleanup_data_index       = 0;
+    r_cleanup_trdid            = 0;
+    r_cleanup_pktid            = 0;
+    r_cleanup_contains_data    = false;
+    r_cleanup_ncc              = false;
+    r_cleanup_to_ixr_cmd_ncc_l1_dirty    = false;
+    r_xram_rsp_to_ixr_cmd_inval_ncc_pending    = false;
+    r_cleanup_to_ixr_cmd_req   = false;
+    r_cleanup_to_ixr_cmd_srcid = 0;
+    r_cleanup_to_ixr_cmd_trdid = 0;
+    r_cleanup_to_ixr_cmd_pktid = 0;
+    r_cleanup_to_ixr_cmd_nline = 0;
+    for (size_t word = 0; word < m_words; word ++)
+    {
+      r_cleanup_to_ixr_cmd_data[word] = 0;
+      r_cleanup_data[word] = 0;
+    }
+
+
     // Activity counters
-    m_cpt_cycles        = 0;
-    m_cpt_read          = 0;
-    m_cpt_read_miss     = 0;
-    m_cpt_write         = 0;
-    m_cpt_write_miss    = 0;
-    m_cpt_write_cells   = 0;
-    m_cpt_write_dirty   = 0;
-    m_cpt_update        = 0;
-    m_cpt_update_mult   = 0;
-    m_cpt_inval_brdcast = 0;
-    m_cpt_inval         = 0;
-    m_cpt_inval_mult    = 0;
-    m_cpt_cleanup       = 0;
-    m_cpt_ll            = 0;
-    m_cpt_sc            = 0;
-    m_cpt_cas           = 0;
-    m_cpt_trt_full      = 0;
-    m_cpt_trt_rb        = 0;
-
+    m_cpt_cycles                  = 0;
+    m_cpt_read                    = 0;
+    m_cpt_read_miss               = 0;
+    m_cpt_write                   = 0;
+    m_cpt_write_miss              = 0;
+    m_cpt_write_cells             = 0;
+    m_cpt_write_dirty             = 0;
+    m_cpt_update                  = 0;
+    m_cpt_update_mult             = 0;
+    m_cpt_inval_brdcast           = 0;
+    m_cpt_inval                   = 0;
+    m_cpt_inval_mult              = 0;
+    m_cpt_cleanup                 = 0;
+    m_cpt_ll                      = 0;
+    m_cpt_sc                      = 0;
+    m_cpt_cas                     = 0;
+    m_cpt_trt_full                = 0;
+    m_cpt_trt_rb                  = 0;
+    m_cpt_dir_unused              = 0;
+    m_cpt_upt_unused              = 0;
+    m_cpt_ivt_unused              = 0;
+    m_cpt_heap_unused             = 0;
+    m_cpt_trt_unused              = 0;
+    m_cpt_read_fsm_n_dir_lock     = 0;
+    m_cpt_read_fsm_dir_lock       = 0;
+    m_cpt_read_fsm_dir_used       = 0;
+    m_cpt_read_fsm_trt_lock       = 0;
+    m_cpt_read_fsm_heap_lock      = 0;
+    m_cpt_write_fsm_dir_lock      = 0;
+    m_cpt_write_fsm_n_dir_lock    = 0;
+    m_cpt_write_fsm_upt_lock      = 0;
+    m_cpt_write_fsm_heap_lock     = 0;
+    m_cpt_write_fsm_dir_used      = 0;
+    m_cpt_write_fsm_trt_lock      = 0;
+    m_cpt_cas_fsm_n_dir_lock      = 0;
+    m_cpt_cas_fsm_dir_lock        = 0;
+    m_cpt_cas_fsm_upt_lock        = 0;
+    m_cpt_cas_fsm_heap_lock       = 0;
+    m_cpt_cas_fsm_trt_lock        = 0;
+    m_cpt_cas_fsm_dir_used        = 0;
+    m_cpt_xram_rsp_fsm_n_dir_lock = 0;
+    m_cpt_xram_rsp_fsm_dir_lock   = 0;
+    m_cpt_xram_rsp_fsm_trt_lock   = 0;
+    m_cpt_xram_rsp_fsm_upt_lock   = 0;
+    m_cpt_xram_rsp_fsm_heap_lock  = 0;
+    m_cpt_xram_rsp_fsm_dir_used   = 0;
+    m_cpt_cleanup_fsm_dir_lock    = 0;
+    m_cpt_cleanup_fsm_n_dir_lock  = 0;
+    m_cpt_cleanup_fsm_heap_lock   = 0;
+    m_cpt_cleanup_fsm_ivt_lock    = 0;
+    m_cpt_cleanup_fsm_dir_used    = 0;
+    m_cpt_ixr_fsm_trt_lock        = 0;
+    m_cpt_multi_ack_fsm_upt_lock  = 0;
+    m_cpt_read_data_unc           = 0;   
+    m_cpt_read_data_miss_CC       = 0;   
+    m_cpt_read_ins_unc            = 0;        
+    m_cpt_read_ins_miss           = 0;      
+    m_cpt_read_ll_CC              = 0;       
+    m_cpt_read_data_miss_NCC      = 0;        
+    m_cpt_read_ll_NCC             = 0;    
+    m_cpt_read_WTF                = 0;   
+    m_cpt_cleanup_data            = 0;      
+    m_cpt_ncc_to_cc_read          = 0;      
+    m_cpt_ncc_to_cc_write         = 0;       
+    m_cpt_ncc_to_cc               = 0;        
     return;
   }
@@ -946,4 +1178,5 @@
     if(p_vci_tgt.cmdval)
     {
+
 
 #if DEBUG_MEMC_TGT_CMD
@@ -1106,5 +1339,5 @@
             error            = 0;
             r_config_address = (r_config_address.read() & 0x00000000FFFFFFFFLL) |
-                               ((addr_t)p_vci_tgt.wdata.read())<<32;
+                               ((uint64_t)p_vci_tgt.wdata.read())<<32;
         }
         else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set buf_lines
@@ -1331,10 +1564,13 @@
     case MULTI_ACK_UPT_LOCK:
     {
+        m_cpt_multi_ack_fsm_upt_lock++;
         // get lock to the UPDATE table
-        if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) break;
+        if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK)  break;
 
         // decrement the number of expected responses
         size_t count = 0;
         bool valid   = m_upt.decrement(r_multi_ack_upt_index.read(), count);
+
+       /*ODCCP*/ //m_upt.print();
 
         if(not valid)
@@ -1361,4 +1597,5 @@
           << " entry = "       << r_multi_ack_upt_index.read()
           << " / rsp_count = " << std::dec << count << std::endl;
+        m_cpt_multi_ack_fsm_n_upt_lock++;
 #endif
         break;
@@ -1875,4 +2112,6 @@
             << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
 #endif
+        r_read_coherent = false; //WB by default
+        r_read_ll_done  = false;
         r_read_fsm = READ_DIR_REQ;
       }
@@ -1886,4 +2125,5 @@
       {
         r_read_fsm = READ_DIR_LOCK;
+        m_cpt_read_fsm_n_dir_lock++;
       }
 
@@ -1892,4 +2132,7 @@
 std::cout << "  <MEMC " << name() << " READ_DIR_REQ> Requesting DIR lock " << std::endl;
 #endif
+
+      m_cpt_read_fsm_dir_lock++;
+
       break;
     }
@@ -1903,8 +2146,13 @@
         DirectoryEntry entry =
           m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
-        // access the global table ONLY when we have an LL cmd
-        if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)   
-        {
-          r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
+        if(((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL) and not r_read_ll_done.read())   // access the global table ONLY when we have an LL cmd
+        {
+          addr_t      nline      = m_nline[(addr_t)(m_cmd_read_addr_fifo.read())];
+          r_read_ll_key   = m_llsc_table.ll(nline);
+          //r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
+          /**//*std::cout << "MEMCACHE : from proc " << m_cmd_read_srcid_fifo.read()
+                        << " | @ " << std::hex << m_cmd_read_addr_fifo.read()
+                        << " | LL" << std::endl;*/
+          r_read_ll_done  = true;
         }
         r_read_is_cnt     = entry.is_cnt;
@@ -1926,14 +2174,26 @@
         // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
         bool cached_read = (m_cmd_read_pktid_fifo.read() & 0x1);
+
+
         if(entry.valid)    // hit
         {
-          // test if we need to register a new copy in the heap
-          if(entry.is_cnt or (entry.count == 0) or !cached_read)
+          r_read_coherent = entry.cache_coherent;
+          if (entry.cache_coherent or (entry.count == 0))// or (entry.owner.srcid == m_cmd_read_srcid_fifo.read())) //hit on a WT line or the owner has no more copy (if LL, the owner must be invalidated even if he made the request)
           {
-            r_read_fsm = READ_DIR_HIT;
+            // test if we need to register a new copy in the heap
+            if(entry.is_cnt || (entry.count == 0) || !cached_read)
+            {
+              r_read_fsm = READ_DIR_HIT;
+            }
+            else
+            {
+              //std::cout << "is LL = " << ((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL) << std::endl;
+              //std::cout << "coherent = " << entry.cache_coherent << " | count = " << std::dec << entry.count << " | cached = " << cached_read << std::endl;
+              r_read_fsm = READ_HEAP_REQ;
+            }
           }
-          else
+          else //hit on a WB line owned by an other proc
           {
-            r_read_fsm = READ_HEAP_REQ;
+            r_read_fsm = READ_IVT_LOCK;
           }
         }
@@ -1950,5 +2210,6 @@
           << " / hit = " << std::dec << entry.valid
           << " / count = " <<std::dec << entry.count
-          << " / is_cnt = " << entry.is_cnt;
+          << " / is_cnt = " << entry.is_cnt
+          << " / is_coherent = " << entry.cache_coherent;
 if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL) std::cout << " / LL access" << std::endl;
 else                                                std::cout << std::endl;
@@ -1965,5 +2226,89 @@
     }
 
+    ///////////////////
+    case READ_IVT_LOCK:
+    {
+      if (r_alloc_ivt_fsm.read() == ALLOC_IVT_READ)
+      {
+        size_t index;
+        addr_t nline = m_nline[(addr_t)(m_cmd_read_addr_fifo.read())];
+        /*std::cout << "nline = " << std::dec <<  nline << std::endl
+                  << "inval en cours sur la ligne = " << m_upt.search_inval(nline, index) << std::endl
+                  << "UPT full = " << m_upt.is_full() << std::endl
+                  << "CC_SEND req = " << r_read_to_cc_send_req.read() << std::endl
+                  << "CLENAUP req = " <<r_read_to_cleanup_req.read() << std::endl;*/
+        if(m_upt.search_inval(nline, index) or m_upt.is_full() or r_read_to_cc_send_req.read() or r_read_to_cleanup_req.read()) //Check pending inval
+        {
+          r_read_fsm = READ_WAIT;
+#if DEBUG_MEMC_READ
+        if(m_debug)
+        {
+          std::cout
+              << "  <MEMC " << name() << " READ_IVT_LOCK>" 
+              << " Wait cleanup completion"
+              << std::endl;
+        }
+#endif
+        }
+        else
+        {
+          r_read_to_cc_send_req = true;
+          r_read_to_cc_send_dest = r_read_copy.read();
+          r_read_to_cc_send_nline = nline;
+          r_read_to_cc_send_inst = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0); 
+          r_read_to_cleanup_req = true;
+          r_read_to_cleanup_nline = nline;
+          r_read_to_cleanup_srcid = m_cmd_read_srcid_fifo.read();
+          r_read_to_cleanup_length  = m_cmd_read_length_fifo.read();
+          r_read_to_cleanup_first_word = m_x[(addr_t) m_cmd_read_addr_fifo.read()];
+          r_read_to_cleanup_cached_read = (m_cmd_read_pktid_fifo.read() & 0x1);
+          r_read_to_cleanup_addr = m_cmd_read_addr_fifo.read();
+          r_read_to_cleanup_is_ll= ((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL);
+          r_read_to_cleanup_ll_key = r_read_ll_key.read();
+          //std::cout << "cleanup req (read) on line " << nline << " /on proc " << r_read_copy.read() << std::endl;
+
+          m_upt.set(false,  // it's an inval transaction
+                          false,     // it's not a broadcast
+                          false,     // it needs a read response
+                          false,     // no acknowledge required
+                          m_cmd_read_srcid_fifo.read(),
+                          m_cmd_read_trdid_fifo.read(),
+                          m_cmd_read_pktid_fifo.read(),
+                          nline,
+                          0x1, //Expect only one answer
+                          index);
+
+          cmd_read_fifo_get = true;
+          r_read_fsm = READ_IDLE;
+#if DEBUG_MEMC_READ
+        if(m_debug)
+        {
+          std::cout
+              << "  <MEMC " << name() << " READ_IVT_LOCK>" 
+              << " Inval req on an NCC line"
+              << std::endl;
+        }
+#endif
+        }
+      }
+
+
+      break;
+    }
+
     //////////////////
+        case READ_WAIT://Release the locks
+        {
+            r_read_fsm = READ_DIR_REQ;
+#if DEBUG_MEMC_READ
+        if(m_debug)
+        {
+          std::cout
+              << "  <MEMC " << name() << " READ_WAIT>" << std::endl;
+        }
+#endif
+        break;
+        }
+    ///////////////////                      
     case READ_DIR_HIT:    //  read data in cache & update the directory
                           //  we enter this state in 3 cases:
@@ -1996,4 +2341,6 @@
         DirectoryEntry entry;
         entry.valid   = true;
+        entry.cache_coherent = r_read_coherent.read() or inst_read or (!(cached_read)) or (r_read_copy.read() != m_cmd_read_srcid_fifo.read());
+        r_read_coherent = r_read_coherent.read() or inst_read or (!(cached_read)) or (r_read_copy.read() != m_cmd_read_srcid_fifo.read());
         entry.is_cnt  = is_cnt;
         entry.dirty   = r_read_dirty.read();
@@ -2001,5 +2348,4 @@
         entry.lock    = r_read_lock.read();
         entry.ptr     = r_read_ptr.read();
-
         if(cached_read)   // Cached read => we must update the copies
         {
@@ -2034,13 +2380,14 @@
 
 #if DEBUG_MEMC_READ
-        if(m_debug)
-          std::cout << "  <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 = " << std::hex << entry.owner.srcid
-            << " / owner_ins = " << std::dec << entry.owner.inst
-            << " / count = " << entry.count
-            << " / is_cnt = " << entry.is_cnt << std::endl;
+if(m_debug)
+std::cout << "  <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 = " << std::hex << entry.owner.srcid
+          << " / owner_ins = " << std::dec << entry.owner.inst
+          << " / coherent = " << entry.cache_coherent
+          << " / count = " << entry.count
+          << " / is_cnt = " << entry.is_cnt << std::endl;
 #endif
 
@@ -2056,4 +2403,5 @@
       {
         r_read_fsm = READ_HEAP_LOCK;
+        m_cpt_read_fsm_n_heap_lock++;
       }
 
@@ -2063,4 +2411,7 @@
           << " Requesting HEAP lock " << std::endl;
 #endif
+
+      m_cpt_read_fsm_heap_lock++;
+
       break;
     }
@@ -2075,4 +2426,9 @@
         bool go_cnt = (r_read_count.read() >= m_max_copies) or m_heap.is_full();
 
+        if (!r_read_coherent.read())
+        {
+          std::cout << "Address = " << std::hex << (m_cmd_read_addr_fifo.read()) << std::dec << " |count = " << r_read_count.read() << std::endl;
+        }
+        assert (r_read_coherent.read() && "accÃšs au heap sur ncc");
         // read data in the cache
         size_t set = m_y[(addr_t)(m_cmd_read_addr_fifo.read())];
@@ -2086,4 +2442,5 @@
         DirectoryEntry entry;
         entry.valid  = true;
+        entry.cache_coherent = r_read_coherent.read();
         entry.is_cnt = go_cnt;
         entry.dirty  = r_read_dirty.read();
@@ -2272,6 +2629,16 @@
         r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
         r_read_to_tgt_rsp_srcid  = m_cmd_read_srcid_fifo.read();
+        /*RWT*/
+        //BUG pktid
+        if (r_read_coherent.read())
+        {
+          r_read_to_tgt_rsp_pktid = 0x0 + m_cmd_read_pktid_fifo.read();
+          //std::cout << "READ RSP COHERENT on word" << std::hex << m_x[(addr_t) m_cmd_read_addr_fifo.read()] << std::dec << std::endl;
+        }
+        else
+        {
+          r_read_to_tgt_rsp_pktid = 0x8 + m_cmd_read_pktid_fifo.read();
+        }
         r_read_to_tgt_rsp_trdid  = m_cmd_read_trdid_fifo.read();
-        r_read_to_tgt_rsp_pktid  = m_cmd_read_pktid_fifo.read();
         r_read_to_tgt_rsp_ll_key = r_read_ll_key.read();
         cmd_read_fifo_get        = true;
@@ -2302,5 +2669,8 @@
         if(hit_read or !wok or hit_write)    // missing line already requested or no space
         {
-          if(!wok)      m_cpt_trt_full++;
+          if(!wok)
+          {
+            m_cpt_trt_full++;
+          }
           if(hit_read or hit_write)   m_cpt_trt_rb++;
           r_read_fsm = READ_IDLE;
@@ -2319,6 +2689,10 @@
           << " / hit_write = " << hit_write
           << " / full = " << !wok << std::endl;
-#endif
-      }
+        m_cpt_read_fsm_n_trt_lock++;
+#endif
+      }
+
+      m_cpt_read_fsm_trt_lock++;
+
       break;
     }
@@ -2341,4 +2715,5 @@
                               std::vector<data_t> (m_words,0),
                               r_read_ll_key.read());
+        
 #if DEBUG_MEMC_READ
 if(m_debug)
@@ -2507,5 +2882,5 @@
       {
         ///////////////////////////////////////////////////////////////////////
-        // SC command treatment
+        // SC command handling
         // We test the r_write_pending_sc register to know if we are returning
         // from the WAIT state.
@@ -2513,28 +2888,33 @@
         // another time from the FIFO. Also, we don't have to test another
         // time if the SC has succeed
+
+        addr_t nline = m_nline[(addr_t)(r_write_address.read())];
         if(((r_write_pktid.read() & 0x7) == TYPE_SC) and not r_write_pending_sc.read())
         {
           if(not m_cmd_write_addr_fifo.rok()) break;
-
+  
           assert(m_cmd_write_eop_fifo.read() and
                  "Error in VCI_MEM_CACHE : "
                  "invalid packet format for SC command");
-
+          //BUG LLSC
           size_t index    = r_write_word_index.read();
-          bool sc_success = m_llsc_table.sc(r_write_address.read()    ,
+          bool sc_success = m_llsc_table.sc(nline    ,
                                             r_write_data[index].read());
-
+  
+          //bool sc_success = m_llsc_table.sc(r_write_address.read()    ,
+          //                                  r_write_data[index].read());
           // consume a word in the FIFO & write it in the local buffer
           cmd_write_fifo_get  = true;
           r_write_data[index] = m_cmd_write_data_fifo.read();
           r_write_sc_fail     = not sc_success;
+          //WARNING: if the SC is a success, it might still fail at next cycle if the line is NCC
           r_write_pending_sc  = true;
-
+  
           if(not sc_success) r_write_fsm = WRITE_RSP;
           else               r_write_fsm = WRITE_DIR_LOCK;
-
+  
           break;
         }
-
+  
         ///////////////////////////////////////////////////////////////////////
         // WRITE command treatment or SC command returning from the WAIT state
@@ -2542,7 +2922,10 @@
         // erase any possible new reservation when we release the lock on the
         // directory
-        m_llsc_table.sw(r_write_address.read());
+        m_llsc_table.sw(nline);
+
+        //m_llsc_table.sw(r_write_address.read());
 
         r_write_fsm = WRITE_DIR_LOCK;
+        m_cpt_write_fsm_n_dir_lock++;
       }
 
@@ -2552,4 +2935,6 @@
           << std::endl;
 #endif
+
+      m_cpt_write_fsm_dir_lock++;
 
       break;
@@ -2578,17 +2963,37 @@
           r_write_ptr        = entry.ptr;
           r_write_way        = way;
-
-          if(entry.is_cnt and entry.count)
+          
+          r_write_coherent   = entry.cache_coherent;
+
+          if (entry.cache_coherent or (entry.owner.srcid == r_write_srcid.read()) or (entry.count == 0)) // hit WT
           {
-            r_write_fsm = WRITE_DIR_READ;
+            if(entry.is_cnt && entry.count)
+            {
+              r_write_fsm = WRITE_DIR_READ;
+            }
+            else
+            {
+             r_write_fsm = WRITE_DIR_HIT;
+            }
           }
           else
           {
-            r_write_fsm = WRITE_DIR_HIT;
+            if (r_write_to_cleanup_req.read())//inval already sent
+            {
+              r_write_fsm = WRITE_WAIT;
+            }
+            else // hit on a NCC line with a different owner
+            {
+              r_write_fsm = WRITE_IVT_LOCK_HIT_WB;
+              if(r_write_pktid.read() == TYPE_SC)
+              {
+                r_write_sc_fail = true;
+              }
+            }
           }
         }
         else  // miss
         {
-          r_write_fsm = WRITE_MISS_TRT_LOCK;
+          r_write_fsm = WRITE_MISS_IVT_LOCK;
         }
 
@@ -2619,4 +3024,58 @@
     }
     ////////////////////
+    case WRITE_IVT_LOCK_HIT_WB:
+    {
+      if(r_alloc_ivt_fsm.read() == ALLOC_IVT_WRITE)
+      {
+
+        size_t index = 0;
+        bool   match_inval;
+        addr_t nline = m_nline[(addr_t)(r_write_address.read())];
+
+        //std::cout << "WRITE on NCC on line" << std::hex << nline << std::dec << std::endl;
+
+        match_inval = m_upt.search_inval(nline, index);
+        assert ((r_write_count.read() == 1) and "NCC to CC req without copy");
+        if(!match_inval and !r_write_to_cc_send_req.read())
+        {
+          r_write_to_cc_send_req = true;
+          r_write_to_cc_send_dest = r_write_copy;
+          r_write_to_cc_send_nline = nline;
+          r_write_to_cleanup_req = true;
+          r_write_to_cleanup_nline = nline;
+
+          m_upt.set(false,  // it's an inval transaction
+                          false,     // it's not a broadcast
+                          true,      // it needs no read response
+                          false,     // no acknowledge required
+                          m_cmd_write_srcid_fifo.read(), //never read, used for debug
+                          m_cmd_write_trdid_fifo.read(), //never read, used for debug
+                          m_cmd_write_pktid_fifo.read(), //never read, used for debug
+                          nline,
+                          0x1, //Expect only one answer
+                          index);
+        }
+        r_write_fsm = WRITE_WAIT;
+#if DEBUG_MEMC_WRITE
+        if(m_debug)
+        {
+          std::cout << "  <MEMC " << name() << " WRITE_IVT_LOCK_HIT_WB> get access to the UPT: "
+                    << " Inval requested =  " << (!match_inval and !r_write_to_cc_send_req.read())
+                    << std::endl;
+        }
+#endif
+      }
+#if DEBUG_MEMC_WRITE
+        if(m_debug)
+        {
+          std::cout << "  <MEMC " << name() << " WRITE_IVT_LOCK_HIT_WB> failed to access to the UPT: "
+                    << std::endl;
+        }
+#endif
+      break;
+    }
+
+
+    ////////////////////
     case WRITE_DIR_READ:  // read the cache and complete the buffer when be!=0xF
     {
@@ -2656,4 +3115,5 @@
       DirectoryEntry entry;
       entry.valid          = true;
+      entry.cache_coherent = r_write_coherent.read();
       entry.dirty          = true;
       entry.tag            = r_write_tag.read();
@@ -2683,10 +3143,10 @@
       // no_update is true when there is no need for coherence transaction
       // (tests for sc requests)
-      bool no_update = ( (r_write_count.read() == 0) or
-                         (owner and (r_write_count.read() ==1) and 
-                         (r_write_pktid.read() != TYPE_SC)));
+      bool no_update = ((r_write_count.read() ==0) || //no need for coherency
+                        (owner && (r_write_count.read() ==1) && (r_write_pktid.read() != TYPE_SC)) || //writer is owner
+                        ((r_write_pktid.read() == TYPE_SC) && r_write_sc_fail.read())); //SC failed: no data update
 
       // write data in the cache if no coherence transaction
-      if(no_update)
+      if(no_update and ((r_write_pktid.read() != TYPE_SC) or !r_write_sc_fail.read()))
       {
         for(size_t word=0 ; word<m_words ; word++)
@@ -2760,4 +3220,5 @@
         size_t      set        = m_y[(addr_t)(r_write_address.read())];
         size_t      way        = r_write_way.read();
+
 
         wok = m_upt.set(true,  // it's an update transaction
@@ -2804,5 +3265,9 @@
         if(wok) r_write_fsm = WRITE_UPT_HEAP_LOCK;
         else    r_write_fsm = WRITE_WAIT;
-      }
+        m_cpt_write_fsm_n_upt_lock++;
+      }
+
+      m_cpt_write_fsm_upt_lock++;
+
       break;
     }
@@ -2820,5 +3285,9 @@
 #endif
         r_write_fsm = WRITE_UPT_REQ;
-      }
+        m_cpt_write_fsm_n_heap_lock++;
+      }
+
+      m_cpt_write_fsm_heap_lock++;
+
       break;
     }
@@ -2834,4 +3303,5 @@
              "transaction in WRITE_UPT_REQ state"
             );
+
 
       r_write_to_cc_send_brdcast_req  = false;
@@ -3070,4 +3540,21 @@
       break;
     }
+    ///////////////////////// RWT
+    case WRITE_MISS_IVT_LOCK: // Miss : check UPT 
+    {
+      if (r_alloc_ivt_fsm.read() == ALLOC_IVT_WRITE)
+      {
+        size_t index;
+        if(m_upt.search_inval(m_nline[(addr_t)(r_write_address.read())], index))
+        {
+          r_write_fsm = WRITE_WAIT;
+        }
+        else
+        {
+          r_write_fsm = WRITE_MISS_TRT_LOCK;
+        }
+      }
+      break;
+    }
 
     /////////////////////////
@@ -3087,5 +3574,5 @@
         bool    hit_write = m_trt.hit_write(m_nline[addr]);
         bool    wok       = !m_trt.full(wok_index);
-
+        //std::cout << "MEMCACHE : WRITE MISS at " << std::hex << (uint32_t)addr << std::dec << std::endl;
         if(hit_read)      // register the modified data in TRT
         {
@@ -3105,5 +3592,9 @@
           m_cpt_trt_full++;
         }
-      }
+        m_cpt_write_fsm_n_trt_lock++;
+      }
+
+      m_cpt_write_fsm_trt_lock++;
+
       break;
     }
@@ -3224,5 +3715,9 @@
           << " : wok = " << wok << " / index = " << wok_index << std::endl;
 #endif
-      }
+        m_cpt_write_fsm_n_trt_lock++;
+      }
+
+      m_cpt_write_fsm_trt_lock++;
+
       break;
     }
@@ -3251,5 +3746,5 @@
                         nb_copies,
                         index);
-
+       /*ODCCP*/ //m_upt.print();
 #if DEBUG_MEMC_WRITE
 if( m_debug and wok )
@@ -3261,5 +3756,9 @@
         if(wok) r_write_fsm = WRITE_BC_DIR_INVAL;
         else    r_write_fsm = WRITE_WAIT;
-      }
+        m_cpt_write_fsm_n_upt_lock++;
+      }
+
+      m_cpt_write_fsm_upt_lock++;
+
       break;
     }
@@ -3295,4 +3794,5 @@
       DirectoryEntry entry;
       entry.valid         = false;
+      entry.cache_coherent= false;
       entry.dirty         = false;
       entry.tag         = 0;
@@ -3394,38 +3894,43 @@
     ////////////////////////
     case IXR_CMD_READ_IDLE:
-    {
       if     (r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
       else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
       else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
+      else if(r_cleanup_to_ixr_cmd_req)  r_ixr_cmd_fsm = IXR_CMD_CLEANUP_DATA;
       else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
       break;
-    }
     ////////////////////////
     case IXR_CMD_WRITE_IDLE:
-    {
-      if     (r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
+      if(r_cas_to_ixr_cmd_req)           r_ixr_cmd_fsm = IXR_CMD_CAS;
       else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
+      else if(r_cleanup_to_ixr_cmd_req)  r_ixr_cmd_fsm = IXR_CMD_CLEANUP_DATA;
       else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
       else if(r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
       break;
-    }
     ////////////////////////
     case IXR_CMD_CAS_IDLE:
-    {
-      if     (r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
+      if(r_xram_rsp_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_XRAM;
+      else if(r_cleanup_to_ixr_cmd_req)  r_ixr_cmd_fsm = IXR_CMD_CLEANUP_DATA;
       else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
       else if(r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
       else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
       break;
-    }
     ////////////////////////
     case IXR_CMD_XRAM_IDLE:
-    {
-      if     (r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
-      else if(r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
+      if(r_cleanup_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_CLEANUP_DATA;
+      else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
+      else if(r_write_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_WRITE;
       else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
       else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
       break;
-    }
+      ////////////////////////
+    case IXR_CMD_CLEANUP_IDLE:
+      /*ODCCP*///std::cout << "IXR_CMD_CLEANUP_IDLE" << std::endl;
+      if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
+      else if(r_write_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_WRITE;
+      else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
+      else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
+      else if(r_cleanup_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_CLEANUP_DATA;
+      break;      
     //////////////////       // send a get from READ FSM
     case IXR_CMD_READ:
@@ -3553,4 +4058,30 @@
       break;
     }
+
+      ////////////////////////
+    case IXR_CMD_CLEANUP_DATA:     // send a put command to XRAM
+      /*ODCCP*///std::cout << "IXR_CMD_CLEANUP_DATA" << std::endl;
+      if(p_vci_ixr.cmdack)
+      {
+        if(r_ixr_cmd_cpt.read() == (m_words - 2))
+        {
+          r_ixr_cmd_cpt = 0;
+          r_ixr_cmd_fsm = IXR_CMD_CLEANUP_IDLE;
+          r_xram_rsp_to_ixr_cmd_inval_ncc_pending = false;
+          r_cleanup_to_ixr_cmd_req = false;
+        }
+        else
+        {
+          r_ixr_cmd_cpt = r_ixr_cmd_cpt.read() + 2;
+        }
+
+#if DEBUG_MEMC_IXR_CMD
+        if(m_debug)
+        {
+          std::cout << "  <MEMC " << name() << ".IXR_CMD_CLEANUP_DATA> Send a put request to xram" << std::endl;
+        }
+#endif
+      }
+      break;
 
   } // end switch r_ixr_cmd_fsm
@@ -3631,5 +4162,9 @@
           << r_ixr_rsp_trt_index.read() << std::endl;
 #endif
-      }
+      m_cpt_ixr_fsm_n_trt_lock++;
+      }
+
+      m_cpt_ixr_fsm_trt_lock++;
+
       break;
     }
@@ -3667,5 +4202,7 @@
           << " / data = " << std::hex << data << std::endl;
 #endif
-      }
+      m_cpt_ixr_fsm_n_trt_lock++;
+      }
+      m_cpt_ixr_fsm_trt_lock++;
       break;
     }
@@ -3740,5 +4277,9 @@
           << " Get access to DIR and TRT" << std::endl;
 #endif
-      }
+        m_cpt_xram_rsp_fsm_n_dir_lock++;
+        m_cpt_xram_rsp_fsm_n_trt_lock++;
+      }
+      m_cpt_xram_rsp_fsm_dir_lock++;
+      m_cpt_xram_rsp_fsm_trt_lock++;
       break;
     }
@@ -3756,5 +4297,6 @@
         DirectoryEntry victim(m_cache_directory.select(set, way));
 
-        bool inval = (victim.count and victim.valid) ;
+        bool inval = (victim.count && victim.valid) or (!victim.cache_coherent and (victim.count == 1)) ;
+
 
         // copy the victim line in a local buffer
@@ -3766,4 +4308,5 @@
         r_xram_rsp_victim_copy_cache= victim.owner.cache_id;
 #endif
+        r_xram_rsp_victim_coherent  = victim.cache_coherent;
         r_xram_rsp_victim_copy_inst = victim.owner.inst;
         r_xram_rsp_victim_count     = victim.count;
@@ -3774,9 +4317,17 @@
         r_xram_rsp_victim_is_cnt    = victim.is_cnt;
         r_xram_rsp_victim_inval     = inval ;
-        r_xram_rsp_victim_dirty     = victim.dirty;
+        r_xram_rsp_victim_dirty     = victim.dirty or (!victim.cache_coherent && (victim.count == 1)); //a NCC line is by default considered as dirty in the L1: we must take a reservation on a TRT entry
+
 
         if(!r_xram_rsp_trt_buf.rerror)
         {
-          r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
+          if (!victim.cache_coherent and r_xram_rsp_to_ixr_cmd_inval_ncc_pending.read()) //there can not be two L2 invalidation on NCC line at the same time
+          {
+            r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+          }
+          else
+          {
+            r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
+          }
         }
         else
@@ -3808,5 +4359,7 @@
       {
         size_t index = 0;
-        if(m_ivt.search_inval(r_xram_rsp_trt_buf.nline, index))  // pending inval
+        size_t index_victim = 0;
+        if(m_ivt.search_inval(r_xram_rsp_trt_buf.nline, index) or
+           m_ivt.search_inval(r_xram_rsp_victim_nline.read(), index_victim))
         {
           r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
@@ -3824,4 +4377,5 @@
         {
           r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+          m_upt.print();
 
 #if DEBUG_MEMC_XRAM_RSP
@@ -3841,5 +4395,9 @@
 #endif
         }
-      }
+        m_cpt_xram_rsp_fsm_n_upt_lock++;
+      }
+
+      m_cpt_xram_rsp_fsm_upt_lock++;
+
       break;
     }
@@ -3891,4 +4449,5 @@
       DirectoryEntry entry;
       entry.valid   = true;
+      entry.cache_coherent = (inst_read or (not(cached_read))) and (r_xram_rsp_trt_buf.proc_read);
       entry.is_cnt  = false;
       entry.lock    = false;
@@ -3907,5 +4466,5 @@
       else
       {
-        entry.owner.srcid    = 0;
+        entry.owner.srcid    = r_xram_rsp_trt_buf.srcid;
 #if L1_MULTI_CACHE
         entry.owner.cache_id = 0;
@@ -3915,5 +4474,6 @@
       }
       m_cache_directory.write(set, way, entry);
-
+      //RWT: keep the coherence information in order to send it to the read_rsp
+      r_xram_rsp_coherent = inst_read or (not(cached_read));
       // request an invalidattion request in IVT for victim line
       if(r_xram_rsp_victim_inval.read())
@@ -3922,5 +4482,5 @@
         size_t index        = 0;
         size_t count_copies = r_xram_rsp_victim_count.read();
-
+  
         bool   wok = m_ivt.set(false,      // it's an inval transaction
                                broadcast,  // set broadcast bit
@@ -3935,5 +4495,4 @@
 
         r_xram_rsp_ivt_index = index;
-
         if(!wok)
         {
@@ -3943,5 +4502,9 @@
         }
       }
-
+      if (!r_xram_rsp_victim_coherent.read())
+      {
+        //m_llsc_table.sw(r_xram_rsp_victim_nline.read()*m_words*4);
+        m_llsc_table.sw(r_xram_rsp_victim_nline.read());
+      }
 #if DEBUG_MEMC_XRAM_RSP
 if(m_debug)
@@ -3962,10 +4525,10 @@
 #endif
 
-      // If the victim is not dirty, we don't need another XRAM put transaction,
+      // If the victim is not dirty (RWT: if it is not coherent, we can not know wether it is dirty or not), we don't need another XRAM  put transaction,
       // and we can erase the TRT entry
-      if(!r_xram_rsp_victim_dirty.read())  m_trt.erase(r_xram_rsp_trt_index.read());
+      if(!r_xram_rsp_victim_dirty.read() and (r_xram_rsp_victim_coherent.read() or (r_xram_rsp_victim_count.read() == 0)))  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;
+      if(r_xram_rsp_victim_dirty.read() or (!r_xram_rsp_victim_coherent.read() and (r_xram_rsp_victim_count.read() == 1)))       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;
@@ -3974,8 +4537,9 @@
     }
     ////////////////////////
-    case XRAM_RSP_TRT_DIRTY:  // set the TRT entry (PUT to XRAM) if the victim is dirty
+    case XRAM_RSP_TRT_DIRTY:  // set the TRT entry (write to XRAM) if the victim is dirty or not coherent (RWT)
     {
       if(r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP)
       {
+
         m_trt.set(r_xram_rsp_trt_index.read(),
                               false,       // write to XRAM
@@ -3999,5 +4563,9 @@
         else if(r_xram_rsp_victim_inval.read())  r_xram_rsp_fsm = XRAM_RSP_INVAL;
         else                                     r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
-      }
+        m_cpt_xram_rsp_fsm_n_trt_lock++;
+      }
+
+      m_cpt_xram_rsp_fsm_trt_lock++;
+
       break;
     }
@@ -4009,5 +4577,12 @@
         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;
+        if (r_xram_rsp_coherent.read())
+        {
+          r_xram_rsp_to_tgt_rsp_pktid = 0x0 + r_xram_rsp_trt_buf.pktid;//RWT CC
+        }
+        else
+        {
+          r_xram_rsp_to_tgt_rsp_pktid = 0x8 + r_xram_rsp_trt_buf.pktid;//RWT NCC
+        }
         for(size_t i=0; i < m_words; i++)
         {
@@ -4019,4 +4594,5 @@
         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;
@@ -4073,5 +4649,5 @@
     case XRAM_RSP_WRITE_DIRTY:  // send a write request to IXR_CMD FSM
     {
-      if(!r_xram_rsp_to_ixr_cmd_req.read())
+      if(!r_xram_rsp_to_ixr_cmd_req.read() and !r_xram_rsp_to_ixr_cmd_inval_ncc_pending.read())
       {
         r_xram_rsp_to_ixr_cmd_req = true;
@@ -4081,6 +4657,15 @@
         {
             r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
+              std::cout << "data L2 = " << std::hex << r_xram_rsp_victim_data[i] << std::dec << std::endl;
         }
         m_cpt_write_dirty++;
+        
+        if ((!r_xram_rsp_victim_coherent.read()) and (r_xram_rsp_victim_count.read() == 1)) //if NCC, we save the data in case of not dirty L1
+        {
+          r_xram_rsp_to_ixr_cmd_req = false;
+          r_xram_rsp_to_ixr_cmd_inval_ncc_pending = true;
+          r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          break;
+        }
 
         bool multi_req = !r_xram_rsp_victim_is_cnt.read() and r_xram_rsp_victim_inval.read();
@@ -4105,4 +4690,5 @@
       {
         r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+        m_cpt_xram_rsp_fsm_n_heap_lock++;
       }
 
@@ -4112,4 +4698,7 @@
           << " Requesting HEAP lock" << std::endl;
 #endif
+
+      m_cpt_xram_rsp_fsm_heap_lock++;
+
       break;
     }
@@ -4278,4 +4867,9 @@
       r_cleanup_inst  = (type == DspinDhccpParam::TYPE_CLEANUP_INST);
       r_cleanup_srcid = srcid;
+      r_cleanup_ncc = 
+        DspinDhccpParam::dspin_get(
+            flit,
+            DspinDhccpParam::CLEANUP_NCC);
+      r_cleanup_contains_data = false;
 
       if(srcid >= m_initiators)
@@ -4294,9 +4888,16 @@
 
 #if DEBUG_MEMC_CLEANUP
-if(m_debug)
-std::cout << "  <MEMC "         << name()
-          << " CLEANUP_IDLE> Cleanup request:" << std::hex
-          << " / owner_id = "   << srcid
-          << " / owner_ins = "  << (type == DspinDhccpParam::TYPE_CLEANUP_INST) << std::endl;
+      if(m_debug)
+      {
+        std::cout
+            << "  <MEMC "         << name()
+            << " CLEANUP_IDLE> Cleanup request:" << std::hex
+            << " / owner_id = "   << srcid
+            << " / owner_ins = "  << (type == DspinDhccpParam::TYPE_CLEANUP_INST)
+            << " / ncc = " << DspinDhccpParam::dspin_get(
+                                                          flit,
+                                                          DspinDhccpParam::CLEANUP_NCC)
+            << std::endl;
+      }
 #endif
       break;
@@ -4312,24 +4913,77 @@
       addr_t nline = r_cleanup_nline.read() |
         DspinDhccpParam::dspin_get(flit, DspinDhccpParam::CLEANUP_NLINE_LSB);
-
+      
+      //A MODIFIER POUR DIRTY //
+      bool eop =
+        DspinDhccpParam::dspin_get(flit, DspinDhccpParam::P2M_EOP) == 0x1;
+      if (! eop)
+      {
+        r_cleanup_fsm = CLEANUP_GET_DATA;
+        r_cleanup_data_index = 0;
+        r_cleanup_contains_data = true;
+      }
+      else
+      {
+        r_cleanup_fsm = CLEANUP_DIR_REQ;
+      }
       cc_receive_to_cleanup_fifo_get = true;
-      r_cleanup_nline                = nline;
-      r_cleanup_fsm                  = CLEANUP_DIR_REQ;
+      r_cleanup_nline               = nline;
 
 #if DEBUG_MEMC_CLEANUP
-if(m_debug)
-std::cout << "  <MEMC "         << name()
-          << " CLEANUP_GET_NLINE> Cleanup request:"
-          << " / address = " << std::hex << nline * m_words * 4 << std::endl;
-#endif
-      break;
-    }
-
+      if(m_debug)
+      {
+        std::cout
+            << "  <MEMC "         << name()
+            << " CLEANUP_GET_NLINE> Cleanup request:"
+            << std::hex
+            << " / address = "    << nline * m_words * 4
+            << " / contains data = " << (!eop)
+            << std::endl;
+      }
+#endif
+      break;
+    }
+    /////////////////////
+    case CLEANUP_GET_DATA :
+    {
+      if (m_cc_receive_to_cleanup_fifo.rok())
+      {
+        uint64_t flit = m_cc_receive_to_cleanup_fifo.read();
+  
+        uint32_t data = 
+          DspinDhccpParam::dspin_get (flit, DspinDhccpParam::CLEANUP_DATA_UPDT);
+  
+        r_cleanup_data[r_cleanup_data_index] = data;
+        r_cleanup_data_index = r_cleanup_data_index.read() + 1;
+        assert (r_cleanup_data_index.read() < m_words and "MEM_CACHE in CLEANUP_GET_DATA : too much flits in cleanup data updt");
+        cc_receive_to_cleanup_fifo_get = true;
+        if (r_cleanup_data_index.read() == m_words - 1)
+        {
+          r_cleanup_contains_data = true;
+          m_cpt_cleanup_data ++;
+          r_cleanup_fsm = CLEANUP_DIR_REQ;
+        }
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug)
+      {
+        std::cout
+            << "  <MEMC "         << name()
+            << " CLEANUP_GET_DATA> "
+            << " / word = "    << std::dec << r_cleanup_data_index.read()
+            << " / data = " << std::hex << data
+            << std::endl;
+      }
+#endif
+      }
+      break;
+    }
     /////////////////////
     case CLEANUP_DIR_REQ:   // Get the lock to the directory
     {
+      m_cpt_cleanup_fsm_dir_lock++;
       if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP) break;
 
       r_cleanup_fsm = CLEANUP_DIR_LOCK;
+      //std::cout << " MEM_CACHE : CLEANUP_DIR_REQ" << std::endl;
 
 #if DEBUG_MEMC_CLEANUP
@@ -4337,4 +4991,7 @@
 std::cout << "  <MEMC " << name() << " CLEANUP_DIR_REQ> Requesting DIR lock" << std::endl;
 #endif
+
+      m_cpt_cleanup_fsm_n_dir_lock++;
+
       break;
     }
@@ -4353,4 +5010,5 @@
         exit(0);
       }
+      //std::cout << " MEM_CACHE : CLEANUP_DIR_LOCK" << std::endl;
 
       // Read the directory
@@ -4371,4 +5029,11 @@
       r_cleanup_copy_cache   = entry.owner.cache_id;
 #endif
+
+      //RWT
+      size_t set = m_y[(addr_t)(cleanup_address)];
+      m_cache_data.read_line(way, set, r_cleanup_old_data); 
+      r_cleanup_coherent = entry.cache_coherent;
+
+
 
       if(entry.valid)      // hit : the copy must be cleared
@@ -4420,4 +5085,5 @@
     case CLEANUP_DIR_WRITE:
     {
+      /*ODCCP*///std::cout << "CLEANUP_DIR_WRITE" << std::endl;
       // Update the directory entry without heap access
       if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP)
@@ -4453,23 +5119,86 @@
       }
 
+      /*RWT*/
+      bool   inval_request = (r_read_to_cleanup_req.read() and (r_cleanup_nline.read() == r_read_to_cleanup_nline.read())) // NCC to CC initiated by a read transaction
+                          or (r_write_to_cleanup_req.read() and (r_cleanup_nline.read() == r_write_to_cleanup_nline.read())); //NCC to CC initiated by a wrtie transaction
+
+
+      if (inval_request) m_cpt_ncc_to_cc ++;
+
+      if (r_write_to_cleanup_req.read() and (r_cleanup_nline.read() == r_write_to_cleanup_nline.read()))
+      {
+        r_write_to_cleanup_req = false;
+        m_cpt_ncc_to_cc_write ++;
+      }
+
+
       // 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;
-
+      entry.valid          = true;
+      entry.cache_coherent = inval_request or r_cleanup_coherent.read();
+      entry.is_cnt         = r_cleanup_is_cnt.read();
+      entry.dirty          = r_cleanup_dirty.read() or r_cleanup_contains_data.read();
+      entry.tag            = r_cleanup_tag.read();
+      entry.lock           = r_cleanup_lock.read();
+      entry.ptr            = r_cleanup_ptr.read();
+      if (r_read_to_cleanup_req.read() and (r_cleanup_nline.read() == r_read_to_cleanup_nline.read())) //pending READ 
+      {
+        if (r_read_to_cleanup_cached_read.read())
+        {
+          entry.count          = r_cleanup_count.read();
+          entry.owner.srcid    = r_read_to_cleanup_srcid.read();
+          entry.owner.inst     = 0;
 #if L1_MULTI_CACHE
-      entry.owner.cache_id = 0;
-#endif
+          entry.owner.cache_id = r_cleanup_copy_cache.read();
+#endif
+        }
+        else
+        {
+          entry.count          = r_cleanup_count.read() - 1;
+          entry.owner.srcid    = r_cleanup_copy.read();
+          entry.owner.inst     = r_cleanup_copy_inst.read();
+#if L1_MULTI_CACHE
+          entry.owner.cache_id = r_cleanup_copy_cache.read();
+#endif
+        }
+        if (r_read_to_cleanup_is_ll.read())
+        {
+          r_cleanup_to_tgt_rsp_ll_key = r_read_to_cleanup_ll_key.read();
+        }
+      }
+      else
+      {
+        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
+      }
+
+
+      if (r_cleanup_contains_data.read())
+      {
+        for (size_t word = 0; word < m_words; word ++)
+        {
+          m_cache_data.write(way, set, word, r_cleanup_data[word].read(), 0xF);
+        }
+        m_llsc_table.sw(r_cleanup_nline.read());
+        //m_llsc_table.sw(r_cleanup_nline.read()*m_words*4);
+      }
+
 
       m_cache_directory.write(set, way, entry);
 
-      r_cleanup_fsm = CLEANUP_SEND_CLACK;
+
+      /*RWT*/
+      if (inval_request)
+      {
+        r_cleanup_fsm = CLEANUP_IVT_LOCK_DATA;
+      }
+      else
+      {
+        r_cleanup_fsm = CLEANUP_SEND_CLACK;
+      }
 
 #if DEBUG_MEMC_CLEANUP
@@ -4485,4 +5214,5 @@
             << " / count = "   << entry.count
             << " / is_cnt = "  << entry.is_cnt
+            << " / match_inval = " << inval_request
             << std::endl;
       }
@@ -4491,5 +5221,102 @@
       break;
     }
-
+    /////////////////////
+    case CLEANUP_IVT_LOCK_DATA://RWT
+    {
+    //Search for a matching inval in the UPT (there must be one) and check if there is a pending read.
+      if(r_alloc_ivt_fsm.read() == ALLOC_IVT_CLEANUP)
+      {
+        size_t index = 0;
+        bool   match_inval;
+
+        match_inval = m_upt.search_inval(r_cleanup_nline.read(), index);
+        assert (match_inval && "VCI MEM CACHE ERROR: In CLEANUP_IVT_LOCK_DATA, NO CORRESPONDING INVAL");
+        r_cleanup_read_srcid    = m_upt.srcid(index);
+        r_cleanup_read_trdid    = m_upt.trdid(index);
+        r_cleanup_read_pktid    = 0x0 + m_upt.pktid(index);
+        r_cleanup_read_need_rsp = !m_upt.need_rsp(index);
+        r_cleanup_index         = index;
+
+        r_cleanup_fsm = CLEANUP_IVT_CLEAR_DATA;
+      }
+#if DEBUG_MC_CLEANUP
+      if (m_debug)
+      {
+        std::cout
+            << " <MEMC " << name()
+            << " CLEANUP_IVT_LOCK_DATA> fetch pending inval"
+            << std::endl;
+      }
+#endif
+    break;
+    }
+
+    //////////////////////////
+    case CLEANUP_IVT_CLEAR_DATA://RWT
+    {
+      m_upt.clear(r_cleanup_index.read());
+      assert ((r_cleanup_read_need_rsp.read() == (r_read_to_cleanup_req.read() && (r_cleanup_nline.read() == r_read_to_cleanup_nline.read()))) && "condition pending read");
+      if (r_cleanup_read_need_rsp.read())
+      {
+        r_cleanup_fsm = CLEANUP_READ_RSP;
+      }
+      else
+      {
+        r_cleanup_fsm = CLEANUP_SEND_CLACK;
+      }
+#if DEBUG_MC_CLEANUP
+      if (m_debug)
+      {
+        std::cout
+            << " <MEMC " << name()
+            << " CLEANUP_IVT_CLEAR_DATA> clear UPT entry"
+            << std::endl;
+      }
+#endif
+    break;
+    }
+
+    ////////////////////////
+    case CLEANUP_READ_RSP://RWT
+    {
+      if(r_cleanup_to_tgt_rsp_req.read()) break;
+      
+      r_cleanup_to_tgt_rsp_req     = true;
+      r_cleanup_to_tgt_rsp_srcid   = r_cleanup_read_srcid.read();
+      r_cleanup_to_tgt_rsp_trdid   = r_cleanup_read_trdid.read();
+      r_cleanup_to_tgt_rsp_pktid   = 0x0 + r_cleanup_read_pktid.read();//WT
+      r_cleanup_to_tgt_rsp_type    = 0; //Read instruction
+      r_cleanup_to_tgt_rsp_length  = r_read_to_cleanup_length.read();
+      r_cleanup_to_tgt_rsp_first_word  = r_read_to_cleanup_first_word.read();
+      r_read_to_cleanup_req        = false;
+      m_cpt_ncc_to_cc_read ++;
+      if (r_cleanup_contains_data.read()) //L1 was dirty
+      {
+        for(size_t i = 0; i<m_words; i++)
+        {
+          r_cleanup_to_tgt_rsp_data[i] = r_cleanup_data[i].read();
+        }
+      }
+      else //the L2 data are up to date
+      {
+        for(size_t i = 0; i<m_words; i++)
+        {
+          r_cleanup_to_tgt_rsp_data[i] = r_cleanup_old_data[i].read();
+        }        
+      }
+
+      r_cleanup_fsm                = CLEANUP_SEND_CLACK;
+
+#if DEBUG_MC_CLEANUP
+      if (m_debug)
+      {
+        std::cout
+            << " <MEMC " << name()
+            << " CLEANUP_READ_RSP> answer READ"
+            << std::endl;
+      }
+#endif
+    break;
+    }
     //////////////////////
     case CLEANUP_HEAP_REQ:
@@ -4497,5 +5324,5 @@
       // get the lock to the HEAP directory
       if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP) break;
-
+ 
       r_cleanup_fsm = CLEANUP_HEAP_LOCK;
 
@@ -4509,4 +5336,5 @@
       }
 #endif
+      m_cpt_cleanup_fsm_n_heap_lock++;
       break;
     }
@@ -4568,6 +5396,7 @@
           << " / 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;
+          << " / heap_entry.owner.inst = " << heap_entry.owner.inst << std::endl
 /**/
+          << "nline = " << r_cleanup_nline << std::endl;
         exit(0);
       }
@@ -4587,7 +5416,7 @@
           << " / 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;
+          << " / heap_entry.owner.inst = " << heap_entry.owner.inst << std::endl
 /**/
-
+          << "nline = " << r_cleanup_nline << std::endl;
         exit(0);
       }
@@ -4595,4 +5424,5 @@
       DirectoryEntry dir_entry;
       dir_entry.valid          = true;
+      dir_entry.cache_coherent = true;
       dir_entry.is_cnt         = r_cleanup_is_cnt.read();
       dir_entry.dirty          = r_cleanup_dirty.read();
@@ -4652,4 +5482,5 @@
 
       m_cache_directory.write(set,way,dir_entry);
+
 
 #if DEBUG_MEMC_CLEANUP
@@ -4854,4 +5685,5 @@
                              // invalidate transaction matching the cleanup 
     {
+      m_cpt_cleanup_fsm_ivt_lock++;
       if(r_alloc_ivt_fsm.read() != ALLOC_IVT_CLEANUP) break;
 
@@ -4860,5 +5692,4 @@
 
       match_inval = m_ivt.search_inval(r_cleanup_nline.read(), index);
-
       if ( not match_inval )     // no pending inval
       {
@@ -4874,5 +5705,6 @@
           << std::endl;
 #endif
-          break;
+        m_cpt_cleanup_fsm_n_upt_lock++;
+        break;
       }
 
@@ -4914,4 +5746,5 @@
       m_ivt.decrement(r_cleanup_index.read(), count);
 
+
       if(count == 0)   // multi inval transaction completed
       {
@@ -4920,5 +5753,12 @@
       else             // multi inval transaction not completed
       {
-        r_cleanup_fsm = CLEANUP_SEND_CLACK ;
+        if (r_cleanup_ncc.read()) //need to put data to the XRAM
+        {
+          r_cleanup_fsm = CLEANUP_IXR_REQ;
+        }
+        else
+        {
+          r_cleanup_fsm = CLEANUP_SEND_CLACK;
+        }
       }
 
@@ -4950,4 +5790,5 @@
       if      ( r_cleanup_need_rsp.read() ) r_cleanup_fsm = CLEANUP_WRITE_RSP;
       else if ( r_cleanup_need_ack.read() ) r_cleanup_fsm = CLEANUP_CONFIG_ACK;
+      else if ( r_cleanup_ncc.read()      ) r_cleanup_fsm = CLEANUP_IXR_REQ;
       else                                  r_cleanup_fsm = CLEANUP_SEND_CLACK;
 
@@ -4971,6 +5812,14 @@
       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_CLACK;
+      r_cleanup_to_tgt_rsp_type    = true;
+
+      if (r_cleanup_ncc.read())
+      {
+        r_cleanup_fsm = CLEANUP_IXR_REQ;//need to put data to the XRAM
+      }
+      else
+      {
+        r_cleanup_fsm = CLEANUP_SEND_CLACK;
+      }
 
 #if DEBUG_MEMC_CLEANUP
@@ -5000,4 +5849,67 @@
       break;
     }
+
+    /////////////////////////
+    case CLEANUP_IXR_REQ:
+    {
+    
+      //Send a request to the ixr to write the data in the XRAM using the prereserved TRT entry
+      if (r_alloc_trt_fsm.read() == ALLOC_TRT_CLEANUP)
+      {
+        if(!r_cleanup_to_ixr_cmd_req.read())
+        {
+          size_t index = 0;
+          bool   hit   = m_trt.hit_write(r_cleanup_nline.read(), &index); 
+
+          assert (hit and "CLEANUP_IXR_REQ found no matching entry in TRT");
+
+            r_cleanup_to_ixr_cmd_req     = true;
+
+            for(size_t i = 0; i < m_words; i++){
+              r_cleanup_to_ixr_cmd_data[i]   = r_cleanup_data[i];
+            }
+
+            r_cleanup_to_ixr_cmd_srcid   = r_cleanup_srcid.read();
+            r_cleanup_to_ixr_cmd_trdid   = index;
+            r_cleanup_to_ixr_cmd_pktid   = r_cleanup_pktid.read();
+            r_cleanup_to_ixr_cmd_nline   = r_cleanup_nline.read();
+            r_cleanup_to_ixr_cmd_ncc_l1_dirty = r_cleanup_contains_data.read();
+            r_cleanup_fsm = CLEANUP_SEND_CLACK;
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << " CLEANUP_IXR_REQ>"
+            << " request send to IXR_CMD"
+            << std::endl;
+      }
+#endif
+        }
+        else
+        {
+            r_cleanup_fsm = CLEANUP_WAIT;
+#if DEBUG_MEMC_CLEANUP
+      if(m_debug)
+      {
+        std::cout
+            << "  <MEMC " << name()
+            << " CLEANUP_IXR_REQ>"
+            << " waiting completion of previous request"
+            << std::endl;
+      }
+#endif
+        }
+      }
+      break;
+    }
+
+    /////////////////////
+    case CLEANUP_WAIT :
+    {
+      r_cleanup_fsm = CLEANUP_IXR_REQ;
+      break;
+    }
+
     ////////////////////////
     case CLEANUP_SEND_CLACK:  // acknowledgement to a cleanup command
@@ -5102,4 +6014,5 @@
       {
         r_cas_fsm = CAS_DIR_LOCK;
+        m_cpt_cas_fsm_n_dir_lock++;
       }
 
@@ -5112,4 +6025,7 @@
       }
 #endif
+
+      m_cpt_cas_fsm_dir_lock++;
+
       break;
     }
@@ -5124,4 +6040,5 @@
 
         r_cas_is_cnt     = entry.is_cnt;
+        r_cas_coherent   = entry.cache_coherent;
         r_cas_dirty      = entry.dirty;
         r_cas_tag        = entry.tag;
@@ -5171,4 +6088,5 @@
       DirectoryEntry entry;
       entry.valid          = true;
+      entry.cache_coherent = r_cas_coherent.read();
       entry.is_cnt         = r_cas_is_cnt.read();
       entry.dirty          = true;
@@ -5238,5 +6156,11 @@
     {
       // The CAS is a success => sw access to the llsc_global_table
-      m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
+      // BUG LLSC
+      addr_t      nline      = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
+      m_llsc_table.sw(nline);
+      //m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
+          /**//*std::cout << "MEMCACHE : from proc " << m_cmd_cas_srcid_fifo.read()
+                        << " | @ " << std::hex << m_cmd_cas_addr_fifo.read()
+                        << " | WRITE (cas triggered)" << std::endl;*/
 
       // test coherence request
@@ -5355,5 +6279,9 @@
           << " / count = " << nb_copies << std::endl;
 #endif
-      }
+        m_cpt_cas_fsm_n_upt_lock++;
+      }
+
+      m_cpt_cas_fsm_upt_lock++;
+
       break;
     }
@@ -5386,5 +6314,9 @@
 #endif
         r_cas_fsm = CAS_UPT_REQ;
-      }
+        m_cpt_cas_fsm_n_heap_lock++;
+      }
+
+      m_cpt_cas_fsm_heap_lock++;
+
       break;
     }
@@ -5526,5 +6458,9 @@
           r_cas_fsm = CAS_WAIT;
         }
-      }
+        m_cpt_cas_fsm_n_trt_lock++;
+      }
+
+      m_cpt_cas_fsm_trt_lock++;
+
       break;
     }
@@ -5591,5 +6527,9 @@
           r_cas_fsm = CAS_WAIT;
         }
-      }
+        m_cpt_cas_fsm_n_upt_lock++;
+      }
+
+      m_cpt_cas_fsm_upt_lock++;
+
       break;
     }
@@ -5769,5 +6709,9 @@
           r_cas_fsm       = CAS_MISS_TRT_SET;
         }
-      }
+        m_cpt_cas_fsm_n_trt_lock++;
+      }
+
+      m_cpt_cas_fsm_trt_lock++;
+
       break;
     }
@@ -5897,5 +6841,30 @@
           break;
         }
+
+        if(r_read_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_READ_NCC_INVAL_HEADER;
+          break;
+        }
+
+        if(r_write_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_NCC_INVAL_HEADER;
+          break;
+        }
+
+
         // WRITE
+        if(r_read_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_READ_NCC_INVAL_HEADER;
+          break;
+        }
+
+        if(r_write_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_NCC_INVAL_HEADER;
+          break;
+        }
         if(m_write_to_cc_send_inst_fifo.rok() or
             r_write_to_cc_send_multi_req.read())
@@ -5971,4 +6940,15 @@
         }
         // WRITE
+        if(r_read_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_READ_NCC_INVAL_HEADER;
+          break;
+        }
+
+        if(r_write_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_NCC_INVAL_HEADER;
+          break;
+        }
         if(m_write_to_cc_send_inst_fifo.rok() or
             r_write_to_cc_send_multi_req.read())
@@ -6003,5 +6983,30 @@
           break;
         }
+
+        if(r_read_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_READ_NCC_INVAL_HEADER;
+          break;
+        }
+
+        if(r_write_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_NCC_INVAL_HEADER;
+          break;
+        }
+
+
         // WRITE
+        if(r_read_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_READ_NCC_INVAL_HEADER;
+          break;
+        }
+
+        if(r_write_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_NCC_INVAL_HEADER;
+          break;
+        }
         if(m_write_to_cc_send_inst_fifo.rok() or
             r_write_to_cc_send_multi_req.read())
@@ -6050,4 +7055,18 @@
       case CC_SEND_CAS_IDLE:   // CLEANUP FSM has highest priority
       {
+
+        if(r_read_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_READ_NCC_INVAL_HEADER;
+          break;
+        }
+
+        if(r_write_to_cc_send_req.read())
+        {
+          r_cc_send_fsm = CC_SEND_WRITE_NCC_INVAL_HEADER;
+          break;
+        }
+
+
         if(m_write_to_cc_send_inst_fifo.rok() or
             r_write_to_cc_send_multi_req.read())
@@ -6208,4 +7227,63 @@
         break;
       }
+
+    case CC_SEND_READ_NCC_INVAL_HEADER:
+      {
+        if(not p_dspin_m2p.read) break;
+
+        r_cc_send_fsm = CC_SEND_READ_NCC_INVAL_NLINE;
+        break;
+      }
+
+    case CC_SEND_READ_NCC_INVAL_NLINE:
+      {
+        if(not p_dspin_m2p.read) break;
+
+        r_read_to_cc_send_req = false;
+        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
+
+#if DEBUG_MEMC_CC_SEND
+        if(m_debug)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << " CC_SEND_READ_NCC_INVAL_HEADER> Inval for line "
+            << r_read_to_cc_send_nline.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+
+    case CC_SEND_WRITE_NCC_INVAL_HEADER:
+      {
+        if(not p_dspin_m2p.read) break;
+
+        r_cc_send_fsm = CC_SEND_WRITE_NCC_INVAL_NLINE;
+        break;
+      }
+
+    case CC_SEND_WRITE_NCC_INVAL_NLINE:
+      {
+        if(not p_dspin_m2p.read) break;
+
+        r_write_to_cc_send_req = false;
+        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
+
+#if DEBUG_MEMC_CC_SEND
+        if(m_debug)
+        {
+          std::cout
+            << "  <MEMC " << name()
+            << " CC_SEND_WRITE_NCC_INVAL_HEADER> Inval for line "
+            << r_write_to_cc_send_nline.read()
+            << std::endl;
+        }
+#endif
+        break;
+      }
+
+
       //////////////////////////////////
       case CC_SEND_WRITE_BRDCAST_HEADER:   // send first flit broadcast-inval (from WRITE FSM)
@@ -6417,10 +7495,7 @@
           break;
 
-        assert(not p_dspin_p2m.eop.read() and
-            "VCI_MEM_CACHE ERROR in CC_RECEIVE : "
-            "CLEANUP command must have two flits");
-
         cc_receive_to_cleanup_fifo_put = true;
-        r_cc_receive_fsm               = CC_RECEIVE_CLEANUP_EOP;
+        if(p_dspin_p2m.eop.read())
+          r_cc_receive_fsm               = CC_RECEIVE_IDLE;
 
         break;
@@ -6439,6 +7514,6 @@
 
         cc_receive_to_cleanup_fifo_put = true;
-        r_cc_receive_fsm               = CC_RECEIVE_IDLE;
-
+        if(p_dspin_p2m.eop.read())
+          r_cc_receive_fsm               = CC_RECEIVE_IDLE;
         break;
       }
@@ -6519,5 +7594,9 @@
       }
       else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_MULTI_ACK;
-      else if(r_cleanup_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+      else if(r_cleanup_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+        r_tgt_rsp_cpt = r_cleanup_to_tgt_rsp_first_word.read();
+      }
       else if(r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
       else if(r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
@@ -6535,4 +7614,79 @@
       }
       else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_MULTI_ACK;
+      else if(r_cleanup_to_tgt_rsp_req) 
+      {
+        r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+        r_tgt_rsp_cpt = r_cleanup_to_tgt_rsp_first_word.read();
+      }
+      else if(r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
+      else if(r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
+      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_MULTI_ACK;
+      else if(r_cleanup_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+        r_tgt_rsp_cpt = r_cleanup_to_tgt_rsp_first_word.read();
+      }
+
+      else if(r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
+      else if(r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
+      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_MULTI_ACK   ;
+      else if(r_cleanup_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+        r_tgt_rsp_cpt = r_cleanup_to_tgt_rsp_first_word.read();
+      }
+      else if(r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
+      else if(r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
+      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: // multi ack requests have the highest priority
+    {
+
+      if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_MULTI_ACK   ;
+      else if(r_cleanup_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+        r_tgt_rsp_cpt = r_cleanup_to_tgt_rsp_first_word.read();
+      }
       else if(r_cleanup_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
       else if(r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
@@ -6543,10 +7697,6 @@
         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_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)
       {
@@ -6554,6 +7704,14 @@
         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_MULTI_ACK;
-      else if(r_cleanup_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+      break;
+    }
+    ////////////////////////////
+    case TGT_RSP_MULTI_ACK_IDLE: // cleanup requests have the highest priority
+    {
+      if(r_cleanup_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+        r_tgt_rsp_cpt = r_cleanup_to_tgt_rsp_first_word.read();
+      }
       else if(r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
       else if(r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
@@ -6564,34 +7722,17 @@
       }
       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)
+      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_MULTI_ACK   ;
-      else if(r_cleanup_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
-      else if(r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
-      else if(r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
-      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: // multi ack requests have the highest priority
-    {
-
-      if(r_multi_ack_to_tgt_rsp_req)      r_tgt_rsp_fsm = TGT_RSP_MULTI_ACK   ;
-      else if(r_cleanup_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
-      else if(r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
+      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_MULTI_ACK;
+      break;
+    }
+    //////////////////////////
+    case TGT_RSP_CLEANUP_IDLE: // tgt cmd requests have the highest priority
+    {
+      if(r_config_to_tgt_rsp_req)         r_tgt_rsp_fsm = TGT_RSP_CONFIG;
       else if(r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
       else if(r_read_to_tgt_rsp_req)
@@ -6607,46 +7748,10 @@
         r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
       }
-      break;
-    }
-    ////////////////////////////
-    case TGT_RSP_MULTI_ACK_IDLE: // cleanup requests have the highest priority
-    {
-      if(r_cleanup_to_tgt_rsp_req)        r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
-      else if(r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
-      else if(r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
-      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_MULTI_ACK;
-      break;
-    }
-    //////////////////////////
-    case TGT_RSP_CLEANUP_IDLE: // tgt cmd requests have the highest priority
-    {
-      if(r_config_to_tgt_rsp_req)         r_tgt_rsp_fsm = TGT_RSP_CONFIG;
-      else if(r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
-      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_MULTI_ACK   ;
-      else if(r_cleanup_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+      else if(r_cleanup_to_tgt_rsp_req)
+      {
+        r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+        r_tgt_rsp_cpt = r_cleanup_to_tgt_rsp_first_word.read();
+      }
       break;
     }
@@ -6716,4 +7821,5 @@
 #endif
 
+
         uint32_t last_word_idx = r_read_to_tgt_rsp_word.read() +
                                  r_read_to_tgt_rsp_length.read() - 1;
@@ -6728,4 +7834,36 @@
           r_read_to_tgt_rsp_req = false;
           r_tgt_rsp_fsm         = TGT_RSP_READ_IDLE;
+          if (r_read_to_tgt_rsp_pktid.read() == 0x0)
+          {
+            m_cpt_read_data_unc ++;
+          }
+          else if (r_read_to_tgt_rsp_pktid.read() == 0x1)
+          {
+            m_cpt_read_data_miss_CC ++;
+          }
+          else if (r_read_to_tgt_rsp_pktid.read() == 0x2)
+          {
+            m_cpt_read_ins_unc ++;
+          }
+          else if (r_read_to_tgt_rsp_pktid.read() == 0x3)
+          {
+            m_cpt_read_ins_miss ++;
+          }
+          else if (r_read_to_tgt_rsp_pktid.read() == 0x6)
+          {
+            m_cpt_read_ll_CC ++;
+          }
+          else if (r_read_to_tgt_rsp_pktid.read() == 0x9)
+          {
+            m_cpt_read_data_miss_NCC ++;
+          }
+          else if (r_read_to_tgt_rsp_pktid.read() == 0x14)
+          {
+            m_cpt_read_ll_NCC ++;
+          }
+          else
+          {
+            m_cpt_read_WTF ++;
+          }
         }
         else
@@ -6768,12 +7906,71 @@
 
 #if DEBUG_MEMC_TGT_RSP
-if(m_debug)
-std::cout << "  <MEMC " << name() << " TGT_RSP_CLEANUP> Cleanup response"
-          << " / rsrcid = " << std::hex << 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;
+        if(m_debug)
+        {
+          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
+                    << " / data = " << std::hex << r_cleanup_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read() << std::dec << std::endl;
+        }
+#endif
+
+
+        uint32_t last_word_idx = r_cleanup_to_tgt_rsp_first_word.read() + r_cleanup_to_tgt_rsp_length.read() - 1;
+        bool is_ll = ((r_cleanup_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
+
+        if (r_cleanup_to_tgt_rsp_type.read() or ((r_tgt_rsp_cpt.read() == last_word_idx) and not is_ll) or (r_tgt_rsp_key_sent.read() and is_ll) )
+        {
+          r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
+          r_cleanup_to_tgt_rsp_req = false;
+          r_tgt_rsp_key_sent = false;
+
+
+          if (r_cleanup_to_tgt_rsp_pktid.read() == 0x0)
+          {
+            m_cpt_read_data_unc ++;
+          }
+          else if (r_cleanup_to_tgt_rsp_pktid.read() == 0x1)
+          {
+            m_cpt_read_data_miss_CC ++;
+          }
+          else if (r_cleanup_to_tgt_rsp_pktid.read() == 0x2)
+          {
+            m_cpt_read_ins_unc ++;
+          }
+          else if (r_cleanup_to_tgt_rsp_pktid.read() == 0x3)
+          {
+            m_cpt_read_ins_miss ++;
+          }
+          else if (r_cleanup_to_tgt_rsp_pktid.read() == 0x6)
+          {
+            m_cpt_read_ll_CC ++;
+          }
+          else if (r_cleanup_to_tgt_rsp_pktid.read() == 0x9)
+          {
+            m_cpt_read_data_miss_NCC ++;
+          }
+          else if (r_cleanup_to_tgt_rsp_pktid.read() == 0x14)
+          {
+            m_cpt_read_ll_NCC ++;
+          }
+          else if (!r_cleanup_to_tgt_rsp_type.read())
+          {
+            m_cpt_read_WTF ++;
+          }
+
+        }
+        else
+        {
+          if (is_ll)
+          {
+            r_tgt_rsp_key_sent = true;
+          }
+          else
+          {
+            r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+          }
+        }
+
       }
       break;
@@ -6825,4 +8022,39 @@
           r_xram_rsp_to_tgt_rsp_req = false;
           r_tgt_rsp_fsm             = TGT_RSP_XRAM_IDLE;
+
+
+          if (r_xram_rsp_to_tgt_rsp_pktid.read() == 0x0)
+          {
+            m_cpt_read_data_unc ++;
+          }
+          else if (r_xram_rsp_to_tgt_rsp_pktid.read() == 0x1)
+          {
+            m_cpt_read_data_miss_CC ++;
+          }
+          else if (r_xram_rsp_to_tgt_rsp_pktid.read() == 0x2)
+          {
+            m_cpt_read_ins_unc ++;
+          }
+          else if (r_xram_rsp_to_tgt_rsp_pktid.read() == 0x3)
+          {
+            m_cpt_read_ins_miss ++;
+          }
+          else if (r_xram_rsp_to_tgt_rsp_pktid.read() == 0x6)
+          {
+            m_cpt_read_ll_CC ++;
+          }
+          else if (r_xram_rsp_to_tgt_rsp_pktid.read() == 0x9)
+          {
+            m_cpt_read_data_miss_NCC ++;
+          }
+          else if (r_xram_rsp_to_tgt_rsp_pktid.read() == 0x14)
+          {
+            m_cpt_read_ll_NCC ++;
+          }
+          else
+          {
+            m_cpt_read_WTF ++;
+          }
+
         }
         else
@@ -6882,4 +8114,7 @@
               else if (r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
                   r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
+            
+              else
+                  m_cpt_upt_unused++;
           }
           break;
@@ -6894,4 +8129,7 @@
               else if (r_write_fsm.read() == WRITE_UPT_LOCK)
                   r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+            
+              else
+                  m_cpt_upt_unused++;
           }
           break;
@@ -6907,4 +8145,7 @@
               else if (r_cas_fsm.read() == CAS_UPT_LOCK)
                   r_alloc_upt_fsm = ALLOC_UPT_CAS;
+            
+              else
+                  m_cpt_upt_unused++;
           }
           break;
@@ -6930,17 +8171,53 @@
       //////////////////////////
       case ALLOC_IVT_WRITE:            // allocated to WRITE FSM
-          if (r_write_fsm.read() != WRITE_BC_IVT_LOCK)
+          if ((r_write_fsm.read() != WRITE_BC_IVT_LOCK) and
+             (r_write_fsm.read() != WRITE_IVT_LOCK_HIT_WB) and
+             (r_write_fsm.read() != WRITE_MISS_IVT_LOCK))
           {
-              if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
-
-              else if (r_cleanup_fsm.read() == CLEANUP_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
-
-              else if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
+            if(r_read_fsm.read() == READ_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_READ;
+            
+            else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
+
+            else if ((r_cleanup_fsm.read() == CLEANUP_IVT_LOCK) or
+                    (r_cleanup_fsm.read() == CLEANUP_IVT_LOCK_DATA))
+              r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
+              
+            else if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
                   r_alloc_ivt_fsm = ALLOC_IVT_CAS;
-
-              else if (r_config_fsm.read() == CONFIG_DIR_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
+        
+            else if (r_config_fsm.read() == CONFIG_DIR_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
+
+            else
+              m_cpt_ivt_unused++;
+          }
+          break;
+
+      //////////////////////////
+      case ALLOC_IVT_READ:            // allocated to READ FSM
+          if (r_read_fsm.read() != READ_IVT_LOCK) 
+          {
+            if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
+
+            else if ((r_cleanup_fsm.read() == CLEANUP_IVT_LOCK) or
+                    (r_cleanup_fsm.read() == CLEANUP_IVT_LOCK_DATA))
+              r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
+              
+            else if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
+                  r_alloc_ivt_fsm = ALLOC_IVT_CAS;
+        
+            else if (r_config_fsm.read() == CONFIG_DIR_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
+          
+            else if ((r_write_fsm.read() == WRITE_BC_IVT_LOCK) or
+                (r_write_fsm.read() == WRITE_IVT_LOCK_HIT_WB) or
+                (r_write_fsm.read() == WRITE_MISS_IVT_LOCK))
+              r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
+
+            else
+              m_cpt_ivt_unused++;
           }
           break;
@@ -6950,15 +8227,24 @@
           if(r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)
           {
-              if(r_cleanup_fsm.read() == CLEANUP_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
-
-              else if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CAS;
-
-              else if (r_config_fsm.read() == CONFIG_DIR_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
-
-              else if (r_write_fsm.read() == WRITE_BC_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
+            if ((r_cleanup_fsm.read() == CLEANUP_IVT_LOCK) or
+                (r_cleanup_fsm.read() == CLEANUP_IVT_LOCK_DATA))
+              r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
+
+            else if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_CAS;
+
+            else if (r_config_fsm.read() == CONFIG_DIR_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
+
+            else if ((r_write_fsm.read() == WRITE_BC_IVT_LOCK) or
+                    (r_write_fsm.read() == WRITE_IVT_LOCK_HIT_WB) or
+                    (r_write_fsm.read() == WRITE_MISS_IVT_LOCK))
+              r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
+
+            else if(r_read_fsm.read() == READ_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_READ;
+            
+            else
+              m_cpt_ivt_unused++;
           }
           break;
@@ -6967,17 +8253,26 @@
       case ALLOC_IVT_CLEANUP:          // allocated to CLEANUP FSM
           if ((r_cleanup_fsm.read() != CLEANUP_IVT_LOCK     ) and
-              (r_cleanup_fsm.read() != CLEANUP_IVT_DECREMENT))
+              (r_cleanup_fsm.read() != CLEANUP_IVT_DECREMENT) and
+              (r_cleanup_fsm.read() != CLEANUP_IVT_LOCK_DATA))
           {
-              if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CAS;
-
-              else if (r_config_fsm.read() == CONFIG_DIR_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
-
-              else if (r_write_fsm.read() == WRITE_BC_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
-
-              else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
+            if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_CAS;
+
+            else if (r_config_fsm.read() == CONFIG_DIR_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
+
+            else if ((r_write_fsm.read() == WRITE_BC_IVT_LOCK) or
+                (r_write_fsm.read() == WRITE_IVT_LOCK_HIT_WB) or
+                (r_write_fsm.read() == WRITE_MISS_IVT_LOCK))
+              r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
+
+            else if(r_read_fsm.read() == READ_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_READ;
+
+            else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
+
+            else
+              m_cpt_ivt_unused++;
           }
           break;
@@ -6987,15 +8282,24 @@
           if (r_cas_fsm.read() != CAS_BC_IVT_LOCK)
           {
-              if (r_config_fsm.read() == CONFIG_DIR_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
-
-              else if (r_write_fsm.read() == WRITE_BC_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
-
-              else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
-
-              else if (r_cleanup_fsm.read() == CLEANUP_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
+            if (r_config_fsm.read() == CONFIG_DIR_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
+
+            else if ((r_write_fsm.read() == WRITE_BC_IVT_LOCK) or
+                (r_write_fsm.read() == WRITE_IVT_LOCK_HIT_WB) or
+                (r_write_fsm.read() == WRITE_MISS_IVT_LOCK))
+              r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
+
+            else if(r_read_fsm.read() == READ_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_READ;
+
+            else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
+
+            else if ((r_cleanup_fsm.read() == CLEANUP_IVT_LOCK) or
+                (r_cleanup_fsm.read() == CLEANUP_IVT_LOCK_DATA))
+              r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
+
+            else
+              m_cpt_ivt_unused++;
           }
           break;
@@ -7005,20 +8309,28 @@
           if (r_config_fsm.read() != CONFIG_DIR_IVT_LOCK)
           {
-              if (r_write_fsm.read() == WRITE_BC_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
-
-              else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
-
-              else if (r_cleanup_fsm.read() == CLEANUP_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
-
-              else if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
-                  r_alloc_ivt_fsm = ALLOC_IVT_CAS;
+            if ((r_write_fsm.read() == WRITE_BC_IVT_LOCK) or
+                (r_write_fsm.read() == WRITE_IVT_LOCK_HIT_WB) or
+                (r_write_fsm.read() == WRITE_MISS_IVT_LOCK))
+              r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
+
+            else if(r_read_fsm.read() == READ_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_READ;
+
+            else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
+
+            else if ((r_cleanup_fsm.read() == CLEANUP_IVT_LOCK) or
+                (r_cleanup_fsm.read() == CLEANUP_IVT_LOCK_DATA))
+              r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
+      
+            else if(r_cas_fsm.read() == CAS_BC_IVT_LOCK)
+              r_alloc_ivt_fsm = ALLOC_IVT_CAS;
+
+            else
+              m_cpt_ivt_unused++;
           }
           break;
-
   } // end switch r_alloc_ivt_fsm
-
+  
   ////////////////////////////////////////////////////////////////////////////////////
   //    ALLOC_DIR FSM
@@ -7073,5 +8385,6 @@
          (r_read_fsm.read()      != READ_DIR_LOCK)   and
          (r_read_fsm.read()      != READ_TRT_LOCK)   and
-         (r_read_fsm.read()      != READ_HEAP_REQ))
+         (r_read_fsm.read()      != READ_HEAP_REQ)   and
+         (r_read_fsm.read()      != READ_IVT_LOCK))
          or
          ((r_read_fsm.read()       == READ_TRT_LOCK)   and
@@ -7089,28 +8402,35 @@
         else if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
           r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
-
+        
         else if(r_config_fsm.read() == CONFIG_DIR_REQ)
           r_alloc_dir_fsm = ALLOC_DIR_CONFIG;
-    }
-    break;
-
-    /////////////////////
-    case ALLOC_DIR_WRITE:    // allocated to WRITE FSM
-    if(((r_write_fsm.read()       != WRITE_DIR_REQ)  and
-        (r_write_fsm.read()       != WRITE_DIR_LOCK)  and
-        (r_write_fsm.read()       != WRITE_DIR_READ)  and
-        (r_write_fsm.read()       != WRITE_DIR_HIT)  and
-        (r_write_fsm.read()       != WRITE_BC_TRT_LOCK)  and
-        (r_write_fsm.read()       != WRITE_BC_IVT_LOCK)  and
-        (r_write_fsm.read()       != WRITE_MISS_TRT_LOCK)  and
-        (r_write_fsm.read()       != WRITE_UPT_LOCK)  and
-        (r_write_fsm.read()       != WRITE_UPT_HEAP_LOCK))
-        or
-        ((r_write_fsm.read()      == WRITE_UPT_HEAP_LOCK)  and
-         (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE))
-        or
-        ((r_write_fsm.read()      == WRITE_MISS_TRT_LOCK)  and
-         (r_alloc_trt_fsm.read()  == ALLOC_TRT_WRITE)))
-    {
+
+        else
+          m_cpt_dir_unused++;
+      }
+      else
+        m_cpt_read_fsm_dir_used++;
+      break;
+
+      /////////////////////
+    case ALLOC_DIR_WRITE:
+      if(((r_write_fsm.read()       != WRITE_DIR_REQ)  and
+          (r_write_fsm.read()       != WRITE_DIR_LOCK)  and
+          (r_write_fsm.read()       != WRITE_DIR_READ)  and
+          (r_write_fsm.read()       != WRITE_DIR_HIT)  and
+          (r_write_fsm.read()       != WRITE_BC_TRT_LOCK)  and
+          (r_write_fsm.read()       != WRITE_BC_IVT_LOCK)  and
+          (r_write_fsm.read()       != WRITE_MISS_IVT_LOCK)  and
+          (r_write_fsm.read()       != WRITE_MISS_TRT_LOCK)  and
+          (r_write_fsm.read()       != WRITE_UPT_LOCK)  and
+          (r_write_fsm.read()       != WRITE_UPT_HEAP_LOCK) and
+          (r_write_fsm.read()       != WRITE_IVT_LOCK_HIT_WB))
+          or
+          ((r_write_fsm.read()      == WRITE_UPT_HEAP_LOCK)  and
+           (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE))
+          or
+          ((r_write_fsm.read()      == WRITE_MISS_TRT_LOCK)  and
+           (r_alloc_trt_fsm.read()  == ALLOC_TRT_WRITE)))
+      {
         if(r_cas_fsm.read() == CAS_DIR_REQ)
           r_alloc_dir_fsm = ALLOC_DIR_CAS;
@@ -7127,10 +8447,15 @@
         else if(r_read_fsm.read() == READ_DIR_REQ)
           r_alloc_dir_fsm = ALLOC_DIR_READ;
-    }
-    break;
+        
+        else
+          m_cpt_dir_unused++;
+      }
+      else
+        m_cpt_write_fsm_dir_used++;
+      break;
 
     ///////////////////
     case ALLOC_DIR_CAS:    // allocated to CAS FSM
-    if(((r_cas_fsm.read()         != CAS_DIR_REQ)  and
+      if(((r_cas_fsm.read()         != CAS_DIR_REQ)  and
         (r_cas_fsm.read()         != CAS_DIR_LOCK)  and
         (r_cas_fsm.read()         != CAS_DIR_HIT_READ)  and
@@ -7148,5 +8473,5 @@
         ((r_cas_fsm.read()        == CAS_MISS_TRT_LOCK)  and
          (r_alloc_trt_fsm.read()  == ALLOC_TRT_CAS)))
-    {
+      {
         if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
           r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
@@ -7163,14 +8488,20 @@
         else if(r_write_fsm.read() == WRITE_DIR_REQ)
           r_alloc_dir_fsm = ALLOC_DIR_WRITE;
-    }
-      break;
-
+        
+        else
+          m_cpt_dir_unused++;
+      }
+      else
+        m_cpt_cas_fsm_dir_used++;
+      break;
+      
     ///////////////////////
     case ALLOC_DIR_CLEANUP:    // allocated to CLEANUP FSM
-    if((r_cleanup_fsm.read() != CLEANUP_DIR_REQ) and
+      if((r_cleanup_fsm.read() != CLEANUP_DIR_REQ) and
         (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) and
         (r_cleanup_fsm.read() != CLEANUP_HEAP_REQ) and
-        (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK))
-    {
+        (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) and
+        (r_cleanup_fsm.read() != CLEANUP_IVT_LOCK_DATA))
+      {
         if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
           r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
@@ -7187,13 +8518,18 @@
         else if(r_cas_fsm.read() == CAS_DIR_REQ)
           r_alloc_dir_fsm = ALLOC_DIR_CAS;
-    }
-    break;
+
+        else
+          m_cpt_dir_unused++;
+      }
+      else
+        m_cpt_cleanup_fsm_dir_used++;
+      break;
 
     ////////////////////////
     case ALLOC_DIR_XRAM_RSP:    // allocated to XRAM_RSP FSM
-    if( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK) and
+      if( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK) and
         (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY) and
         (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
-    {
+      {
         if(r_config_fsm.read() == CONFIG_DIR_REQ)
           r_alloc_dir_fsm = ALLOC_DIR_CONFIG;
@@ -7210,6 +8546,11 @@
         else if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
           r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
-    }
-    break;
+
+        else
+          m_cpt_dir_unused++;
+      }
+      else
+        m_cpt_xram_rsp_fsm_dir_used++;
+      break;
 
   } // end switch alloc_dir_fsm
@@ -7245,5 +8586,13 @@
                 (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
           r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
-      }
+
+        else if (r_cleanup_fsm.read() == CLEANUP_IXR_REQ)
+          r_alloc_trt_fsm = ALLOC_TRT_CLEANUP;
+
+        else
+          m_cpt_trt_unused++;
+      }
+      else
+        m_cpt_read_fsm_trt_used++;
       break;
 
@@ -7265,8 +8614,16 @@
                 (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
           r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+        
+        else if (r_cleanup_fsm.read() == CLEANUP_IXR_REQ)
+          r_alloc_trt_fsm = ALLOC_TRT_CLEANUP;
 
         else if(r_read_fsm.read() == READ_TRT_LOCK)
           r_alloc_trt_fsm = ALLOC_TRT_READ;
-      }
+
+        else
+          m_cpt_trt_unused++;
+      }
+      else
+        m_cpt_write_fsm_trt_used++;
       break;
 
@@ -7284,4 +8641,7 @@
                 (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
           r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+        
+        else if (r_cleanup_fsm.read() == CLEANUP_IXR_REQ)
+          r_alloc_trt_fsm = ALLOC_TRT_CLEANUP;
 
         else if(r_read_fsm.read() == READ_TRT_LOCK)
@@ -7291,5 +8651,10 @@
                 (r_write_fsm.read() == WRITE_BC_TRT_LOCK))
           r_alloc_trt_fsm = ALLOC_TRT_WRITE;
-      }
+
+        else
+          m_cpt_trt_unused++;
+      }
+      else
+        m_cpt_cas_fsm_trt_used++;
       break;
 
@@ -7305,4 +8670,7 @@
             (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
           r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+        
+        else if (r_cleanup_fsm.read() == CLEANUP_IXR_REQ)
+          r_alloc_trt_fsm = ALLOC_TRT_CLEANUP;
 
         else if(r_read_fsm.read() == READ_TRT_LOCK)
@@ -7316,5 +8684,10 @@
                 (r_cas_fsm.read() == CAS_BC_TRT_LOCK))
           r_alloc_trt_fsm = ALLOC_TRT_CAS;
-      }
+
+        else
+          m_cpt_trt_unused++;
+      }
+      else
+        m_cpt_xram_rsp_fsm_trt_used++;
       break;
 
@@ -7324,4 +8697,35 @@
           (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ))
       {
+        
+        if (r_cleanup_fsm.read() == CLEANUP_IXR_REQ)
+          r_alloc_trt_fsm = ALLOC_TRT_CLEANUP;
+
+        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;
+
+        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
+          m_cpt_trt_unused++;
+      }
+      else
+        m_cpt_ixr_fsm_trt_used++;
+      break;
+
+      ////////////////////////
+    case ALLOC_TRT_CLEANUP:
+      /*ODCCP*///std::cout << "TRT ALLOCATED TO CLEANUP" << std::endl;
+      if(r_cleanup_fsm.read() != CLEANUP_IXR_REQ)
+      {
         if(r_read_fsm.read() == READ_TRT_LOCK)
           r_alloc_trt_fsm = ALLOC_TRT_READ;
@@ -7338,4 +8742,8 @@
                 (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;
@@ -7388,5 +8796,10 @@
         else if(r_config_fsm.read() == CONFIG_HEAP_REQ)
           r_alloc_heap_fsm = ALLOC_HEAP_CONFIG;
-      }
+
+        else
+          m_cpt_heap_unused++;
+      }
+      else
+        m_cpt_read_fsm_heap_used++;
       break;
 
@@ -7411,5 +8824,10 @@
         else if(r_read_fsm.read() == READ_HEAP_REQ)
           r_alloc_heap_fsm = ALLOC_HEAP_READ;
-      }
+
+        else
+          m_cpt_heap_unused++;
+      }
+      else
+        m_cpt_write_fsm_heap_used++;
       break;
 
@@ -7434,5 +8852,10 @@
         else if(r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)
           r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
-      }
+
+        else
+          m_cpt_heap_unused++;
+      }
+      else
+        m_cpt_cas_fsm_heap_used++;
       break;
 
@@ -7458,5 +8881,10 @@
         else if(r_cas_fsm.read() == CAS_UPT_HEAP_LOCK)
           r_alloc_heap_fsm = ALLOC_HEAP_CAS;
-      }
+
+        else
+          m_cpt_heap_unused++;
+      }
+      else
+        m_cpt_cleanup_fsm_heap_used++;
       break;
 
@@ -7503,5 +8931,10 @@
         if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
           r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
-      }
+
+        else
+          m_cpt_heap_unused++;
+      }
+      else
+        m_cpt_xram_rsp_fsm_heap_used++;
       break;
 
@@ -7563,7 +8996,25 @@
   ////////////////////////////////////////////////////////////////////////////////////
 
-  m_cc_receive_to_cleanup_fifo.update( cc_receive_to_cleanup_fifo_get,
-                                       cc_receive_to_cleanup_fifo_put, 
-                                       p_dspin_p2m.data.read() );
+  if(cc_receive_to_cleanup_fifo_put)
+  {
+    if(cc_receive_to_cleanup_fifo_get)
+    {
+      m_cc_receive_to_cleanup_fifo.put_and_get( ((uint64_t)(p_dspin_p2m.eop.read()&0x1) << 32) | p_dspin_p2m.data.read() );
+    }
+    else
+    {
+      m_cc_receive_to_cleanup_fifo.simple_put( ((uint64_t)(p_dspin_p2m.eop.read()&0x1) << 32) | p_dspin_p2m.data.read() );
+    }
+  }
+  else
+  {
+    if(cc_receive_to_cleanup_fifo_get)
+    {
+      m_cc_receive_to_cleanup_fifo.simple_get();
+    }
+  }
+  //m_cc_receive_to_cleanup_fifo.update( cc_receive_to_cleanup_fifo_get,
+  //                                     cc_receive_to_cleanup_fifo_put, 
+  //                                     p_dspin_p2m.data.read() );
 
   ////////////////////////////////////////////////////////////////////////////////////
@@ -7714,4 +9165,26 @@
     p_vci_ixr.trdid     = r_xram_rsp_to_ixr_cmd_trdid.read();
     p_vci_ixr.eop       = (r_ixr_cmd_cpt == (m_words-2));
+  } 
+  else if (r_ixr_cmd_fsm.read() == IXR_CMD_CLEANUP_DATA)
+  {
+    p_vci_ixr.cmd     = vci_param_ext::CMD_WRITE;
+    p_vci_ixr.cmdval  = true;
+    p_vci_ixr.address = (addr_t)((r_cleanup_to_ixr_cmd_nline.read() * m_words + r_ixr_cmd_cpt.read()) * 4);
+    if (r_cleanup_to_ixr_cmd_ncc_l1_dirty.read()) //if L1 was dirty, the correct data is in the cleanup
+    {
+      p_vci_ixr.wdata   = ((wide_data_t)(r_cleanup_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read()) | 
+          ((wide_data_t)(r_cleanup_to_ixr_cmd_data[r_ixr_cmd_cpt.read()+1].read()) << 32));
+      if(r_cleanup_to_ixr_cmd_nline.read() == 0x12bb)
+        std::cout << "IXR data dirty = " << std::hex << p_vci_ixr.wdata << std::dec << std::endl;
+    }
+    else //if L1 was not dirty, the data is in the L2
+    {
+      p_vci_ixr.wdata   = ((wide_data_t)(r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read()) | 
+          ((wide_data_t)(r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()+1].read()) << 32));
+      if(r_cleanup_to_ixr_cmd_nline.read() == 0x12bb)
+        std::cout << "IXR data not dirty = " << std::hex << p_vci_ixr.wdata << std::dec << std::endl;
+    }
+    p_vci_ixr.trdid   = r_cleanup_to_ixr_cmd_trdid.read();
+    p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words - 2));
   }
   else
@@ -7857,12 +9330,29 @@
 
     case TGT_RSP_CLEANUP:
+    {
+      uint32_t last_word_idx = r_cleanup_to_tgt_rsp_first_word.read() + r_cleanup_to_tgt_rsp_length - 1;
+      bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
+      bool     is_ll         = ((r_cleanup_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
+
       p_vci_tgt.rspval   = true;
-      p_vci_tgt.rdata    = 0;
+      if (is_ll and not r_tgt_rsp_key_sent.read())
+      {
+        p_vci_tgt.rdata   = r_cleanup_to_tgt_rsp_ll_key.read();
+      }
+      else if (!r_cleanup_to_tgt_rsp_type.read())
+      {
+        p_vci_tgt.rdata    = r_cleanup_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
+      }
+      else  //if the CLEANUP fsm sends a SC_RSP, then it is a success (and it caused an inval)
+      {
+        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;
+      p_vci_tgt.reop     = r_cleanup_to_tgt_rsp_type.read() or (is_last_word and not is_ll) or (r_tgt_rsp_key_sent.read() and is_ll);
+      break;
+    }
 
     case TGT_RSP_CAS:
@@ -7885,9 +9375,11 @@
       p_vci_tgt.rspval  = true;
 
-      if( is_ll and not r_tgt_rsp_key_sent.read() ) {
+      if( is_ll and not r_tgt_rsp_key_sent.read() ) 
+      {
         // LL response first flit
         p_vci_tgt.rdata = r_xram_rsp_to_tgt_rsp_ll_key.read();
       }
-      else {
+      else 
+      {
         // LL response second flit or READ response
         p_vci_tgt.rdata = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
@@ -7900,4 +9392,5 @@
       p_vci_tgt.reop    = (((is_last_word or is_error) and not is_ll) or
                             (r_tgt_rsp_key_sent.read() and     is_ll));
+
       break;
     }
@@ -8081,4 +9574,105 @@
     }
     /////////////////////////////////
+
+  case CC_SEND_READ_NCC_INVAL_HEADER:
+    {
+      uint64_t flit = 0;
+
+      uint8_t multi_inval_type;
+      if (r_read_to_cc_send_inst.read())
+      {
+        multi_inval_type = DspinDhccpParam::TYPE_MULTI_INVAL_INST;
+      }
+      else
+      {
+        multi_inval_type = DspinDhccpParam::TYPE_MULTI_INVAL_DATA;
+      }
+
+      DspinDhccpParam::dspin_set(
+          flit,
+          r_read_to_cc_send_dest.read(),
+          DspinDhccpParam::MULTI_INVAL_DEST);
+
+      DspinDhccpParam::dspin_set(
+          flit,
+          m_cc_global_id,
+          DspinDhccpParam::MULTI_INVAL_SRCID);
+
+      DspinDhccpParam::dspin_set(
+          flit,
+          DspinDhccpParam::TYPE_MULTI_INVAL_DATA,
+          DspinDhccpParam::M2P_TYPE);
+
+      p_dspin_m2p.write = true;
+      p_dspin_m2p.data  = flit;
+
+      break;
+
+    }
+
+
+    case CC_SEND_READ_NCC_INVAL_NLINE:
+    {
+      uint64_t flit = 0;
+
+      DspinDhccpParam::dspin_set(
+          flit,
+          r_read_to_cc_send_nline.read(),
+          DspinDhccpParam::MULTI_INVAL_NLINE);
+
+
+      p_dspin_m2p.write = true;
+      p_dspin_m2p.data  = flit;
+      p_dspin_m2p.eop   = true;
+
+      break;
+
+    }
+
+    case CC_SEND_WRITE_NCC_INVAL_HEADER:
+    {
+      uint64_t flit = 0;
+
+      DspinDhccpParam::dspin_set(
+          flit,
+          r_write_to_cc_send_dest.read(),
+          DspinDhccpParam::MULTI_INVAL_DEST);
+
+      DspinDhccpParam::dspin_set(
+          flit,
+          m_cc_global_id,
+          DspinDhccpParam::MULTI_INVAL_SRCID);
+
+      DspinDhccpParam::dspin_set(
+          flit,
+          DspinDhccpParam::TYPE_MULTI_INVAL_DATA,
+          DspinDhccpParam::M2P_TYPE);
+
+      p_dspin_m2p.write = true;
+      p_dspin_m2p.data  = flit;
+
+      break;
+
+    }
+
+    case CC_SEND_WRITE_NCC_INVAL_NLINE:
+    {
+      uint64_t flit = 0;
+
+      DspinDhccpParam::dspin_set(
+          flit,
+          r_write_to_cc_send_nline.read(),
+          DspinDhccpParam::MULTI_INVAL_NLINE);
+
+
+      p_dspin_m2p.write = true;
+      p_dspin_m2p.data  = flit;
+      p_dspin_m2p.eop   = true;
+
+      break;
+
+    }
+
+
     case CC_SEND_WRITE_BRDCAST_NLINE:
     {
