Index: branches/ODCCP/modules/vci_cc_vcache_wrapper/caba/source/include/vci_cc_vcache_wrapper.h
===================================================================
--- branches/ODCCP/modules/vci_cc_vcache_wrapper/caba/source/include/vci_cc_vcache_wrapper.h	(revision 460)
+++ branches/ODCCP/modules/vci_cc_vcache_wrapper/caba/source/include/vci_cc_vcache_wrapper.h	(revision 479)
@@ -89,8 +89,6 @@
         // handling coherence requests
         ICACHE_CC_CHECK,
+        ICACHE_CC_UPDT,
         ICACHE_CC_INVAL,
-        ICACHE_CC_UPDT,
-        ICACHE_CC_BROADCAST,
-        ICACHE_CC_SEND_WAIT,
     };
 
@@ -141,9 +139,7 @@
         // handling coherence requests
         DCACHE_CC_CHECK,
+        DCACHE_CC_UPDT,
+        DCACHE_CC_INVAL,
         DCACHE_CC_INVAL_DATA,
-        DCACHE_CC_INVAL,
-        DCACHE_CC_UPDT,
-        DCACHE_CC_BROADCAST,
-        DCACHE_CC_SEND_WAIT,
         // handling TLB inval (after a coherence or XTN request)
         DCACHE_INVAL_TLB_SCAN,
@@ -177,12 +173,16 @@
     {
         CC_RECEIVE_IDLE,
-        CC_RECEIVE_CLACK,
         CC_RECEIVE_BRDCAST_HEADER,
         CC_RECEIVE_BRDCAST_NLINE,
-        CC_RECEIVE_INVAL_HEADER,
-        CC_RECEIVE_INVAL_NLINE,
-        CC_RECEIVE_UPDT_HEADER,
-        CC_RECEIVE_UPDT_NLINE,
-        CC_RECEIVE_UPDT_DATA,
+        CC_RECEIVE_INS_INVAL_HEADER,
+        CC_RECEIVE_INS_INVAL_NLINE,
+        CC_RECEIVE_INS_UPDT_HEADER,
+        CC_RECEIVE_INS_UPDT_NLINE,
+        CC_RECEIVE_INS_UPDT_DATA,
+        CC_RECEIVE_DATA_INVAL_HEADER,
+        CC_RECEIVE_DATA_INVAL_NLINE,
+        CC_RECEIVE_DATA_UPDT_HEADER,
+        CC_RECEIVE_DATA_UPDT_NLINE,
+        CC_RECEIVE_DATA_UPDT_DATA,
     };
 
@@ -301,10 +301,11 @@
 
 public:
-    sc_in<bool>                                 p_clk;
-    sc_in<bool>                                 p_resetn;
-    sc_in<bool>                                 p_irq[iss_t::n_irq];
-    soclib::caba::VciInitiator<vci_param>       p_vci;
-    soclib::caba::DspinInput <dspin_in_width>   p_dspin_in;
-    soclib::caba::DspinOutput<dspin_out_width>  p_dspin_out;
+    sc_in<bool>                                p_clk;
+    sc_in<bool>                                p_resetn;
+    sc_in<bool>                                p_irq[iss_t::n_irq];
+    soclib::caba::VciInitiator<vci_param>      p_vci;
+    soclib::caba::DspinInput<dspin_in_width>   p_dspin_m2p;
+    soclib::caba::DspinOutput<dspin_out_width> p_dspin_p2m;
+    soclib::caba::DspinInput<dspin_in_width>   p_dspin_clack;
 
 private:
@@ -387,4 +388,9 @@
     sc_signal<bool>         r_icache_cc_need_write;     // activate the cache for writing
 
+    // coherence clack handling
+    sc_signal<bool>         r_icache_clack_req;         // clack request
+    sc_signal<size_t>       r_icache_clack_way;		    // clack way
+    sc_signal<size_t>       r_icache_clack_set;		    // clack set
+
     // icache flush handling
     sc_signal<size_t>       r_icache_flush_count;	    // slot counter used for cache flush
@@ -459,4 +465,9 @@
     sc_signal<size_t>       r_dcache_cc_word;		    // word counter for cc update
     sc_signal<bool>         r_dcache_cc_need_write;     // activate the cache for writing
+
+    // coherence clack handling
+    sc_signal<bool>         r_dcache_clack_req;         // clack request
+    sc_signal<size_t>       r_dcache_clack_way;		    // clack way
+    sc_signal<size_t>       r_dcache_clack_set;		    // clack set
 
     // dcache flush handling
@@ -586,4 +597,10 @@
     sc_signal<paddr_t>      r_cc_receive_dcache_nline;	    // cache line physical address
 
+    ///////////////////////////////////
+    //  DSPIN CLACK INTERFACE REGISTER
+    ///////////////////////////////////
+    sc_signal<bool>         r_dspin_clack_req;
+    sc_signal<uint64_t>     r_dspin_clack_flit;
+    
     //////////////////////////////////////////////////////////////////
     // processor, write buffer, caches , TLBs
Index: branches/ODCCP/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp
===================================================================
--- branches/ODCCP/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp	(revision 460)
+++ branches/ODCCP/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp	(revision 479)
@@ -65,8 +65,6 @@
 
         "ICACHE_CC_CHECK",
+        "ICACHE_CC_UPDT",
         "ICACHE_CC_INVAL",
-        "ICACHE_CC_UPDT",
-        "ICACHE_CC_BROADCAST",
-        "ICACHE_CC_SEND_WAIT",
     };
 
@@ -116,9 +114,7 @@
 
         "DCACHE_CC_CHECK",
+        "DCACHE_CC_UPDT",
+        "DCACHE_CC_INVAL",
         "DCACHE_CC_INVAL_DATA",
-        "DCACHE_CC_INVAL",
-        "DCACHE_CC_UPDT",
-        "DCACHE_CC_BROADCAST",
-        "DCACHE_CC_SEND_WAIT",
 
         "DCACHE_INVAL_TLB_SCAN",
@@ -167,12 +163,16 @@
 const char *cc_receive_fsm_state_str[] = {
         "CC_RECEIVE_IDLE",
-        "CC_RECEIVE_CLACK",
         "CC_RECEIVE_BRDCAST_HEADER",
         "CC_RECEIVE_BRDCAST_NLINE",
-        "CC_RECEIVE_INVAL_HEADER",
-        "CC_RECEIVE_INVAL_NLINE",
-        "CC_RECEIVE_UPDT_HEADER",
-        "CC_RECEIVE_UPDT_NLINE",
-        "CC_RECEIVE_UPDT_DATA",
+        "CC_RECEIVE_INS_INVAL_HEADER",
+        "CC_RECEIVE_INS_INVAL_NLINE",
+        "CC_RECEIVE_INS_UPDT_HEADER",
+        "CC_RECEIVE_INS_UPDT_NLINE",
+        "CC_RECEIVE_INS_UPDT_DATA",
+        "CC_RECEIVE_DATA_INVAL_HEADER",
+        "CC_RECEIVE_DATA_INVAL_NLINE",
+        "CC_RECEIVE_DATA_UPDT_HEADER",
+        "CC_RECEIVE_DATA_UPDT_NLINE",
+        "CC_RECEIVE_DATA_UPDT_DATA",
     };
 
@@ -224,6 +224,7 @@
       p_resetn("p_resetn"),
       p_vci("p_vci"),
-      p_dspin_in("p_dspin_in"),
-      p_dspin_out("p_dspin_out"),
+      p_dspin_m2p("p_dspin_m2p"),
+      p_dspin_p2m("p_dspin_p2m"),
+      p_dspin_clack("p_dspin_clack"),
 
       m_cacheability_table( mtd.getCacheabilityTable() ),
@@ -792,4 +793,6 @@
         r_icache_cc_send_req       = false;
 
+        r_icache_clack_req         = false;
+
         // No pending write in pipeline
         r_dcache_wbuf_req          = false;
@@ -812,4 +815,6 @@
         r_dcache_cc_send_req       = false;
 
+        r_dcache_clack_req         = false;
+
         // No request from CC_RECEIVE FSM to ICACHE/DCACHE FSMs
         r_cc_receive_icache_req    = false;
@@ -826,4 +831,6 @@
         r_icache_miss_inval        = false;
         r_dcache_miss_inval        = false;
+
+        r_dspin_clack_req          = false;
 
         // No signalisation  of errors
@@ -1077,4 +1084,12 @@
                         // 5/ uncacheable read miss                     => ICACHE_UNC_REQ
     {
+        // coherence clack interrupt
+        if ( r_icache_clack_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
+            r_icache_fsm_save = r_icache_fsm.read();
+            break;
+        }
+
         // coherence interrupt
         if ( r_cc_receive_icache_req.read())
@@ -1306,4 +1321,12 @@
                             // external coherence request are accepted in this state.
     {
+        // coherence clack interrupt
+        if ( r_icache_clack_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
+            r_icache_fsm_save = r_icache_fsm.read();
+            break;
+        }
+
         // coherence interrupt
         if ( r_cc_receive_icache_req.read() )
@@ -1350,4 +1373,12 @@
                        		        // A cleanup request is generated for each valid line
     {
+        // coherence clack interrupt
+        if ( r_icache_clack_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
+            r_icache_fsm_save = r_icache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_icache_req.read() )
@@ -1548,4 +1579,12 @@
     {
         if (m_ireq.valid) m_cost_ins_miss_frz++;
+
+        // coherence clack interrupt
+        if ( r_icache_clack_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
+            r_icache_fsm_save = r_icache_fsm.read();
+            break;
+        }
 
         // coherence interrupt
@@ -1638,4 +1677,12 @@
         if (m_ireq.valid) m_cost_ins_miss_frz++;
 
+        // coherence clack interrupt
+        if ( r_icache_clack_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
+            r_icache_fsm_save = r_icache_fsm.read();
+            break;
+        }
+
         // coherence interrupt
         if ( r_cc_receive_icache_req.read() )
@@ -1709,4 +1756,12 @@
         if ( m_ireq.valid ) m_cost_ins_miss_frz++;
 
+        // coherence clack interrupt
+        if ( r_icache_clack_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
+            r_icache_fsm_save = r_icache_fsm.read();
+            break;
+        }
+
         // coherence interrupt
         if ( r_cc_receive_icache_req.read() )
@@ -1780,4 +1835,12 @@
     case ICACHE_UNC_WAIT:	// waiting a response to an uncacheable read from VCI_RSP FSM
     {
+        // coherence clack interrupt
+        if ( r_icache_clack_req.read() )
+        {
+            r_icache_fsm = ICACHE_CC_CHECK;
+            r_icache_fsm_save = r_icache_fsm.read();
+            break;
+        }
+
         // coherence interrupt
         if ( r_cc_receive_icache_req.read() )
@@ -1820,41 +1883,13 @@
         paddr_t  mask  = ~((m_icache_words<<2)-1);
 
-        if (r_cc_receive_icache_type.read() == CC_TYPE_CLACK)
-                           	// We switch the directory slot to EMPTY state
-                            // and reset r_icache_miss_clack if the cleanup ack
-                            // is matching a pending miss
-        {
-
-            if ( m_ireq.valid ) m_cost_ins_miss_frz++;
-
-#ifdef INSTRUMENTATION
-m_cpt_icache_dir_write++;
-#endif
-            r_icache.write_dir( 0,
-                                r_cc_receive_icache_way.read(),
-                                r_cc_receive_icache_set.read(),
-                                CACHE_SLOT_STATE_EMPTY);
-
-            if ( (r_icache_miss_set.read() == r_cc_receive_icache_set.read()) and
-                 (r_icache_miss_way.read() == r_cc_receive_icache_way.read()) )
-                    r_icache_miss_clack = false;
-
-            r_icache_fsm = r_icache_fsm_save.read() ;
-            r_cc_receive_icache_req = false;
-
-#if DEBUG_ICACHE
-if ( m_debug_activated )
-{
-    std::cout << "  <PROC " << name()
-    << " ICACHE_CC_CHECK>  CC_TYPE_CLACK slot returns to empty state"
-    << " set = " << r_cc_receive_icache_set.read()
-    << " / way = " << r_cc_receive_icache_way.read() << std::endl;
-}
-#endif
-        }
-        else if( ((r_icache_fsm_save.read() == ICACHE_MISS_SELECT) or
-                 (r_icache_fsm_save.read() == ICACHE_MISS_WAIT) or
-                 (r_icache_fsm_save.read() == ICACHE_MISS_DIR_UPDT)) and
-                 ((r_icache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching
+
+        // Match between MISS address and CC address
+        // note: In the same cycle we can handle a CLACK and a MISS match
+        // because the CLACK access the directory but the MISS match dont.
+        if (r_cc_receive_icache_req.read() and
+          ((r_icache_fsm_save.read() == ICACHE_MISS_SELECT  )  or
+           (r_icache_fsm_save.read() == ICACHE_MISS_WAIT    )  or
+           (r_icache_fsm_save.read() == ICACHE_MISS_DIR_UPDT)) and
+          ((r_icache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching
         {
             // signaling the matching
@@ -1867,4 +1902,5 @@
                 r_icache_fsm        = ICACHE_CC_UPDT;
                 r_icache_cc_word    = r_cc_receive_word_idx.read();
+
                 // just pop the fifo , don't write in icache
                 r_icache_cc_need_write = false;
@@ -1885,63 +1921,33 @@
 #endif
         }
-        else  								                            // no match
-        {
-            int	        state = 0;
-            size_t 	    way = 0;
-            size_t 	    set = 0;
-            size_t 	    word = 0;
+
+        // CLACK handler
+        // We switch the directory slot to EMPTY state
+        // and reset r_icache_miss_clack if the cleanup ack
+        // is matching a pending miss.
+        if ( r_icache_clack_req.read() )
+        {
+
+            if ( m_ireq.valid ) m_cost_ins_miss_frz++;
 
 #ifdef INSTRUMENTATION
-m_cpt_icache_dir_read++;
-#endif
-            r_icache.read_dir(paddr,
-                              &state,
-                              &way,
-                              &set,
-                              &word);
-
-            r_icache_cc_way = way;
-            r_icache_cc_set = set;
-
-            if ( state == CACHE_SLOT_STATE_VALID_CC)            // hit
-            {
-                // need to update the cache state
-                r_icache_cc_need_write = true;
-                if (r_cc_receive_icache_type.read() == CC_TYPE_UPDT)  // hit update
-                {
-                    r_icache_fsm          = ICACHE_CC_UPDT;
-                    r_icache_cc_word      = r_cc_receive_word_idx.read();
-                }
-                else if (r_cc_receive_icache_type.read() == CC_TYPE_INVAL)   // hit inval
-                {
-                    r_icache_fsm          = ICACHE_CC_INVAL;
-                }
-                else if (r_cc_receive_icache_type.read() == CC_TYPE_BRDCAST)  // hit broadcast
-                {
-                    r_icache_fsm          = ICACHE_CC_BROADCAST;
-                }
-            }
-            else                                      // miss
-            {
-                // multicast acknowledgement required in case of update
-                if(r_cc_receive_icache_type.read() == CC_TYPE_UPDT)
-                {
-                    r_icache_fsm          = ICACHE_CC_UPDT;
-                    r_icache_cc_word      = r_cc_receive_word_idx.read();
-                    // just pop the fifo , don't write in icache
-                    r_icache_cc_need_write = false;
-                }
-                else // No response needed
-                {
-                    r_cc_receive_icache_req = false;
-                    r_icache_fsm          = r_icache_fsm_save.read();
-                }
-            }
-        }
-        break;
-    }
-    /////////////////////
-    case ICACHE_CC_INVAL:  	// hit inval : switch slot to EMPTY state
-    {
+m_cpt_icache_dir_write++;
+#endif
+            r_icache.write_dir( 0,
+                                r_icache_clack_way.read(),
+                                r_icache_clack_set.read(),
+                                CACHE_SLOT_STATE_EMPTY);
+
+            if ( (r_icache_miss_set.read() == r_icache_clack_set.read()) and
+                 (r_icache_miss_way.read() == r_icache_clack_way.read()) )
+            {
+                r_icache_miss_clack = false;
+            }
+
+            r_icache_clack_req = false;
+
+            // return to cc_save state if no pending CC request
+            if ( not r_cc_receive_icache_req.read() )
+                r_icache_fsm = r_icache_fsm_save.read();
 
 #if DEBUG_ICACHE
@@ -1949,38 +1955,105 @@
 {
     std::cout << "  <PROC " << name()
-              << " ICACHE_//CC_INVAL> slot returns to empty state"
-              << " set = " << r_icache_cc_set.read()
-              << " / way = " << r_icache_cc_way.read() << std::endl;
+        << " ICACHE_CC_CHECK>  CC_TYPE_CLACK slot returns to empty state"
+        << " set = " << r_icache_clack_set.read()
+        << " / way = " << r_icache_clack_way.read() << std::endl;
 }
 #endif
+
+            break;
+        }
+
+        // wait if pending request to CC_SEND. This way if there are pending
+        // CLACK they can be treated in this state and then a deadlock
+        // situation is avoided
+        if ( r_icache_cc_send_req.read() ) break;
+
+        // CC request handler
+
+        int	        state = 0;
+        size_t 	    way = 0;
+        size_t 	    set = 0;
+        size_t 	    word = 0;
 
 #ifdef INSTRUMENTATION
 m_cpt_icache_dir_read++;
 #endif
-
-            if (r_icache_cc_need_write.read())
-            {
-                r_icache.write_dir( 0,
-                        r_icache_cc_way.read(),
-                        r_icache_cc_set.read(),
-                        CACHE_SLOT_STATE_EMPTY );
-                // no need to write in the cache anymore
+        r_icache.read_dir(paddr,
+                          &state,
+                          &way,
+                          &set,
+                          &word);
+
+        r_icache_cc_way = way;
+        r_icache_cc_set = set;
+
+        if ( state == CACHE_SLOT_STATE_VALID_CC)            // hit
+        {
+            // need to update the cache state
+            if (r_cc_receive_icache_type.read() == CC_TYPE_UPDT)  // hit update
+            {
+                r_icache_cc_need_write = true;
+                r_icache_fsm           = ICACHE_CC_UPDT;
+                r_icache_cc_word       = r_cc_receive_word_idx.read();
+            }
+            else if ( r_cc_receive_icache_type.read() == CC_TYPE_INVAL ) // hit inval
+            {
+                r_icache_fsm           = ICACHE_CC_INVAL;
+            }
+        }
+        else                                      // miss
+        {
+            // multicast acknowledgement required in case of update
+            if(r_cc_receive_icache_type.read() == CC_TYPE_UPDT)
+            {
+                r_icache_fsm           = ICACHE_CC_UPDT;
+                r_icache_cc_word       = r_cc_receive_word_idx.read();
+
+                // just pop the fifo , don't write in icache
                 r_icache_cc_need_write = false;
             }
-        // multicast acknowledgement
-        // send a request to cc_send_fsm
-        if(not r_icache_cc_send_req.read()) // cc_send is available
-        {
-            // coherence request completed
-            r_cc_receive_icache_req = false;
-            // request multicast acknowledgement
-            r_icache_cc_send_req = true;
-            r_icache_cc_send_nline = r_cc_receive_icache_nline.read();
-            r_icache_cc_send_updt_tab_idx = r_cc_receive_icache_updt_tab_idx.read();
-            r_icache_cc_send_type = CC_TYPE_MULTI_ACK;
-
-            r_icache_fsm          = r_icache_fsm_save.read();
-        }
-        //else wait for previous cc_send request to be sent
+            else // No response needed
+            {
+                r_cc_receive_icache_req = false;
+                r_icache_fsm            = r_icache_fsm_save.read();
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_CC_INVAL:  	// hit inval : switch slot to ZOMBI state
+    {
+        assert (not r_icache_cc_send_req.read() &&
+                "ERROR in ICACHE_CC_INVAL: the r_icache_cc_send_req "
+                "must not be set");
+
+#ifdef INSTRUMENTATION
+m_cpt_icache_dir_read++;
+#endif
+
+        // Switch slot state to ZOMBI and send CLEANUP command 
+        r_icache.write_dir( 0,
+                            r_icache_cc_way.read(),
+                            r_icache_cc_set.read(),
+                            CACHE_SLOT_STATE_ZOMBI );
+
+        // coherence request completed
+        r_icache_cc_send_req   = true;
+        r_icache_cc_send_nline = r_cc_receive_icache_nline.read();
+        r_icache_cc_send_way   = r_icache_cc_way.read();
+        r_icache_cc_send_type  = CC_TYPE_CLEANUP;
+
+        r_icache_fsm           = r_icache_fsm_save.read();
+
+#if DEBUG_ICACHE
+if ( m_debug_activated )
+{
+std::cout << "  <PROC " << name()
+          << " ICACHE_CC_INVAL> slot returns to ZOMBI state"
+          << " set = " << r_icache_cc_set.read()
+          << " / way = " << r_icache_cc_way.read() << std::endl;
+}
+#endif
+
         break;
     }
@@ -1988,4 +2061,28 @@
     case ICACHE_CC_UPDT:	// hit update : write one word per cycle
     {
+        assert (not r_icache_cc_send_req.read() &&
+                "ERROR in ICACHE_CC_UPDT: the r_icache_cc_send_req "
+                "must not be set");
+
+        if ( not r_cc_receive_updt_fifo_be.rok() ) break;
+
+
+        size_t  word  = r_icache_cc_word.read();
+        size_t  way   = r_icache_cc_way.read();
+        size_t  set   = r_icache_cc_set.read();
+
+        if (r_icache_cc_need_write.read())
+        {
+            r_icache.write( way,
+                            set,
+                            word,
+                            r_cc_receive_updt_fifo_data.read(),
+                            r_cc_receive_updt_fifo_be.read() );
+
+            r_icache_cc_word = word+1;
+
+#ifdef INSTRUMENTATION
+m_cpt_icache_data_write++;
+#endif
 
 #if DEBUG_ICACHE
@@ -1999,96 +2096,28 @@
 }
 #endif
-
-#ifdef INSTRUMENTATION
-m_cpt_icache_data_write++;
-#endif
-        size_t  word  = r_icache_cc_word.read();
-        size_t  way   = r_icache_cc_way.read();
-        size_t  set   = r_icache_cc_set.read();
-
-        if (r_cc_receive_updt_fifo_be.rok())
-        {
-            if (r_icache_cc_need_write.read())
-            {
-                r_icache.write( way,
-                                set,
-                                word,
-                                r_cc_receive_updt_fifo_data.read(),
-                                r_cc_receive_updt_fifo_be.read() );
-
-                r_icache_cc_word = word+1;
-            }
-            if ( r_cc_receive_updt_fifo_eop.read() )	// last word
-            {
+        }
+
+        if ( r_cc_receive_updt_fifo_eop.read() )	// last word
+        {
                 // no need to write in the cache anymore
-                r_icache_cc_need_write = false;
-                // wait to send a request to cc_send_fsm
-                if(not r_icache_cc_send_req.read()) // cc_send is available
-                {
-                    //consume last flit
-                    cc_receive_updt_fifo_get  = true;
-                    // coherence request completed
-                    r_cc_receive_icache_req = false;
-                    // request multicast acknowledgement
-                    r_icache_cc_send_req = true;
-                    r_icache_cc_send_nline = r_cc_receive_icache_nline.read();
-                    r_icache_cc_send_updt_tab_idx = r_cc_receive_icache_updt_tab_idx.read();
-                    r_icache_cc_send_type = CC_TYPE_MULTI_ACK;
-
-                    r_icache_fsm          = r_icache_fsm_save.read();
-                }
-            }
-            else
-            {
-                //consume fifo if not eop
-                cc_receive_updt_fifo_get  = true;
-            }
-        }
+            r_icache_cc_need_write        = false;
+
+            // coherence request completed
+            r_cc_receive_icache_req       = false;
+
+            // request multicast acknowledgement
+            r_icache_cc_send_req          = true;
+            r_icache_cc_send_nline        = r_cc_receive_icache_nline.read();
+            r_icache_cc_send_updt_tab_idx = r_cc_receive_icache_updt_tab_idx.read();
+            r_icache_cc_send_type         = CC_TYPE_MULTI_ACK;
+
+            r_icache_fsm                  = r_icache_fsm_save.read();
+        }
+        //consume fifo if not eop
+        cc_receive_updt_fifo_get  = true;
+
         break;
     }
-    /////////////////////////
-    case ICACHE_CC_BROADCAST:  // hit broadcast : switch slot to ZOMBI state
-                               // and request a cleanup
-    {
-
-#if DEBUG_ICACHE
-if ( m_debug_activated )
-{
-    std::cout << "  <PROC " << name()
-              << " ICACHE_CC_BROADCAST > Slot goes to zombi state "
-              << " set = " << r_icache_cc_set.read()
-              << " / way = " << r_icache_cc_way.read() << std::endl;
-}
-#endif
-
-#ifdef INSTRUMENTATION
-m_cpt_icache_dir_write++;
-#endif
-       if (r_icache_cc_need_write.read())
-       {
-            r_icache.write_dir( r_icache_cc_way.read(),
-                                r_icache_cc_set.read(),
-                                CACHE_SLOT_STATE_ZOMBI );
-                // no need to write in the cache anymore
-            r_icache_cc_need_write = false;
-        }
-
-        // cleanup
-        // send a request to cc_send_fsm
-        if(not r_icache_cc_send_req.read()) // cc_send is available
-        {
-            // coherence request completed
-            r_cc_receive_icache_req = false;
-            // request cleanup
-            r_icache_cc_send_req = true;
-            r_icache_cc_send_nline = r_cc_receive_icache_nline.read();
-            r_icache_cc_send_way   = r_icache_cc_way.read();
-            r_icache_cc_send_type  = CC_TYPE_CLEANUP;
-
-            r_icache_fsm          = r_icache_fsm_save.read();
-        }
-        //else wait for previous cc_send request to be sent
-        break;
-    }
+
     } // end switch r_icache_fsm
 
@@ -2371,4 +2400,10 @@
         }
 
+        // coherence clack request (from DSPIN CLACK)
+        else if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+        }
         // coherence request (from CC_RECEIVE FSM)
         else if ( r_cc_receive_dcache_req.read() )
@@ -3067,4 +3102,12 @@
     case DCACHE_TLB_PTE1_GET:	// try to read a PT1 entry in dcache
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -3366,4 +3409,12 @@
     case DCACHE_TLB_PTE2_GET:	// Try to get a PTE2 (64 bits) in the dcache
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -3665,4 +3716,12 @@
 
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -3736,4 +3795,12 @@
                                 // as there is a risk of dead-lock
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -3741,4 +3808,5 @@
             r_dcache_fsm = DCACHE_CC_CHECK;
             r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
         }
 
@@ -3757,4 +3825,12 @@
                                     // and because it can exist a simultaneous ITLB miss
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -3792,4 +3868,12 @@
                                 // returns to IDLE and flush TLBs when last slot
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -3895,5 +3979,4 @@
             r_dcache_xtn_flush_addr_data = r_dcache_xtn_flush_addr_data.read() + 4;
 
-            cleanup_data_updt_fifo_dcache_get   = false;
             cleanup_data_updt_fifo_dcache_put   = true;
             cleanup_data_updt_fifo_dcache_data  = rdata;
@@ -4158,5 +4241,4 @@
             r_dcache_xtn_data_addr = r_dcache_xtn_data_addr.read() + 4;
 
-            cleanup_data_updt_fifo_dcache_get   = false;
             cleanup_data_updt_fifo_dcache_put   = true;
             cleanup_data_updt_fifo_dcache_data  = rdata;
@@ -4193,4 +4275,12 @@
     {
         if ( m_dreq.valid) m_cost_data_miss_frz++;
+
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
 
         // coherence request (from CC_RECEIVE FSM)
@@ -4247,5 +4337,5 @@
                             r_dcache_fsm = DCACHE_MISS_DATA;
                             m_cpt_data_cleanup_dirty ++;
-                            
+
                             /*STATS DIRTY*/
                             for (size_t w = 0; w < m_dcache_words; w++)
@@ -4294,5 +4384,4 @@
         size_t set;
         size_t word;
-
         r_dcache.read_neutral(r_dcache_miss_data_addr,
                               &rdata,
@@ -4300,9 +4389,9 @@
                               &set,
                               &word);
+
         if(r_cc_send_data_fifo.wok())
         {
             r_dcache_miss_data_addr = r_dcache_miss_data_addr.read() + 4;
 
-            cleanup_data_updt_fifo_dcache_get   = false;
             cleanup_data_updt_fifo_dcache_put   = true;
             cleanup_data_updt_fifo_dcache_data  = rdata;
@@ -4314,4 +4403,14 @@
                 r_dcache_fsm = DCACHE_MISS_CLEAN;
             }
+#if DEBUG_DCACHE
+if ( m_debug_activated )
+{
+    std::cout << "  <PROC " << name()
+              << " DCACHE_MISS_DATA>:" << std::hex
+              << " / DATA  = "   << rdata
+              << " / WORD  = "   << word
+              << " / PADDR = " << std::hex << r_dcache_miss_data_addr.read() << std::endl;
+}
+#endif
         }
         break;
@@ -4370,4 +4469,12 @@
     {
         if ( m_dreq.valid) m_cost_data_miss_frz++;
+
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
 
         // coherence request (from CC_RECEIVE FSM)
@@ -4486,4 +4593,12 @@
         if ( m_dreq.valid) m_cost_data_miss_frz++;
 
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -4592,4 +4707,12 @@
     case DCACHE_UNC_WAIT:  // waiting a response to an uncacheable read
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -4629,4 +4752,12 @@
     case DCACHE_LL_WAIT:    // waiting VCI response to a LL transaction
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -4675,4 +4806,12 @@
     case DCACHE_SC_WAIT:	// waiting VCI response to a SC transaction
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -4714,5 +4853,5 @@
         size_t   way;
         size_t   set;
-        size_t   word;	// unused
+        size_t   word; // unused
         int      state;
 
@@ -4767,4 +4906,12 @@
                                     // - if the CAS is a failure, we just retry the write.
     {
+        // coherence clack request (from DSPIN CLACK)
+        if ( r_dcache_clack_req.read() )
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_cc_save = r_dcache_fsm.read();
+            break;
+        }
+
         // coherence request (from CC_RECEIVE FSM)
         if ( r_cc_receive_dcache_req.read() )
@@ -4775,5 +4922,5 @@
         }
 
-        if ( r_vci_rsp_data_error.read() )	// bus error
+        if ( r_vci_rsp_data_error.read() )      // bus error
         {
             std::cout << "BUS ERROR in DCACHE_DIRTY_WAIT state" << std::endl;
@@ -4781,5 +4928,5 @@
             exit(0);
         }
-        else if ( r_vci_rsp_fifo_dcache.rok() )	// response available
+        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
         {
             vci_rsp_fifo_dcache_get = true;
@@ -4825,47 +4972,13 @@
 #endif
 
-        if (r_cc_receive_dcache_type.read() == CC_TYPE_CLACK)
-                            // We switch the directory slot to EMPTY state
-                            // and reset r_icache_miss_clack if the cleanup ack
-                            // is matching a pending miss.
-        {
-
-            if ( m_dreq.valid ) m_cost_data_miss_frz++;
-
-#ifdef INSTRUMENTATION
-m_cpt_dcache_dir_write++;
-#endif
-            r_dcache.write_dir( 0,
-                                r_cc_receive_dcache_way.read(),
-                                r_cc_receive_dcache_set.read(),
-                                CACHE_SLOT_STATE_EMPTY);
-            
-            /*STATS DIRTY*/
-            for (size_t word = 0; word < m_dcache_words; word++)
-            {
-                dirty_stats[(r_cc_receive_dcache_way * m_dcache_sets + r_cc_receive_dcache_set) * m_dcache_words + word] = false;
-            }
-
-            
-            if ( (r_dcache_miss_set.read() == r_cc_receive_dcache_set.read()) and
-                 (r_dcache_miss_way.read() == r_cc_receive_dcache_way.read()) )
-                  r_dcache_miss_clack = false;
-
-            r_dcache_fsm = r_dcache_fsm_cc_save.read() ;
-            r_cc_receive_dcache_req = false;
-#if DEBUG_DCACHE
-if ( m_debug_activated )
-{
-    std::cout << "  <PROC " << name()
-              << " DCACHE_CC_CHECK> CC_TYPE_CLACK Switch slot to EMPTY state"
-              << " set = " << r_cc_receive_dcache_set.read()
-              << " / way = " << r_cc_receive_dcache_way.read() << std::endl;
-}
-#endif
-        }
-        else if( ((r_dcache_fsm_cc_save == DCACHE_MISS_SELECT) or
-                  (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) or
-                  (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT)) and
-                  ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching
+        
+        // Match between MISS address and CC address
+        // note: In the same cycle we can handle a CLACK and a MISS match
+        // because the CLACK access the directory but the MISS match dont.
+        if (r_cc_receive_dcache_req.read() and 
+          ((r_dcache_fsm_cc_save == DCACHE_MISS_SELECT  )  or
+           (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT    )  or
+           (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT)) and
+          ((r_dcache_vci_paddr.read() & mask) == (paddr & mask))) // matching
         {
             // signaling matching
@@ -4878,4 +4991,5 @@
                 r_dcache_fsm        = DCACHE_CC_UPDT;
                 r_dcache_cc_word    = r_cc_receive_word_idx.read();
+
                 // just pop the fifo , don't write in icache
                 r_dcache_cc_need_write = false;
@@ -4885,5 +4999,5 @@
             {
                 r_cc_receive_dcache_req = false;
-                r_dcache_fsm          = r_dcache_fsm_cc_save.read();
+                r_dcache_fsm            = r_dcache_fsm_cc_save.read();
             }
 
@@ -4896,79 +5010,125 @@
 }
 #endif
-
-        }
-        else                                                    // no match
-	    {
-            int        state = 0;
-            size_t 	   way = 0;
-            size_t 	   set = 0;
-            size_t	   word = 0;
+        }
+
+        // CLACK handler
+        // We switch the directory slot to EMPTY state and reset
+        // r_dcache_miss_clack if the cleanup ack is matching a pending miss.
+        if ( r_dcache_clack_req.read() )
+        {
+            if ( m_dreq.valid ) m_cost_data_miss_frz++;
+
+#ifdef INSTRUMENTATION
+m_cpt_dcache_dir_write++;
+#endif
+            r_dcache.write_dir( 0,
+                                r_dcache_clack_way.read(),
+                                r_dcache_clack_set.read(),
+                                CACHE_SLOT_STATE_EMPTY);
+            /*STATS DIRTY*/
+            for (size_t word = 0; word < m_dcache_words; word++)
+            {
+                dirty_stats[(r_cc_receive_dcache_way * m_dcache_sets + r_cc_receive_dcache_set) * m_dcache_words + word] = false;
+            }
+
+            if ( (r_dcache_miss_set.read() == r_dcache_clack_set.read()) and
+                 (r_dcache_miss_way.read() == r_dcache_clack_way.read()) )
+            {
+                  r_dcache_miss_clack = false;
+            }
+
+            r_dcache_clack_req = false;
+
+            // return to cc_save state if no pending CC request
+            if ( not r_cc_receive_dcache_req.read() )
+            {
+                r_dcache_fsm = r_dcache_fsm_cc_save.read() ;
+            }
+
+#if DEBUG_DCACHE
+if ( m_debug_activated )
+{
+    std::cout << "  <PROC " << name()
+              << " DCACHE_CC_CHECK> CC_TYPE_CLACK Switch slot to EMPTY state"
+              << " set = " << r_dcache_clack_set.read()
+              << " / way = " << r_dcache_clack_way.read() << std::endl;
+}
+#endif
+            break;
+        }
+
+        // wait if pending request to CC_SEND. This way if there are pending
+        // CLACK they can be treated in this state and then a deadlock
+        // situation is avoided
+        if ( r_dcache_cc_send_req.read() ) break;
+
+        // CC request handler
+       
+        int    state = 0;
+        size_t way   = 0;
+        size_t set   = 0;
+        size_t word  = 0;
 
 #ifdef INSTRUMENTATION
 m_cpt_dcache_dir_read++;
 #endif
-            r_dcache.read_dir( paddr,
-                               &state,
-                               &way,
-                               &set,
-                               &word );	// unused
-
-            r_dcache_cc_way = way;
-            r_dcache_cc_set = set;
-            /*ODCCP*/
-            if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC))             // hit
-            {
-                // need to update the cache state
-                r_dcache_cleanup_ncc = false;
-                r_dcache_cc_need_write = true;
-                if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)  // hit update
+        r_dcache.read_dir( paddr,
+                           &state,
+                           &way,
+                           &set,
+                           &word ); // unused
+
+        r_dcache_cc_way = way;
+        r_dcache_cc_set = set;
+        /*ODCCP*/
+        if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC))             // hit
+        {
+            r_dcache_cleanup_ncc = false;
+            r_dcache_cc_need_write = true;
+            if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)  // hit update
+            {
+                    /*ODCCP*/ // we can't receive a CC_UPDT on a NCC line
+                if (state == CACHE_SLOT_STATE_VALID_NCC)
+                    std::cout << "DCACHE_CC_CHECK : IMPOSSIBLE NCC STATE FOR CC_UPDT at cycle " << m_cpt_total_cycles << std::endl;
+                assert((state != CACHE_SLOT_STATE_VALID_NCC) and "DCACHE_CC_CHECK : IMPOSSIBLE NCC STATE FOR CC_UPDT");
+                    
+                r_dcache_fsm          = DCACHE_CC_UPDT;
+                r_dcache_cc_word      = r_cc_receive_word_idx.read();
+            }
+            else if (r_cc_receive_dcache_type.read() == CC_TYPE_INVAL)   // hit inval
+            {
+                if ( (state == CACHE_SLOT_STATE_VALID_NCC) )
                 {
-                    /*ODCCP*/ // we can't receive a CC_UPDT on a NCC line
-                    if (state == CACHE_SLOT_STATE_VALID_NCC)
-                        std::cout << "DCACHE_CC_CHECK : IMPOSSIBLE NCC STATE FOR CC_UPDT at cycle " << m_cpt_total_cycles << std::endl;
-                    assert((state != CACHE_SLOT_STATE_VALID_NCC) and "DCACHE_CC_CHECK : IMPOSSIBLE NCC STATE FOR CC_UPDT");
-                    
-                    r_dcache_fsm          = DCACHE_CC_UPDT;
-                    r_dcache_cc_word      = r_cc_receive_word_idx.read();
+                    if (r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_DATA_DIRTY)
+                        m_cpt_data_cleanup_dirty ++;
+                    r_dcache_cc_state           = state;
+                    r_dcache_cc_inval_addr      = (paddr &~0x3F);
+                    r_dcache_cc_inval_data_cpt  = 0;
                 }
-                else if (r_cc_receive_dcache_type.read() == CC_TYPE_INVAL)   // hit inval
+                else
                 {
-                    if ( (state == CACHE_SLOT_STATE_VALID_NCC) )
-                    {
-                        if (r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_DATA_DIRTY)
-                            m_cpt_data_cleanup_dirty ++;
-                        r_dcache_cc_state           = state;
-                        r_dcache_cc_inval_addr      = (paddr &~0x3F);
-                        r_dcache_cc_inval_data_cpt  = 0;
-                    }
-                    else
-                    {
-                        r_dcache_cc_state           = state;
-                        r_dcache_cc_inval_addr      = (paddr &~0x3F);
-                    }
-                    r_dcache_fsm                = DCACHE_CC_INVAL;
+                    r_dcache_cc_state           = state;
+                    r_dcache_cc_inval_addr      = (paddr &~0x3F);
                 }
-                else if ( r_cc_receive_dcache_type.read() == CC_TYPE_BRDCAST)  // hit broadcast
-                {
-                    assert((state != CACHE_SLOT_STATE_VALID_NCC) and "DCACHE_CC_CHECK : IMPOSSIBLE NCC STATE FOR CC_BROADCAST");
-                    r_dcache_fsm          = DCACHE_CC_BROADCAST;
-                }
-            }
-            else                                      // miss
-            {
-                // multicast acknowledgement required in case of update
-                if(r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)
-                {
-                    r_dcache_fsm          = DCACHE_CC_UPDT;
-                    r_dcache_cc_word      = r_cc_receive_word_idx.read();
-                    // just pop the fifo , don't write in icache
-                    r_dcache_cc_need_write = false;
-                }
-                else // No response needed
-                {
-                    r_cc_receive_dcache_req = false;
-                    r_dcache_fsm          = r_dcache_fsm_cc_save.read();
-                }
-            }
+                r_dcache_fsm                = DCACHE_CC_INVAL;
+            }
+        }
+        else                                  // miss
+        {
+            // multicast acknowledgement required in case of update
+            if(r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)
+            {
+                r_dcache_fsm           = DCACHE_CC_UPDT;
+                r_dcache_cc_word       = r_cc_receive_word_idx.read();
+
+                // just pop the fifo , don't write in icache
+                r_dcache_cc_need_write = false;
+            }
+            else // No response needed
+            {
+                r_cc_receive_dcache_req = false;
+                r_dcache_fsm            = r_dcache_fsm_cc_save.read();
+            }
+        }
 
 #if DEBUG_DCACHE
@@ -4982,4 +5142,93 @@
 }
 #endif
+
+        break;
+    }
+    /////////////////////
+    case DCACHE_CC_INVAL: // hit inval: switch slot to ZOMBI state and send a
+                          // CLEANUP after possible invalidation of copies in
+                          // TLBs
+    {
+        size_t way    = r_dcache_cc_way.read();
+        size_t set    = r_dcache_cc_set.read();
+        int      state  = r_dcache_cc_state.read();
+        if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
+        {
+            r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
+            r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
+            r_dcache_tlb_inval_set   = 0;
+            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
+            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+            break;
+        }
+        if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
+        {
+            r_itlb.reset();
+            r_dtlb.reset();
+            r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
+
+#if DEBUG_DCACHE
+if ( m_debug_activated )
+{
+    std::cout << "  <PROC " << name()
+    << " DCACHE_CC_INVAL> Flush DTLB & ITLB" << std::endl;
+}
+#endif
+        }
+
+
+        if ( state == CACHE_SLOT_STATE_VALID_CC )
+        {
+            // Switch slot state to ZOMBI and send CLEANUP command 
+            r_dcache.write_dir( way,
+                                set,
+                                CACHE_SLOT_STATE_ZOMBI );
+#if DEBUG_DCACHE
+if ( m_debug_activated )
+{
+    std::cout << "  <PROC " << name()
+    << " DCACHE_CC_INVAL> Switch slot valid CC to ZOMBI state:" << std::dec
+    << " / WAY = " << way
+    << " / SET = " << set << std::endl;
+}
+#endif
+        }
+
+        assert (not r_dcache_cc_send_req.read() &&
+                "ERROR in DCACHE_CC_INVAL: the r_dcache_cc_send_req "
+                "must not be set");
+
+        // coherence request completed
+        r_cc_receive_dcache_req = false;
+        r_dcache_cc_send_req    = true;
+        r_dcache_cc_send_nline  = r_cc_receive_dcache_nline.read();
+        r_dcache_cc_send_way    = way;
+        r_dcache_cc_send_type   = CC_TYPE_CLEANUP;
+        r_dcache_fsm            = r_dcache_fsm_cc_save.read();
+            
+        if ( (state == CACHE_SLOT_STATE_VALID_NCC) )
+        {
+            r_dcache_cleanup_ncc = true;
+                
+            if (r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_DATA_DIRTY)
+            {
+                r_dcache_cc_cleanup_updt_data = true;
+                r_dcache_fsm = DCACHE_CC_INVAL_DATA;
+                    
+                    /*STATS DIRTY*/
+                    for (size_t w = 0; w < m_dcache_words; w++)
+                    {
+                       if(dirty_stats[(way * m_dcache_sets + set) * m_dcache_words + w] == true)
+                           m_cpt_words_dirty++;
+                    }
+            }
+            else
+            {
+                r_dcache_cc_cleanup_updt_data = false;
+                r_dcache.write_dir( way,
+                                    set,
+                                    CACHE_SLOT_STATE_ZOMBI );
+                r_dcache_fsm = r_dcache_fsm_cc_save.read();
+            }
         }
         break;
@@ -5001,5 +5250,4 @@
             r_dcache_cc_inval_addr = r_dcache_cc_inval_addr.read() + 4;
 
-            cleanup_data_updt_fifo_dcache_get   = false;
             cleanup_data_updt_fifo_dcache_put   = true;
             cleanup_data_updt_fifo_dcache_data  = rdata;
@@ -5026,138 +5274,28 @@
         break;
     }
-    /////////////////////
-    case DCACHE_CC_INVAL:   	// hit inval: switch slot to EMPTY state,
+    ///////////////////
+    case DCACHE_CC_UPDT:        // hit update: write one word per cycle,
                                 // after possible invalidation of copies in TLBs
     {
-        size_t	 way    = r_dcache_cc_way.read();
-        size_t	 set    = r_dcache_cc_set.read();
-        int      state  = r_dcache_cc_state.read();
-        if (r_dcache_cc_need_write.read())
-        {
-            if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
-            {
-                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
-                r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
-                r_dcache_tlb_inval_set   = 0;
-                r_dcache_fsm_scan_save   = r_dcache_fsm.read();
-                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
-                break;
-            }
-            else
-            {
-                if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
-                {
-                    r_itlb.reset();
-                    r_dtlb.reset();
-                    r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
-
-#if DEBUG_DCACHE
-                    if ( m_debug_activated )
-                    {
-                        std::cout << "  <PROC " << name()
-                            << " DCACHE_CC_INVAL> Flush DTLB & ITLB" << std::endl;
-                    }
-#endif
-                }
-
-                if ( state == CACHE_SLOT_STATE_VALID_CC )
-                {
-                    r_dcache.write_dir( 0,
-                            way,
-                            set,
-                            CACHE_SLOT_STATE_EMPTY );
-#if DEBUG_DCACHE
-                    if ( m_debug_activated )
-                    {
-                        std::cout << "  <PROC " << name()
-
-                            << " DCACHE_CC_INVAL> Switch slot to EMPTY state:" << std::dec
-                            << " / WAY = " << way
-                            << " / SET = " << set << std::endl;
-                    }
-#endif
-                }
-                r_dcache_cc_need_write = false;
-
-            }
-        }
-
-        // multicast acknowledgement
-        // send a request to cc_send_fsm
-        if(not r_dcache_cc_send_req.read()) // cc_send is available
-        {
-
-            // coherence request completed
-            r_cc_receive_dcache_req = false;
-            r_dcache_cc_send_req = true;
-            r_dcache_cc_send_nline = r_cc_receive_dcache_nline.read();
-
-            
-            if ( (state == CACHE_SLOT_STATE_VALID_NCC) )
-            {
-                r_dcache_cleanup_ncc = true;
-                r_dcache_cc_send_type = CC_TYPE_CLEANUP;
-                r_dcache_cc_send_way = way;
-                
-                if (r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_DATA_DIRTY)
-                {
-                    r_dcache_cc_cleanup_updt_data = true;
-                    r_dcache_fsm = DCACHE_CC_INVAL_DATA;
-                    
-                    /*STATS DIRTY*/
-                    for (size_t w = 0; w < m_dcache_words; w++)
-                    {
-                       if(dirty_stats[(way * m_dcache_sets + set) * m_dcache_words + w] == true)
-                           m_cpt_words_dirty++;
-                    }
-                }
-                else
-                {
-                    r_dcache_cc_cleanup_updt_data = false;
-                    r_dcache.write_dir( way,
-                                        set,
-                                        CACHE_SLOT_STATE_ZOMBI );
-                    r_dcache_fsm = r_dcache_fsm_cc_save.read();
-                }
-            }
-            else
-            {
-                // request multicast acknowledgement
-                r_dcache_cc_send_updt_tab_idx = r_cc_receive_dcache_updt_tab_idx.read();
-                r_dcache_cc_send_type = CC_TYPE_MULTI_ACK;
-                r_dcache_fsm = r_dcache_fsm_cc_save.read();
-            }
-        }
-        //else wait for previous cc_send request to be sent
-        break;
-    }
-    ///////////////////
-    case DCACHE_CC_UPDT:    	// hit update: write one word per cycle,
-                                // after possible invalidation of copies in TLBs
-    {
-        size_t	 word       = r_dcache_cc_word.read();
-        size_t	 way        = r_dcache_cc_way.read();
-        size_t	 set        = r_dcache_cc_set.read();
-
-        if (r_cc_receive_updt_fifo_be.rok())
-        {
-            if (r_dcache_cc_need_write.read())
-            {
-                // selective TLB inval
-                if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
-                {
-                    r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
-                    r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
-                    r_dcache_tlb_inval_set   = 0;
-                    r_dcache_fsm_scan_save   = r_dcache_fsm.read();
-                    r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
-                    break;
-                }
-                // TLB flush
-                if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
-                {
-                    r_itlb.reset();
-                    r_dtlb.reset();
-                    r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
+        size_t word       = r_dcache_cc_word.read();
+        size_t way        = r_dcache_cc_way.read();
+        size_t set        = r_dcache_cc_set.read();
+
+        // selective TLB inval
+        if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
+        {
+            r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
+            r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
+            r_dcache_tlb_inval_set   = 0;
+            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
+            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+            break;
+        }
+        // TLB flush
+        if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
+        {
+            r_itlb.reset();
+            r_dtlb.reset();
+            r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
 
 #if DEBUG_DCACHE
@@ -5165,19 +5303,28 @@
 {
     std::cout << "  <PROC " << name()
-              << " DCACHE_CC_UPDT> Flush DTLB & ITLB" << std::endl;
+    << " DCACHE_CC_UPDT> Flush DTLB & ITLB" << std::endl;
 }
 #endif
-                }
-
+        }
+
+        assert (not r_dcache_cc_send_req.read() &&
+                "ERROR in DCACHE_CC_INVAL: the r_dcache_cc_send_req "
+                "must not be set");
+        
+        if ( not r_cc_receive_updt_fifo_be.rok() ) break;
+
+        if (r_dcache_cc_need_write.read())
+        {
+        
 #ifdef INSTRUMENTATION
 m_cpt_dcache_data_write++;
 #endif
-                r_dcache.write( way,
-                                set,
-                                word,
-                                r_cc_receive_updt_fifo_data.read(),
-                                r_cc_receive_updt_fifo_be.read() );
-
-                r_dcache_cc_word = word + 1;
+            r_dcache.write( way,
+                            set,
+                            word,
+                            r_cc_receive_updt_fifo_data.read(),
+                            r_cc_receive_updt_fifo_be.read() );
+
+            r_dcache_cc_word = word + 1;
 
 #if DEBUG_DCACHE
@@ -5192,111 +5339,26 @@
 }
 #endif
-            }
-
-            if ( r_cc_receive_updt_fifo_eop.read() )	// last word
-            {
-                // no need to write in the cache anymore
-                r_dcache_cc_need_write = false;
-
-                // wait to send a request to cc_send_fsm
-                if(not r_dcache_cc_send_req.read())
-                // cc_send is available
-                {
-                    //consume last fifo flit if eop and request to cc_send possible
-                    cc_receive_updt_fifo_get  = true;
-
-                    // coherence request completed
-                    r_cc_receive_dcache_req = false;
-
-                    // request multicast acknowledgement
-                    r_dcache_cc_send_req = true;
-                    r_dcache_cc_send_nline = r_cc_receive_dcache_nline.read();
-                    r_dcache_cc_send_updt_tab_idx = r_cc_receive_dcache_updt_tab_idx.read();
-                    r_dcache_cc_send_type = CC_TYPE_MULTI_ACK;
-
-                    r_dcache_fsm          = r_dcache_fsm_cc_save.read();
-                }
-            }
-            else
-            {
-                //consume fifo if not eop
-                cc_receive_updt_fifo_get  = true;
-            }
-        }
-        break;
-    }
-    /////////////////////////
-    case DCACHE_CC_BROADCAST:   // hit broadcast : switch state to ZOMBI state
-                                // and request a cleanup, after possible
-                                // invalidation of copies in TLBs
-    {
-        size_t	 way   = r_dcache_cc_way.read();
-        size_t	 set   = r_dcache_cc_set.read();
-        paddr_t  nline = r_cc_receive_dcache_nline.read();
-
-        if (r_dcache_cc_need_write.read())
-        {
-            // selective TLB inval
-            if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
-            {
-                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
-                r_dcache_tlb_inval_line  = nline;
-                r_dcache_tlb_inval_set   = 0;
-                r_dcache_fsm_scan_save   = r_dcache_fsm.read();
-                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
-                break;
-            }
-            else
-            {
-            	// TLB flush
-                if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
-                {
-                    r_itlb.reset();
-                    r_dtlb.reset();
-                    r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
-
-#if DEBUG_DCACHE
-                    if ( m_debug_activated )
-                    {
-                        std::cout << "  <PROC " << name()
-                            << " DCACHE_CC_BROADCAST> Flush DTLB & ITLB" << std::endl;
-                    }
-#endif
-                }
-
-#ifdef INSTRUMENTATION
-                m_cpt_dcache_dir_write++;
-#endif
-                r_dcache.write_dir( way,
-                        set,
-                        CACHE_SLOT_STATE_ZOMBI );
-
-                r_dcache_cc_need_write = false;
-#if DEBUG_DCACHE
-                if ( m_debug_activated )
-                {
-                    std::cout << "  <PROC " << name()
-                        << " DCACHE_CC_BROADCAST > Slot goes to ZOMBI state "
-                        << " SET = " << set
-                        << " / WAY = " << way << std::endl;
-                }
-#endif
-            }
-        }
-        // cleanup
-        // send a request to cc_send_fsm
-        if(not r_dcache_cc_send_req.read()) // cc_send is available
-        {
+        }
+
+        if ( r_cc_receive_updt_fifo_eop.read() )  // last word
+        {
+            // no need to write in the cache anymore
+            r_dcache_cc_need_write = false;
+
             // coherence request completed
             r_cc_receive_dcache_req = false;
-            // request cleanup
-            r_dcache_cc_send_req = true;
-            r_dcache_cc_send_nline = r_cc_receive_dcache_nline.read();
-            r_dcache_cc_send_way   = r_dcache_cc_way.read();
-            r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
-
-            r_dcache_fsm          = r_dcache_fsm_cc_save.read();
-        }
-        //else wait for previous cc_send request to be sent
+
+            // request multicast acknowledgement
+            r_dcache_cc_send_req          = true;
+            r_dcache_cc_send_nline        = r_cc_receive_dcache_nline.read();
+            r_dcache_cc_send_updt_tab_idx = r_cc_receive_dcache_updt_tab_idx.read();
+            r_dcache_cc_send_type         = CC_TYPE_MULTI_ACK;
+
+            r_dcache_fsm                  = r_dcache_fsm_cc_save.read();
+        }
+
+        //consume fifo if not eop
+        cc_receive_updt_fifo_get  = true;
+
         break;
     }
@@ -5689,7 +5751,11 @@
                     if ( r_vci_rsp_fifo_icache.wok() )
                     {
-                        assert( (r_vci_rsp_cpt.read() < m_icache_words) and
-                        "The VCI response packet for instruction miss is too long" );
-
+                        if ( r_vci_rsp_cpt.read() >= m_icache_words )
+                        {
+                            std::cout << "ERROR in VCI_CC_VCACHE " << name()
+                                      << " VCI response packet too long "
+                                      << " for instruction miss" << std::endl;
+                            exit(0);
+                        }
                         r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
                         vci_rsp_fifo_icache_put       = true,
@@ -5697,7 +5763,11 @@
                         if ( p_vci.reop.read() )
                         {
-                            assert( (r_vci_rsp_cpt.read() == m_icache_words - 1) and
-                            "The VCI response packet for instruction miss is too short");
-
+                            if ( r_vci_rsp_cpt.read() != (m_icache_words - 1) )
+                            {
+                                std::cout << "ERROR in VCI_CC_VCACHE " << name()
+                                          << " VCI response packet too short" 
+                                          << " for instruction miss" << std::endl;
+                                exit(0);
+                            }
                             r_vci_rsp_fsm    = RSP_IDLE;
                         }
@@ -5902,5 +5972,5 @@
         {
             // wait for the first flit to be consumed
-            if (p_dspin_out.read.read())
+            if (p_dspin_p2m.read.read())
                 r_cc_send_fsm = CC_SEND_CLEANUP_2;
 
@@ -5911,5 +5981,5 @@
         {
             // wait for the second flit to be consumed
-            if (p_dspin_out.read.read())
+            if (p_dspin_p2m.read.read())
             {
                 /*ODCCP*/ // If there is a cleanup with data and dcache active request we send other flits contained data
@@ -5933,5 +6003,5 @@
         case CC_SEND_CLEANUP_DATA_UPDT: /*ODCCP*/ // we send the data values of line cache into [m_dcache_words] flits
         {
-            if (p_dspin_out.read.read())
+            if (p_dspin_p2m.read.read())
             {
                 if(r_cc_send_data_fifo.rok())
@@ -5956,5 +6026,5 @@
         {
             // wait for the flit to be consumed
-            if(p_dspin_out.read.read())
+            if(p_dspin_p2m.read.read())
             {
                 if(r_cc_send_last_client.read() == 0) // dcache active request
@@ -5970,7 +6040,7 @@
 
     ///////////////////////////////////////////////////////////////////////////////
-    //   C_RECEIVE  FSM
+    //  CC_RECEIVE  FSM
     // This FSM receive all coherence packets on a DSPIN40 port.
-    // There is 7 packet types:
+    // There is 5 packet types:
     // - CC_DATA_INVAL : DCACHE invalidate request
     // - CC_DATA_UPDT  : DCACHE update request (multi-words)
@@ -5978,6 +6048,4 @@
     // - CC_INST_UPDT  : ICACHE update request (multi-words)
     // - CC_BROADCAST  : Broadcast invalidate request (both DCACHE & ICACHE)
-    // - CC_DATA_CLACK : DCACHE cleanup acknowledge
-    // - CC_INST_CLACK : ICACHE cleanup acknowledge
     //////////////////////////////////////////////////////////////////////////////
     switch( r_cc_receive_fsm.read() )
@@ -5987,79 +6055,35 @@
         {
             // a coherence request has arrived
-            if (p_dspin_in.write.read())
+            if (p_dspin_m2p.write.read())
             {
                 // initialize dspin received data
-                uint64_t receive_data = p_dspin_in.data.read();
+                uint64_t receive_data = p_dspin_m2p.data.read();
                 // initialize coherence packet type
                 uint64_t receive_type = DspinDhccpParam::dspin_get(receive_data,
-                                            DspinDhccpParam::FROM_MC_TYPE);
-                // initialize data/ins flip_flop (0 data / 1 ins)
-                r_cc_receive_data_ins = (bool)(receive_type & 0x1);
+                                            DspinDhccpParam::M2P_TYPE);
                 // test for a broadcast
-                if (DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::FROM_MC_BC))
+                if (DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::M2P_BC))
                 {
                     r_cc_receive_fsm = CC_RECEIVE_BRDCAST_HEADER;
                 }
-                // test for a CLACK
-                else if ((receive_type == DspinDhccpParam::TYPE_CLEANUP_ACK_DATA) or
-                         (receive_type == DspinDhccpParam::TYPE_CLEANUP_ACK_INST))
+                // test for a multi updt
+                else if (receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_DATA) 
                 {
-                    r_cc_receive_fsm = CC_RECEIVE_CLACK;
+                    r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_HEADER;
                 }
-                // test for a multi updt
-                else if ((receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_DATA) or
-                         (receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_INST))
+                else if (receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_INST)
                 {
-                    r_cc_receive_fsm = CC_RECEIVE_UPDT_HEADER;
+                    r_cc_receive_fsm = CC_RECEIVE_INS_UPDT_HEADER;
                 }
                 // test for a multi inval
+                else if (receive_type == DspinDhccpParam::TYPE_MULTI_INVAL_DATA)
+                {
+                    r_cc_receive_fsm = CC_RECEIVE_DATA_INVAL_HEADER;
+                }
                 else
                 {
-                    r_cc_receive_fsm = CC_RECEIVE_INVAL_HEADER;
+                    r_cc_receive_fsm = CC_RECEIVE_INS_INVAL_HEADER;
                 }
             }
-            break;
-        }
-        //////////////////////
-        case CC_RECEIVE_CLACK:
-        {
-            // initialize dspin received data
-            uint64_t receive_data = p_dspin_in.data.read();
-
-            // for data CLACK, wait for dcache to take the request
-            if ((r_cc_receive_data_ins.read() == 0) and 
-                    not r_cc_receive_dcache_req.read())
-            {
-                // request dcache to handle the CLACK
-                r_cc_receive_dcache_req  = true;
-                r_cc_receive_dcache_set  = DspinDhccpParam::dspin_get(receive_data, 
-                                           DspinDhccpParam::CLEANUP_ACK_SET) & 
-                                           ((1ULL<<(uint32_log2(m_dcache_sets)))-1);
-                r_cc_receive_dcache_way  = DspinDhccpParam::dspin_get(receive_data, 
-                                           DspinDhccpParam::CLEANUP_ACK_WAY) & 
-                                           ((1ULL<<(uint32_log2(m_dcache_ways)))-1);
-                r_cc_receive_dcache_type = CC_TYPE_CLACK;
-                // get back to idle state
-                r_cc_receive_fsm = CC_RECEIVE_IDLE;
-                break;
-            }
-            // for ins CLACK, wait for icache to take the request
-            if ((r_cc_receive_data_ins.read() == 1) and 
-                   not (r_cc_receive_icache_req.read()))
-            {
-                // request icache to handle the CLACK
-                r_cc_receive_icache_req  = true;
-                r_cc_receive_icache_set  = DspinDhccpParam::dspin_get(receive_data,
-                                           DspinDhccpParam::CLEANUP_ACK_SET) & 
-                                           ((1ULL<<(uint32_log2(m_icache_sets)))-1);
-                r_cc_receive_icache_way  = DspinDhccpParam::dspin_get(receive_data,
-                                           DspinDhccpParam::CLEANUP_ACK_WAY) & 
-                                           ((1ULL<<(uint32_log2(m_icache_ways)))-1);
-                r_cc_receive_icache_type = CC_TYPE_CLACK;
-                // get back to idle state
-                r_cc_receive_fsm = CC_RECEIVE_IDLE;
-                break;
-            }
-            // keep waiting for the correct cache to accept the request
             break;
         }
@@ -6075,5 +6099,5 @@
         {
             // initialize dspin received data
-            uint64_t receive_data = p_dspin_in.data.read();
+            uint64_t receive_data = p_dspin_m2p.data.read();
             // wait for both dcache and icache to take the request
             // TODO maybe we need to wait for both only to leave the state, but
@@ -6082,16 +6106,16 @@
             if (not (r_cc_receive_icache_req.read()) and 
                 not (r_cc_receive_dcache_req.read()) and 
-                (p_dspin_in.write.read()))
+                (p_dspin_m2p.write.read()))
             {
                 // request dcache to handle the BROADCAST
-                r_cc_receive_dcache_req  = true;
+                r_cc_receive_dcache_req = true;
                 r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,
                                              DspinDhccpParam::BROADCAST_NLINE);
-                r_cc_receive_dcache_type = CC_TYPE_BRDCAST;
+                r_cc_receive_dcache_type = CC_TYPE_INVAL;
                 // request icache to handle the BROADCAST
-                r_cc_receive_icache_req  = true;
+                r_cc_receive_icache_req = true;
                 r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,
                                              DspinDhccpParam::BROADCAST_NLINE);
-                r_cc_receive_icache_type = CC_TYPE_BRDCAST;
+                r_cc_receive_icache_type = CC_TYPE_INVAL;
                 // get back to idle state
                 r_cc_receive_fsm = CC_RECEIVE_IDLE;
@@ -6102,42 +6126,28 @@
         }
         /////////////////////////////
-        case CC_RECEIVE_INVAL_HEADER:
+        case CC_RECEIVE_DATA_INVAL_HEADER:
         {
             // sample updt tab index in the HEADER, then skip to second flit
-            uint64_t receive_data = p_dspin_in.data.read();
+            r_cc_receive_fsm = CC_RECEIVE_DATA_INVAL_NLINE;
+            break;
+        }
+        /////////////////////////////
+        case CC_RECEIVE_INS_INVAL_HEADER:
+        {
+            // sample updt tab index in the HEADER, then skip to second flit
+            r_cc_receive_fsm = CC_RECEIVE_INS_INVAL_NLINE;
+            break;
+        }
+        ////////////////////////////
+        case CC_RECEIVE_DATA_INVAL_NLINE:
+        {
+            // sample nline in the second flit
+            uint64_t receive_data = p_dspin_m2p.data.read();
             // for data INVAL, wait for dcache to take the request
-            if ((r_cc_receive_data_ins.read() == 0) and 
-                 not (r_cc_receive_dcache_req.read()))
-            {
-                r_cc_receive_dcache_updt_tab_idx = DspinDhccpParam::dspin_get(receive_data,
-                                                   DspinDhccpParam::MULTI_INVAL_UPDT_INDEX);
-                r_cc_receive_fsm = CC_RECEIVE_INVAL_NLINE;
-                break;
-            }
-            // for ins INVAL, wait for icache to take the request
-            if ((r_cc_receive_data_ins.read() == 1) and 
-                 not (r_cc_receive_icache_req.read()))
-            {
-                r_cc_receive_icache_updt_tab_idx = DspinDhccpParam::dspin_get(receive_data,
-                                                   DspinDhccpParam::MULTI_INVAL_UPDT_INDEX);
-                r_cc_receive_fsm = CC_RECEIVE_INVAL_NLINE;
-                break;
-            }
-            // keep waiting for the correct cache to accept the request
-            break;
-        }
-        ////////////////////////////
-        case CC_RECEIVE_INVAL_NLINE:
-        {
-            // sample nline in the second flit
-            uint64_t receive_data = p_dspin_in.data.read();
-            // for data INVAL, wait for dcache to take the request
-            if ( (r_cc_receive_data_ins.read() == 0) and 
-                 not (r_cc_receive_dcache_req.read()) and 
-                 (p_dspin_in.write.read()) )
+            if (p_dspin_m2p.write.read() and not r_cc_receive_dcache_req.read())
             {
                 // request dcache to handle the INVAL
-                r_cc_receive_dcache_req  = true;
-                r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
+                r_cc_receive_dcache_req = true;
+                r_cc_receive_dcache_nline = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
                 r_cc_receive_dcache_type = CC_TYPE_INVAL;
                 // get back to idle state
@@ -6145,10 +6155,17 @@
                 break;
             }
+            break;
+        }
+        //////////////////////////////
+        case CC_RECEIVE_INS_INVAL_NLINE:
+        {
+            // sample nline in the second flit
+            uint64_t receive_data = p_dspin_m2p.data.read();
             // for ins INVAL, wait for icache to take the request
-            if ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read()) and (p_dspin_in.write.read()))
+            if (p_dspin_m2p.write.read() and not r_cc_receive_icache_req.read())
             {
                 // request icache to handle the INVAL
-                r_cc_receive_icache_req  = true;
-                r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
+                r_cc_receive_icache_req = true;
+                r_cc_receive_icache_nline = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
                 r_cc_receive_icache_type = CC_TYPE_INVAL;
                 // get back to idle state
@@ -6156,26 +6173,32 @@
                 break;
             }
-            // we should never get there
-            assert ( false && "ERROR in CC_VCACHE : CC_RECEIVE_INVAL_NLINE\n");
+            break;
         }
         ////////////////////////////
-        case CC_RECEIVE_UPDT_HEADER:
+        case CC_RECEIVE_DATA_UPDT_HEADER:
         {
             // sample updt tab index in the HEADER, than skip to second flit
-            uint64_t receive_data = p_dspin_in.data.read();
+            uint64_t receive_data = p_dspin_m2p.data.read();
             // for data INVAL, wait for dcache to take the request and fifo to
             // be empty
-            if ((r_cc_receive_data_ins.read() == 0) and not r_cc_receive_dcache_req.read() and r_cc_receive_updt_fifo_be.empty())
+            if (not r_cc_receive_dcache_req.read())
             {
                 r_cc_receive_dcache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
-                r_cc_receive_fsm = CC_RECEIVE_UPDT_NLINE;
+                r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_NLINE;
                 break;
             }
+            break;
+        }
+        ////////////////////////////
+        case CC_RECEIVE_INS_UPDT_HEADER:
+        {
+            // sample updt tab index in the HEADER, than skip to second flit
+            uint64_t receive_data = p_dspin_m2p.data.read();
             // for ins INVAL, wait for icache to take the request and fifo to be
             // empty
-            if ((r_cc_receive_data_ins.read() == 1) and not r_cc_receive_icache_req.read() and r_cc_receive_updt_fifo_be.empty())
+            if (not r_cc_receive_icache_req.read())
             {
                 r_cc_receive_icache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
-                r_cc_receive_fsm = CC_RECEIVE_UPDT_NLINE;
+                r_cc_receive_fsm = CC_RECEIVE_INS_UPDT_NLINE;
                 break;
             }
@@ -6184,53 +6207,51 @@
         }
         ///////////////////////////
-        case CC_RECEIVE_UPDT_NLINE:
+        case CC_RECEIVE_DATA_UPDT_NLINE:
         {
             // sample nline and word index in the second flit
-            uint64_t receive_data = p_dspin_in.data.read();
+            uint64_t receive_data = p_dspin_m2p.data.read();
             // for data INVAL, wait for dcache to take the request and fifo to
             // be empty
-            if ( (r_cc_receive_data_ins.read() == 0) and 
-                 not (r_cc_receive_dcache_req.read()) and 
-                 r_cc_receive_updt_fifo_be.empty() and 
-                 (p_dspin_in.write.read()) )
-            {
+            if ( r_cc_receive_updt_fifo_be.empty() and 
+                 p_dspin_m2p.write.read() )
+            {
+                r_cc_receive_dcache_req = true;
                 r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_NLINE);
                 r_cc_receive_word_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
                 r_cc_receive_dcache_type = CC_TYPE_UPDT;
                 // get back to idle state
-                r_cc_receive_fsm = CC_RECEIVE_UPDT_DATA;
+                r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_DATA;
                 break;
             }
+            break;
+        }
+        ////////////////////////////
+        case CC_RECEIVE_INS_UPDT_NLINE:
+        {
+            // sample nline and word index in the second flit
+            uint64_t receive_data = p_dspin_m2p.data.read();
             // for ins INVAL, wait for icache to take the request and fifo to be
             // empty
-            if ( (r_cc_receive_data_ins.read() == 1) and 
-                 not (r_cc_receive_icache_req.read()) and 
-                 r_cc_receive_updt_fifo_be.empty() and 
-                 (p_dspin_in.write.read()))
-            {
+            if ( r_cc_receive_updt_fifo_be.empty() and 
+                 p_dspin_m2p.write.read() )
+            {
+                r_cc_receive_icache_req = true;
                 r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_NLINE);
                 r_cc_receive_word_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
                 r_cc_receive_icache_type = CC_TYPE_UPDT;
                 // get back to idle state
-                r_cc_receive_fsm = CC_RECEIVE_UPDT_DATA;
+                r_cc_receive_fsm = CC_RECEIVE_INS_UPDT_DATA;
                 break;
             }
-            // we should never get there
-            assert ( false && "ERROR in CC_VCACHE : CC_RECEIVE_UPDT_NLINE \n");
             break;
         }
         //////////////////////////
-        case CC_RECEIVE_UPDT_DATA:
-        {
-            if ((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read()) and (p_dspin_in.write.read()))
-                r_cc_receive_dcache_req = true;
-            if ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read()) and (p_dspin_in.write.read()))
-                r_cc_receive_icache_req = true;
-
+        case CC_RECEIVE_DATA_UPDT_DATA:
+        {
             // wait for the fifo
-            if (r_cc_receive_updt_fifo_be.wok() and (p_dspin_in.write.read()))
-            {
-                uint64_t receive_data = p_dspin_in.data.read();
-                bool     receive_eop  = p_dspin_in.eop.read();
+            if (r_cc_receive_updt_fifo_be.wok() and (p_dspin_m2p.write.read()))
+            {
+                uint64_t receive_data = p_dspin_m2p.data.read();
+                bool     receive_eop  = p_dspin_m2p.eop.read();
                 cc_receive_updt_fifo_be   = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_BE);
                 cc_receive_updt_fifo_data = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_DATA);
@@ -6241,5 +6262,66 @@
             break;
         }
+        //////////////////////////
+        case CC_RECEIVE_INS_UPDT_DATA:
+        {
+            // wait for the fifo
+            if (r_cc_receive_updt_fifo_be.wok() and (p_dspin_m2p.write.read()))
+            {
+                uint64_t receive_data = p_dspin_m2p.data.read();
+                bool     receive_eop  = p_dspin_m2p.eop.read();
+                cc_receive_updt_fifo_be   = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_BE);
+                cc_receive_updt_fifo_data = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_DATA);
+                cc_receive_updt_fifo_eop  = receive_eop;
+                cc_receive_updt_fifo_put  = true;
+                if ( receive_eop ) r_cc_receive_fsm = CC_RECEIVE_IDLE;
+            }
+            break;
+        }
+
     } // end switch CC_RECEIVE FSM
+
+    ///////////////// DSPIN CLACK interface ///////////////
+    
+    uint64_t clack_type = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
+                                                     DspinDhccpParam::CLACK_TYPE);
+
+    size_t clack_way  = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
+                                                   DspinDhccpParam::CLACK_WAY);
+
+    size_t clack_set  = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
+                                                   DspinDhccpParam::CLACK_SET);
+
+    bool dspin_clack_get      = false;
+    bool dcache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_DATA);
+    bool icache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_INST);
+
+    if (r_dspin_clack_req.read())
+    {
+        // CLACK DATA: Send request to DCACHE FSM
+        if (dcache_clack_request and not r_dcache_clack_req.read()){
+            r_dcache_clack_req = true;
+            r_dcache_clack_way = clack_way & ((1ULL<<(uint32_log2(m_dcache_ways)))-1);
+            r_dcache_clack_set = clack_set & ((1ULL<<(uint32_log2(m_dcache_sets)))-1);
+            dspin_clack_get    = true;
+        }
+
+        // CLACK INST: Send request to ICACHE FSM
+        else if (icache_clack_request and not r_icache_clack_req.read()){
+            r_icache_clack_req = true;
+            r_icache_clack_way = clack_way & ((1ULL<<(uint32_log2(m_dcache_ways)))-1);
+            r_icache_clack_set = clack_set & ((1ULL<<(uint32_log2(m_icache_sets)))-1);
+            dspin_clack_get    = true;
+        }
+    }
+    else
+    {
+        dspin_clack_get = true;
+    }
+
+    if (dspin_clack_get)
+    {
+        r_dspin_clack_req  = p_dspin_clack.write.read();
+        r_dspin_clack_flit = p_dspin_clack.data.read();
+    }
 
     ///////////////// Response FIFOs update  //////////////////////
@@ -6447,5 +6529,5 @@
         case CC_SEND_IDLE:
         {
-            p_dspin_out.write = false;
+            p_dspin_p2m.write = false;
             break;
         }
@@ -6454,4 +6536,7 @@
         {
             // initialize dspin send data
+//            DspinDhccpParam::dspin_set(dspin_send_data,
+//                                       0,
+//                                       DspinDhccpParam::P2M_EOP);
             DspinDhccpParam::dspin_set(dspin_send_data,
                                        m_cc_global_id,
@@ -6459,5 +6544,5 @@
             DspinDhccpParam::dspin_set(dspin_send_data,
                                        0,
-                                       DspinDhccpParam::FROM_L1_BC);
+                                       DspinDhccpParam::P2M_BC);
 
             if(r_cc_send_last_client.read() == 0) // dcache active request
@@ -6480,5 +6565,5 @@
                 DspinDhccpParam::dspin_set(dspin_send_data,
                                            DspinDhccpParam::TYPE_CLEANUP_DATA,
-                                           DspinDhccpParam::FROM_L1_TYPE);
+                                           DspinDhccpParam::P2M_TYPE);
                 /*ODCCP*/ // If cleanup on NCC line we set the CLEANUP_NCC bit in cleanup flit
                 if (r_dcache_cleanup_ncc.read())                 
@@ -6516,5 +6601,5 @@
                 DspinDhccpParam::dspin_set(dspin_send_data,
                                            DspinDhccpParam::TYPE_CLEANUP_INST,
-                                           DspinDhccpParam::FROM_L1_TYPE);
+                                           DspinDhccpParam::P2M_TYPE);
                 
                 DspinDhccpParam::dspin_set(dspin_send_data,
@@ -6523,7 +6608,7 @@
             }
             // send flit
-            p_dspin_out.data  = dspin_send_data;
-            p_dspin_out.write = true;
-            p_dspin_out.eop   = false;
+            p_dspin_p2m.data  = dspin_send_data;
+            p_dspin_p2m.write = true;
+            p_dspin_p2m.eop   = false;
             break;
         }
@@ -6535,9 +6620,9 @@
             if (r_dcache_cc_cleanup_updt_data.read() and not r_cc_send_last_client.read())
             {
-                p_dspin_out.eop   = false;
+                p_dspin_p2m.eop   = false;
             }
             else
             {
-                p_dspin_out.eop   = true;
+                p_dspin_p2m.eop   = true;
             }
 
@@ -6555,6 +6640,6 @@
             }
             // send flit
-            p_dspin_out.data  = dspin_send_data;
-            p_dspin_out.write = true;
+            p_dspin_p2m.data  = dspin_send_data;
+            p_dspin_p2m.write = true;
             break;
         }
@@ -6564,9 +6649,9 @@
             if (r_cc_send_cpt_word.read() == m_dcache_words-1) /*ODCCP*/ // Last flit sent
             {
-                p_dspin_out.eop   = true;
+                p_dspin_p2m.eop   = true;
             }
             else
             {
-                p_dspin_out.eop   = false;
+                p_dspin_p2m.eop   = false;
             }
 
@@ -6575,6 +6660,10 @@
                                        DspinDhccpParam::CLEANUP_DATA_UPDT);
             
-            p_dspin_out.data = dspin_send_data;
-            p_dspin_out.write = true;
+            p_dspin_p2m.data = dspin_send_data;
+            //p_dspin_p2m.write = true;
+            if(r_cc_send_data_fifo.rok())
+                p_dspin_p2m.write = true;
+            else
+                p_dspin_p2m.write = false;
             break;
         }
@@ -6585,11 +6674,11 @@
 //            DspinDhccpParam::dspin_set(dspin_send_data,
 //                                       1,
-//                                       DspinDhccpParam::FROM_L1_EOP);
+//                                       DspinDhccpParam::P2M_EOP);
             DspinDhccpParam::dspin_set(dspin_send_data,
                                        0,
-                                       DspinDhccpParam::FROM_L1_BC);
+                                       DspinDhccpParam::P2M_BC);
             DspinDhccpParam::dspin_set(dspin_send_data,
                                        DspinDhccpParam::TYPE_MULTI_ACK,
-                                       DspinDhccpParam::FROM_L1_TYPE);
+                                       DspinDhccpParam::P2M_TYPE);
 
             if(r_cc_send_last_client.read() == 0) // dcache active request
@@ -6623,7 +6712,7 @@
             }
             // send flit
-            p_dspin_out.data  = dspin_send_data;
-            p_dspin_out.write = true;
-            p_dspin_out.eop   = true;
+            p_dspin_p2m.data  = dspin_send_data;
+            p_dspin_p2m.write = true;
+            p_dspin_p2m.eop   = true;
 
             break;
@@ -6633,5 +6722,4 @@
     // Receive coherence packets
     // It depends on the CC_RECEIVE FSM 
-
     switch( r_cc_receive_fsm.read() )
     {
@@ -6639,15 +6727,5 @@
         case CC_RECEIVE_IDLE:
         {
-            p_dspin_in.read = false;
-            break;
-        }
-        //////////////////////
-        case CC_RECEIVE_CLACK:
-        {
-            if (((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read())) or
-                ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read())))
-                p_dspin_in.read = true;
-            else
-                p_dspin_in.read = false;
+            p_dspin_m2p.read = false;
             break;
         }
@@ -6655,5 +6733,5 @@
         case CC_RECEIVE_BRDCAST_HEADER:
         {
-            p_dspin_in.read = true;
+            p_dspin_m2p.read = true;
             break;
         }
@@ -6665,66 +6743,95 @@
             // flip_flop to check that ?
             if (not (r_cc_receive_icache_req.read()) and not (r_cc_receive_dcache_req.read()))
-                p_dspin_in.read = true;
+                p_dspin_m2p.read = true;
             else
-                p_dspin_in.read = false;
+                p_dspin_m2p.read = false;
             break;
         }
         /////////////////////////////
-        case CC_RECEIVE_INVAL_HEADER:
-        {
-            if (((r_cc_receive_data_ins.read() == 0) and not (r_cc_receive_dcache_req.read())) or
-                ((r_cc_receive_data_ins.read() == 1) and not (r_cc_receive_icache_req.read())))
-                p_dspin_in.read = true;
+        case CC_RECEIVE_DATA_INVAL_HEADER:
+        case CC_RECEIVE_INS_INVAL_HEADER:
+        {
+            p_dspin_m2p.read = true;
+            break;
+        }
+        ////////////////////////////
+        case CC_RECEIVE_DATA_INVAL_NLINE:
+        {
+            p_dspin_m2p.read = not r_cc_receive_dcache_req.read();
+            break;
+        }
+        case CC_RECEIVE_INS_INVAL_NLINE:
+        {
+            p_dspin_m2p.read = not r_cc_receive_icache_req.read();
+            break;
+        }
+        ///////////////////////////
+        case CC_RECEIVE_DATA_UPDT_HEADER:
+        {
+            if (not r_cc_receive_dcache_req.read())
+                p_dspin_m2p.read = true;
             else
-                p_dspin_in.read = false;
+                p_dspin_m2p.read = false;
             break;
         }
         ////////////////////////////
-        case CC_RECEIVE_INVAL_NLINE:
-        {
-            p_dspin_in.read = true;
-            break;
-        }
-        ////////////////////////////
-        case CC_RECEIVE_UPDT_HEADER:
-        {
-            if (((r_cc_receive_data_ins.read() == 0) and
-                not r_cc_receive_dcache_req.read() and
-                r_cc_receive_updt_fifo_be.empty())
-                or
-                (((r_cc_receive_data_ins.read() == 1) and
-                not r_cc_receive_icache_req.read()) and
-                r_cc_receive_updt_fifo_be.empty()))
-                p_dspin_in.read = true;
+        case CC_RECEIVE_INS_UPDT_HEADER:
+        {
+            if ( not r_cc_receive_icache_req.read()) 
+                p_dspin_m2p.read = true;
             else
-                p_dspin_in.read = false;
+                p_dspin_m2p.read = false;
             break;
         }
         ///////////////////////////
-        case CC_RECEIVE_UPDT_NLINE:
-        {
-            if (((r_cc_receive_data_ins.read() == 0) and
-                not (r_cc_receive_dcache_req.read()) and
-                r_cc_receive_updt_fifo_be.empty())
-                or
-                ((r_cc_receive_data_ins.read() == 1) and
-                not (r_cc_receive_icache_req.read()) and
-                r_cc_receive_updt_fifo_be.empty()))
-                p_dspin_in.read = true;
+        case CC_RECEIVE_DATA_UPDT_NLINE:
+        case CC_RECEIVE_INS_UPDT_NLINE:
+        {
+            if(r_cc_receive_updt_fifo_be.empty())
+                p_dspin_m2p.read = true;
             else
-                p_dspin_in.read = false;
-            break;
-        }
-        //////////////////////////
-        case CC_RECEIVE_UPDT_DATA:
+                p_dspin_m2p.read = false;
+            break;
+        }
+        ///////////////////////////
+        case CC_RECEIVE_DATA_UPDT_DATA:
+        case CC_RECEIVE_INS_UPDT_DATA:
         {
             if (r_cc_receive_updt_fifo_be.wok())
-                p_dspin_in.read = true;
+                p_dspin_m2p.read = true;
             else
-                p_dspin_in.read = false;
+                p_dspin_m2p.read = false;
             break;
         }
     } // end switch CC_RECEIVE FSM
 
+
+    int clack_type = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
+                                                DspinDhccpParam::CLACK_TYPE);
+
+    bool dspin_clack_get      = false;
+    bool dcache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_DATA);
+    bool icache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_INST);
+
+    if (r_dspin_clack_req.read())
+    {
+        // CLACK DATA: wait if pending request to DCACHE FSM
+        if (dcache_clack_request and not r_dcache_clack_req.read())
+        {
+            dspin_clack_get = true;
+        }
+
+        // CLACK INST: wait if pending request to ICACHE FSM
+        else if (icache_clack_request and not r_icache_clack_req.read())
+        {
+            dspin_clack_get = true;
+        }
+    }
+    else
+    {
+        dspin_clack_get = true;
+    }
+
+    p_dspin_clack.read = dspin_clack_get; 
 } // end genMoore
 
