Index: trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp	(revision 205)
+++ trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp	(revision 206)
@@ -88,12 +88,9 @@
         "DCACHE_XTN_DT_INVAL",
 
-        "DCACHE_DIRTY_TLB_SET",
-        "DCACHE_DIRTY_CACHE_SET",
+        "DCACHE_DIRTY_PTE_GET",
         "DCACHE_DIRTY_SC_WAIT",  
-        "DCACHE_DIRTY_UNC_WAIT",  
 
         "DCACHE_MISS_VICTIM",
         "DCACHE_MISS_INVAL",
-        "DCACHE_MISS_INVAL_WAIT",
         "DCACHE_MISS_WAIT",  
         "DCACHE_MISS_UPDT",  
@@ -253,14 +250,6 @@
       r_dcache_p0_paddr("r_dcache_p0_paddr"),
       r_dcache_p0_cacheable("r_dcache_p0_cacheable"), 
-      r_dcache_p0_tlb_way("r_dcache_p0_tlb_way"),
-      r_dcache_p0_tlb_set("r_dcache_p0_tlb_set"),
-      r_dcache_p0_tlb_nline("r_dcache_p0_tlb_nline"),
-      r_dcache_p0_tlb_dirty("r_dcache_p0_tlb_dirty"),
-      r_dcache_p0_tlb_big("r_dcache_p0_tlb_big"),
 
       r_dcache_p1_valid("r_dcache_p1_valid"),
-      r_dcache_p1_updt_cache("r_dcache_p1_updt_cache"),
-      r_dcache_p1_set_dirty("r_dcache_p1_set_dirty"),
-      r_dcache_p1_vaddr("r_dcache_p1_vaddr"),
       r_dcache_p1_wdata("r_dcache_p1_wdata"),
       r_dcache_p1_be("r_dcache_p1_be"),
@@ -269,16 +258,8 @@
       r_dcache_p1_cache_set("r_dcache_p1_cache_set"),
       r_dcache_p1_cache_word("r_dcache_p1_word_save"),
-      r_dcache_p1_tlb_way("r_dcache_p1_tlb_way"),
-      r_dcache_p1_tlb_set("r_dcache_p1_tlb_set"),
-      r_dcache_p1_tlb_nline("r_dcache_p1_tlb_nline"),
-      r_dcache_p1_tlb_big("r_dcache_p1_tlb_big"),
-
-      r_dcache_p2_way("r_dcache_p2_way"),
-      r_dcache_p2_set("r_dcache_p2_set"),
-      r_dcache_p2_word("r_dcache_p2_word"),
-      r_dcache_p2_pte_paddr("r_dcache_p2_pte_paddr"),
-      r_dcache_p2_pte_value("r_dcache_p2_pte_value"),
-      r_dcache_p2_type_sc("r_dcache_p2_type_sc"),
-      r_dcache_p2_sc_success("r_dcache_p2_sc_success"),
+
+      r_dcache_dirty_paddr("r_dcache_dirty_paddr"),
+      r_dcache_dirty_way("r_dcache_dirty_way"),
+      r_dcache_dirty_set("r_dcache_dirty_set"),
 
       r_dcache_vci_paddr("r_dcache_vci_paddr"),
@@ -321,6 +302,4 @@
       r_dcache_ll_vaddr("r_dcache_ll_vaddr"),
 
-      r_dcache_itlb_inval_req("r_dcache_itlb_inval_req"),
-      r_dcache_dtlb_inval_req("r_dcache_dtlb_inval_req"),
       r_dcache_tlb_inval_line("r_dcache_tlb_inval_line"),
       r_dcache_tlb_inval_count("r_dcache_tlb_inval_count"),
@@ -395,8 +374,8 @@
     r_mmu_release = (uint32_t)(1 << 16) | 0x1;
 
-    r_tgt_buf         = new uint32_t[dcache_words];
-    r_tgt_be          = new vci_be_t[dcache_words];
-    r_dcache_in_itlb  = new bool[dcache_ways*dcache_sets];           
-    r_dcache_in_dtlb  = new bool[dcache_ways*dcache_sets];          
+    r_tgt_buf             = new uint32_t[dcache_words];
+    r_tgt_be              = new vci_be_t[dcache_words];
+    r_dcache_in_tlb       = new bool[dcache_ways*dcache_sets];          
+    r_dcache_contains_ptd = new bool[dcache_ways*dcache_sets];          
 
     SC_METHOD(transition);
@@ -425,6 +404,6 @@
     delete [] r_tgt_be;
     delete [] r_tgt_buf;
-    delete [] r_dcache_in_itlb;           
-    delete [] r_dcache_in_dtlb;          
+    delete [] r_dcache_in_tlb;          
+    delete [] r_dcache_contains_ptd;     
 }
 
@@ -682,8 +661,11 @@
         r_cleanup_fsm     = CLEANUP_DATA_IDLE;
 
-        std::memset(r_dcache_in_itlb, 0, sizeof(*r_dcache_in_itlb)*m_icache_ways*m_icache_sets);
-        std::memset(r_dcache_in_dtlb, 0, sizeof(*r_dcache_in_dtlb)*m_dcache_ways*m_dcache_sets);
-
-        
+        // reset dcache directory extension
+        for (size_t i=0 ; i< m_dcache_ways*m_dcache_sets ; i++)
+        {
+            r_dcache_in_tlb[i]       = false;
+            r_dcache_contains_ptd[i] = false;
+        } 
+
         // Response FIFOs and cleanup buffer
         r_vci_rsp_fifo_icache.init();
@@ -718,8 +700,4 @@
         // No LL reservation
 	r_dcache_ll_valid          = false;
-
-        // No TLB inval requestis
-        r_dcache_itlb_inval_req    = false;
-        r_dcache_dtlb_inval_req    = false;
 
         // No processor XTN request pending
@@ -1223,6 +1201,8 @@
     ////////////////////////////////////////////////////////////////////////////////////////
 
-    // default value for m_irsp.valid
-    m_irsp.valid = false;
+    // default value for m_irsp
+    m_irsp.valid       = false;
+    m_irsp.error       = false;
+    m_irsp.instruction = 0;
 
     switch( r_icache_fsm.read() ) 
@@ -1898,12 +1878,13 @@
     //    - The registration in wbuf and the dcache hit are computed in stage P1. 
     //    - The dcache update is done in stage P2.  
-    //    A write operation can require a "long write" operation (if the PTE dirty bit 
-    //    must be updated) handled by a dedicated sub-fsm (DCACHE_DIRTY_TLB_SET state).
-    //    If a PTE is modified, the both te itlb and dtlb are selectively, but sequencially
+    //    WRITE or SC requests can require a PTE Dirty bit update (in memory), 
+    //    that is done (before handling the processor request) by a dedicated sub-fsm 
+    //    (DCACHE_DIRTY_TLB_SET state).
+    //    If a PTE is modified, both the itlb and dtlb are selectively, but sequencially
     //    cleared by a dedicated sub_fsm (DCACHE_INVAL_TLB_SCAN state).
     //    If there is no write in the pipe, dcache and dtlb are accessed in parallel,
     //    (virtual address for itlb, and speculative physical address computed during 
-    //    previous cycle for dcache) in order to return the data in one cycle for a read.
-    //    We just pay an extra cycle when the speculative access is failing.
+    //    previous cycle for dcache) in order to return the data in one cycle for a READ
+    //    request. We just pay an extra cycle when the speculative access is failing.
     //
     // 4/ Atomic instructions LL/SC
@@ -1919,5 +1900,4 @@
     //      The cache is not updated, as this is done in case of success by the
     //      coherence transaction.
-    //      If rqired, the dirty bit is updated in PTE by a "long write".
     //
     // 5/ Non cacheable access:
@@ -1944,11 +1924,13 @@
     ////////////////////////////////////////////////////////////////////////////////////////
 
-    // default value for m_drsp.valid 
+    // default value for m_drsp 
     m_drsp.valid = false;
+    m_drsp.error = false;
+    m_drsp.rdata = 0;
 
     switch ( r_dcache_fsm.read() ) 
     {
     case DCACHE_IDLE:	// There is 8 conditions to exit the IDLE state :
-    			// 1) Long write request (DCACHE FSM)	=> DCACHE_DIRTY_***
+    			// 1) Dirty bit update (processor)	=> DCACHE_DIRTY_GET_PTE
     			// 2) Coherence request (TGT FSM) 	=> DCACHE_CC_CHECK 
     			// 3) ITLB miss request (ICACHE FSM) 	=> DCACHE_TLB_MISS
@@ -1956,6 +1938,10 @@
     			// 5) DTLB miss (processor) 		=> DCACHE_TLB_MISS
     			// 6) Cacheable read miss (processor)  	=> DCACHE_MISS_VICTIM
-    			// 7) Uncacheable read (processor) 	=> DCACHE_UNC_REQ 
-    			// 8) SC access (processor)		=> DCACHE_SC
+    			// 7) Uncacheable read (processor) 	=> DCACHE_UNC_WAIT 
+    			// 8) SC access (processor)		=> DCACHE_SC_WAIT
+                        //
+                        // The dtlb is unconditionally accessed to translate the
+                        // virtual adress from processor.
+                        //
                         // There is 4 configurations to access the cache, 
                         // depending on the pipe-line state, defined 
@@ -1971,18 +1957,12 @@
         // Handling P2 pipe-line stage 
         // Inputs are r_dcache_p1_* registers.
-        // Three actions are executed in this P2 stage:
-        // - If r_dcache_p1_updt_cache is true, we update the local copy in dcache.
-        // - If the modified cache line has copies in TLBs, we launch a TLB invalidate
-        //   operation, that is blocking for the processor, because we switch to
-        //   DCACHE_INVAL_TLB 
-        // - If the PTE dirty bit must be updated, we start a "long write", that is 
-        //   blocking for the processor, because we switch to the DCACHE_DIRTY_SET_DIRTY
-
-        bool long_write_set_dirty = false;	// default value
-        bool tlb_inval_required	  = false;	// default value
+        // If r_dcache_p1_valid is true, we update the local copy in dcache.
+        // If the modified cache line has copies in TLBs, we launch a TLB invalidate
+        // operation, going to DCACHE_INVAL_TLB_SCAN state.
+
+        bool tlb_inval_required = false;
 
         if ( r_dcache_p1_valid.read() )		// P2 stage activated
         {
-            bool     cache_updt = r_dcache_p1_updt_cache.read();
             size_t   way        = r_dcache_p1_cache_way.read();
             size_t   set        = r_dcache_p1_cache_set.read();
@@ -1991,57 +1971,25 @@
             vci_be_t be         = r_dcache_p1_be.read();
 
-            // update dcache if required
-            if ( cache_updt )	
-            {
-                r_dcache.write( way,
-                                set,
-                                word,
-                                wdata,
-                                be );
+            r_dcache.write( way,
+                            set,
+                            word,
+                            wdata,
+                            be );
 #ifdef INSTRUMENTATION
 m_cpt_dcache_data_write++; 
 #endif
-                // cache update can require itlb & dtlb inval
-                bool	inval_itlb = false;
-                bool	inval_dtlb = false;
-   
-                if ( (r_mmu_mode.read() & DATA_TLB_MASK) and r_dcache_in_dtlb[way*m_dcache_sets+set] ) 
-                {
-	            r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
-                    inval_dtlb = true;
-                }
-                if ( (r_mmu_mode.read() & INS_TLB_MASK) and r_dcache_in_itlb[m_dcache_sets*way+set] )
-	        {	
-	            r_dcache_in_itlb[way*m_dcache_sets+set] = false;
-                    inval_itlb = true;
-                }
-                if ( inval_itlb or inval_dtlb ) 
-                {
-                    tlb_inval_required       = true;
-	            r_dcache_itlb_inval_req  = inval_itlb;
-	            r_dcache_dtlb_inval_req  = inval_dtlb;
-	            r_dcache_tlb_inval_count = 0;
-	            r_dcache_tlb_inval_line  = r_dcache_p1_paddr.read()>>(uint32_log2(m_dcache_words<<2)); 
-                }
-            } // end dcache update
-
-            // checking if dirty bit update is required
-            if ( r_dcache_p1_set_dirty.read() )  
-            {
-                long_write_set_dirty  = true;
-                r_dcache_p2_way   = r_dcache_p1_tlb_way.read();	
-                r_dcache_p2_set   = r_dcache_p1_tlb_set.read();	
-                // The PTE physical address is the concatenation of the nline value (from dtlb),
-                // with the word index (obtained from the proper bits of the virtual address)
-                if ( r_dcache_p1_tlb_big.read() )	// PTE1
-                {
-                    r_dcache_p2_pte_paddr = (paddr_t)(r_dcache_p1_tlb_nline.read()*(m_dcache_words<<2)) |
-                                            (paddr_t)((r_dcache_p1_vaddr.read()>>19) & 0x3c);
-                }
-                else					// PTE2
-                {
-                    r_dcache_p2_pte_paddr = (paddr_t)(r_dcache_p1_tlb_nline.read()*(m_dcache_words<<2)) |
-                                            (paddr_t)((r_dcache_p1_vaddr.read()>>9) & 0x38);
-                }
+            // cache update after a WRITE hit can require itlb & dtlb inval or flush
+            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
+            {
+                tlb_inval_required       = true;
+	        r_dcache_tlb_inval_count = 0;
+	        r_dcache_tlb_inval_line  = r_dcache_p1_paddr.read()>>(uint32_log2(m_dcache_words<<2)); 
+	        r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+            }
+            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
+            {
+                r_itlb.reset();
+                r_dtlb.reset();
+	        r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
             }
 
@@ -2049,14 +1997,10 @@
 if ( m_debug_dcache_fsm )
 {
-    if ( cache_updt ) 
-        std::cout << "  <PROC.DCACHE_IDLE> P2 stage: cache update" << std::dec
-                  << " / way = " << way 
-                  << " / set = " << set 
-                  << " / word = " << word << std::hex
-                  << " / wdata = " << wdata
-                  << " / be = " << be << std::endl;
-    if ( long_write_set_dirty ) 
-        std::cout << "  <PROC.DCACHE_IDLE> P2 stage: dirty bit update required"
-                  << " / pte_paddr = " << std::hex << r_dcache_p2_pte_paddr.read() << std::endl;
+    std::cout << "  <PROC.DCACHE_IDLE> Cache update in P2 stage" << std::dec
+              << " / WAY = " << way 
+              << " / SET = " << set 
+              << " / WORD = " << word << std::hex
+              << " / DATA = " << wdata
+              << " / BE = " << be << std::endl;
 }
 #endif
@@ -2066,14 +2010,13 @@
         // Handling P1 pipe-line stage 
         // Inputs are r_dcache_p0_* registers.
-        // - We must write into wbuf and test the hit in dcache.
-        // If the write request is not cacheable, and there is a pending
-        // non cacheable write, or if the write buffer is full, we break:
-        // The P0 and P1 pipe-line stages are frozen until the write
-        // request registration is possible, but the P2 stage is not frozen.
-        // - The r_dcache_p1_valid bit activating the P2 pipe-line stage
-        // must be computed at all cycles. The P2 stage must be activated
-        // if there is local copy in dcache, or if the PTE dirty bit must be set.
-
-        if ( r_dcache_p0_valid.read() and not tlb_inval_required )  // P1 stage activated
+        // We must write into wbuf and test the hit in dcache.
+        // If the write request is non cacheable, and there is a pending
+        // non cacheable write, or if the write buffer is full, we break,
+        // because the P0 and P1 pipe-line stages are frozen until the write
+        // request registration is possible, but he P2 stage is not frozen.
+        // The r_dcache_p1_valid bit must be computed at all cycles, and 
+        // the P2 stage must be activated if there is local copy in dcache. 
+
+        if ( r_dcache_p0_valid.read() )  // P1 stage activated
         {
             // write not cacheable, and previous non cacheable write registered
@@ -2101,5 +2044,5 @@
             r_dcache_pending_unc_write = not r_dcache_p0_cacheable.read();
 
-            // read directory to detect local copy
+            // read directory to check local copy
             size_t  cache_way;
             size_t  cache_set;
@@ -2121,21 +2064,11 @@
             }
 
-            // dirty bit update requested
-            bool dirty_req = (r_mmu_mode.read() & DATA_TLB_MASK) and not r_dcache_p0_tlb_dirty.read();
-
-            // if there is a local copy or a dirty bit update requested  
-            if ( local_copy or dirty_req )
+            // store values for P2 pipe stage
+            if ( local_copy )
             {
                 r_dcache_p1_valid       = true;
-                r_dcache_p1_set_dirty   = dirty_req;
-                r_dcache_p1_updt_cache  = local_copy;
-                r_dcache_p1_vaddr       = r_dcache_p0_vaddr.read();
                 r_dcache_p1_wdata       = r_dcache_p0_wdata.read();
                 r_dcache_p1_be          = r_dcache_p0_be.read();
                 r_dcache_p1_paddr       = r_dcache_p0_paddr.read();
-                r_dcache_p1_tlb_way     = r_dcache_p0_tlb_way;
-                r_dcache_p1_tlb_set     = r_dcache_p0_tlb_set;
-                r_dcache_p1_tlb_nline   = r_dcache_p0_tlb_nline;
-                r_dcache_p1_tlb_big     = r_dcache_p0_tlb_big;
                 r_dcache_p1_cache_way   = cache_way;
                 r_dcache_p1_cache_set   = cache_set;
@@ -2152,10 +2085,9 @@
         } // end P1 stage
 
-        /////////////////////////////////////////////////////////////////////////////
+        /////////////////////////////////////////////////////////////////////////////////
         // handling P0 pipe-line stage
         // This stage is controlling r_dcache_fsm and r_dcache_p0_* registers. 
-        // The r_dcache_p0_valid flip-flop is only set in case of WRITE request.
+        // The r_dcache_p0_valid flip-flop is only set in case of a WRITE request.
         // - the TLB invalidate requests have the highest priority,
-        // - then the long write requests, 
         // - then the external coherence requests,
         // - then the itlb miss requests,
@@ -2163,14 +2095,13 @@
         // If dtlb is activated, there is an unconditionnal access to dtlb, 
         // for address translation.
-        // 1) A processor WRITE request enters the three stage pipe-line (handled
-        //    by the IDLE state), and can be completed by a "long write" if the 
-        //    PTE dirty bit must be updated in dtb, dcache and RAM.
-        // 2) A processor READ request generate a simultaneouss access to
+        // 1) A processor WRITE request is blocked if the Dirty bit mus be set, or if 
+        //    dtlb miss. If dtlb is OK, It enters the three stage pipe-line (fully 
+        //    handled by the IDLE state), and the processor request is acknowledged.
+        // 2) A processor READ or LL request generate a simultaneouss access to
         //    both dcache data and dcache directoty, using speculative PPN, but
         //    is delayed if the write pipe-line is not empty.
         //    In case of miss, we wait the VCI response in DCACHE_UNC_WAIT or 
         //    DCACHE_MISS_WAIT states.
-        // 3) A processor LL request is handled as a READ request.
-        // 4) A processor SC request is delayed until the write pipe-line is empty.
+        // 3) A processor SC request is delayed until the write pipe-line is empty.
         //    A VCI SC transaction is launched, and we wait the VCI response in
         //    DCACHE_SC_WAIT state. It can be completed by a "long write" if the 
@@ -2186,12 +2117,4 @@
             r_dcache_p0_valid = false;
         }
-
-        // long write request
-        else if ( long_write_set_dirty )
-        {
-            r_dcache_fsm = DCACHE_DIRTY_TLB_SET;
-            r_dcache_p0_valid = false;
-        }
-
         // external coherence request 
         else if ( r_tgt_dcache_req.read() )   
@@ -2245,5 +2168,4 @@
 
             // systematic dtlb access using virtual address
-
             paddr_t	tlb_paddr;
             pte_info_t 	tlb_flags; 
@@ -2253,5 +2175,5 @@
             bool	tlb_hit;    	
 
-            if ( r_mmu_mode.read() & DATA_TLB_MASK )	// TLB activated
+            if ( r_mmu_mode.read() & DATA_TLB_MASK )	// DTLB activated
             {
                 tlb_hit = r_dtlb.translate( m_dreq.addr,
@@ -2264,10 +2186,4 @@
 m_cpt_dtlb_read++;
 #endif
-                // register dtlb outputs
-                r_dcache_p0_tlb_nline = tlb_nline;
-                r_dcache_p0_tlb_way   = tlb_way;
-                r_dcache_p0_tlb_set   = tlb_set;
-                r_dcache_p0_tlb_dirty = tlb_flags.d;
-                r_dcache_p0_tlb_big   = tlb_flags.b;
             }
             else
@@ -2524,4 +2440,10 @@
                             m_drsp.error   = true;
                             m_drsp.rdata   = 0;
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC.DCACHE_IDLE> HIT in dtlb, but privilege violation" << std::endl;
+}
+#endif
                         }
                         else if ( not tlb_flags.w and 
@@ -2534,4 +2456,10 @@
                             m_drsp.error   = true;
                             m_drsp.rdata   = 0;
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC.DCACHE_IDLE> HIT in dtlb, but writable violation" << std::endl;
+}
+#endif
                         }
                         else
@@ -2541,5 +2469,5 @@
 
                         // physical address
-                        paddr       = tlb_paddr;
+                        paddr = tlb_paddr;
                     }
                     else						// tlb miss
@@ -2599,4 +2527,10 @@
                                 m_drsp.valid   = true;
                                 m_drsp.rdata   = cache_rdata;
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC.DCACHE_IDLE> HIT in dcache" << std::endl;
+}
+#endif
                             }
                         }
@@ -2620,50 +2554,99 @@
 
                     // WRITE request:
-                    // The write request arguments have been registered in r_dcache_p0 registers.
-                    // The physical address has been computed and registered.
-                    // We acknowledge the processor request and activate the P1 pipeline stage.
+                    // If the TLB is activated and the PTE Dirty bit is not set, we stall 
+                    // the processor and set the Dirty bit before handling the write request. 
+                    // If we don't need to set the Dirty bit, we can acknowledge
+                    // the processor request, as the write arguments (including the
+                    // physical address) are registered in r_dcache_p0 registers:
+                    // We simply activate the P1 pipeline stage.
                     else if ( m_dreq.type == iss_t::DATA_WRITE )
                     {
-
+                        if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
+                              and not tlb_flags.d )		// Dirty bit must be set
+                        {
+                            // The PTE physical address is obtained from the nline value (dtlb),
+                            // and the word index (proper bits of the virtual address)
+                            if ( tlb_flags.b )	// PTE1
+                            {
+                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
+                                                       (paddr_t)((m_dreq.addr>>19) & 0x3c);
+                            }
+                            else		// PTE2
+                            {
+                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
+                                                       (paddr_t)((m_dreq.addr>>9) & 0x38);
+                            }
+                            r_dcache_fsm      = DCACHE_DIRTY_GET_PTE;
+                            r_dcache_p0_valid = false;
+                        }
+                        else					// Write request accepted
+                        {
 #ifdef INSTRUMENTATION
 m_cpt_data_write++;
 #endif
-                        m_drsp.valid      = true;
-                        m_drsp.rdata      = 0;
-                        r_dcache_p0_valid = true;
+                            m_drsp.valid      = true;
+                            m_drsp.rdata      = 0;
+                            r_dcache_p0_valid = true;
+                        }
                     } // end WRITE
  
                     // SC request:
                     // The SC requests are taken only if the write pipe-line is empty.
+                    // - if there is no valid registered LL, we just return rdata = 1 
+                    //   (atomic access failed) and the SC transaction is completed.
                     // - if a valid LL reservation (with the same address) is registered, 
-                    // we request a SC transaction to CMD FSM and go to the DCACHE_SC_WAIT state
-                    // that will directly return the response to the processor, invalidate 
-                    // the LL reservation, and set the Dirty bit if required.
-                    // We don't check a possible write hit in dcache, as the cache update 
-                    // is done by the coherence transaction...
-                    // - if there is no valid registered LL, we just stay in IDLE state,
-                    // and return 1 (atomic access failed)
+                    //   we test if a DIRTY bit update is required.
+                    //   If the TLB is activated and the PTE Dirty bit is not set, we stall 
+                    //   the processor and set the Dirty bit before handling the write request. 
+                    //   If we don't need to set the Dirty bit, we request a SC transaction 
+                    //   to CMD FSM and go to DCACHE_SC_WAIT state, that will return 
+                    //   the response to the processor. 
+                    //   We don't check a possible write hit in dcache, as the cache update 
+                    //   is done by the coherence transaction induced by the SC...
                     else if ( ( m_dreq.type == iss_t::DATA_SC )
                         and not r_dcache_p0_valid.read() and not r_dcache_p1_valid.read() )
                     {
-
+                        if ( (r_dcache_ll_vaddr.read() != m_dreq.addr)
+                             or not r_dcache_ll_valid.read() ) 	// no valid registered LL
+                        { 
 #ifdef INSTRUMENTATION
 m_cpt_data_sc++;
 #endif
-                        // test if valid registered LL
-                        if ( r_dcache_ll_valid.read() and (r_dcache_ll_vaddr.read() == m_dreq.addr))
-                        { 
-                            r_dcache_vci_paddr  = paddr;
-                            r_dcache_vci_sc_req = true;
-                            r_dcache_vci_sc_old = r_dcache_ll_data.read();
-                            r_dcache_vci_sc_new = m_dreq.wdata;
-                            r_dcache_fsm        = DCACHE_SC_WAIT;
-                        }
-                        else                                    // no registered LL
-                        {
-                            
                             m_drsp.valid        = true;
                             m_drsp.rdata        = 1;
                             r_dcache_ll_valid   = false;
+                        }
+                        else					// valid registered LL
+                        {
+                            if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
+                                  and not tlb_flags.d )			// Dirty bit must be set
+                            {
+                                // The PTE physical address is obtained from the nline value (dtlb),
+                                // and the word index (proper bits of the virtual address)
+                                if ( tlb_flags.b )	// PTE1
+                                {
+                                    r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
+                                                           (paddr_t)((m_dreq.addr>>19) & 0x3c);
+                                }
+                                else			// PTE2
+                                {
+                                    r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
+                                                           (paddr_t)((m_dreq.addr>>9) & 0x38);
+                                }
+                                r_dcache_fsm           = DCACHE_DIRTY_GET_PTE;
+                            }
+                            else					// SC request accepted
+                            {
+#ifdef INSTRUMENTATION
+m_cpt_data_sc++;
+#endif
+      
+                                r_dcache_vci_paddr  = paddr;
+                                r_dcache_vci_sc_req = true;
+                                r_dcache_vci_sc_old = r_dcache_ll_data.read();
+                                r_dcache_vci_sc_new = m_dreq.wdata;
+                                r_dcache_ll_valid   = false;
+                                r_dcache_fsm        = DCACHE_SC_WAIT;
+                            }
                         }
                         r_dcache_p0_valid = false;
@@ -2797,6 +2780,9 @@
   
             }
-            else if( entry & PTE_T_MASK ) 	//  PTD : access PT2
-            {
+            else if( entry & PTE_T_MASK ) 	//  PTD : me must access PT2
+            {
+                // mark the cache line ac containing a PTD
+                r_dcache_contains_ptd[m_dcache_sets*way+set] = true;
+
                 // register bypass
                 if ( r_dcache_tlb_ins.read() )		// itlb
@@ -2828,8 +2814,7 @@
 #endif
             }
-            else			//  PTE1 :  update the TLB
-            {
-                if ( r_dcache_tlb_ins.read() ) r_dcache_in_itlb[m_icache_sets*way+set] = true;
-                else                           r_dcache_in_dtlb[m_dcache_sets*way+set] = true;
+            else			//  PTE1 :  we must update the TLB
+            {
+                r_dcache_in_tlb[m_icache_sets*way+set] = true;
                 r_dcache_tlb_pte_flags  = entry;
                 r_dcache_tlb_cache_way  = way;
@@ -3050,8 +3035,7 @@
 #endif
             }
-            else				// mapped : update the TLB
-            {
-                if ( r_dcache_tlb_ins.read() ) r_dcache_in_itlb[m_icache_sets*way+set] = true;
-                else                           r_dcache_in_dtlb[m_dcache_sets*way+set] = true;
+            else				// mapped : we must update the TLB
+            {
+                r_dcache_in_tlb[m_dcache_sets*way+set] = true;
                 r_dcache_tlb_pte_flags  = pte_flags;
                 r_dcache_tlb_pte_ppn    = pte_ppn;
@@ -3384,10 +3368,10 @@
             if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) )	// last slot
             {
-                r_dtlb.reset();      // global entries are invalidated
-                r_itlb.reset();      // global entries are invalidated
+                r_dtlb.reset();    
+                r_itlb.reset(); 
                 for (size_t line = 0; line < m_dcache_ways*m_dcache_sets; line++)
                 {
-                    r_dcache_in_itlb[line] = false;
-                    r_dcache_in_dtlb[line] = false;
+                    r_dcache_in_tlb[line]       = false;
+                    r_dcache_contains_ptd[line] = false;
                 }
                 r_dcache_fsm = DCACHE_IDLE;
@@ -3441,4 +3425,14 @@
             r_dcache_fsm        = DCACHE_TLB_MISS; 
         } 
+  
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC.DCACHE_XTN_DC_INVAL_VA> Compute physical address" << std::hex
+              << " / VADDR = " << r_dcache_p0_wdata.read()
+              << " / PADDR = " << paddr << std::endl;
+}
+#endif
+
         break;
     }
@@ -3472,8 +3466,19 @@
             m_drsp.valid        = true;
         }
+
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC.DCACHE_XTN_DC_INVAL_PA> Test hit in dcache" << std::hex
+              << " / PADDR = " << r_dcache_p0_paddr.read() << std::dec
+              << " / HIT = " << hit
+              << " / SET = " << set
+              << " / WAY = " << way << std::endl;
+}
+#endif
         break;
     }
     ////////////////////////////
-    case DCACHE_XTN_DC_INVAL_GO:  // In this state, we invalidate the cache line & cleanup
+    case DCACHE_XTN_DC_INVAL_GO:  // In this state, we invalidate the cache line 
         			  // Blocked if previous cleanup not completed
                                   // Test if itlb or dtlb inval is required    
@@ -3484,8 +3489,6 @@
             size_t	way        = r_dcache_xtn_way.read();
             size_t	set        = r_dcache_xtn_set.read();
-            bool	inval_itlb = false;
-            bool	inval_dtlb = false;
    
-            r_icache.inval( way,
+            r_dcache.inval( way,
                             set,
                             &nline );
@@ -3495,37 +3498,39 @@
 	    r_dcache_cleanup_line = nline;
 	    
-            // possible itlb & dtlb invalidate requests 
-
-            if ( (r_mmu_mode.read() & DATA_TLB_MASK) and r_dcache_in_dtlb[way*m_dcache_sets+set] ) 
-            {
-	        r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
-                inval_dtlb = true;
-            }
-            if ( (r_mmu_mode.read() & INS_TLB_MASK) and r_dcache_in_itlb[m_dcache_sets*way+set] )
-	    {	
-	        r_dcache_in_itlb[way*m_dcache_sets+set] = false;
-                inval_itlb = true;
-            }
-
-            // no valid response until itlb & dtlb invalidated
-            if ( inval_itlb or inval_dtlb ) 
-            {
-	        r_dcache_itlb_inval_req  = inval_itlb;
-	        r_dcache_dtlb_inval_req  = inval_dtlb;
+            // possible itlb & dtlb invalidate 
+            if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
+            {
 	        r_dcache_tlb_inval_line  = nline;
 	        r_dcache_tlb_inval_count = 0;
                 r_dcache_fsm_save        = DCACHE_XTN_DC_INVAL_END;
                 r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+	        r_dcache_in_tlb[way*m_dcache_sets+set] = false;
 	    }
-            else
-            {
+            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
+            {
+                r_itlb.reset();
+                r_dtlb.reset();
+	        r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
                 r_dcache_fsm = DCACHE_IDLE;
                 m_drsp.valid = true;
             }
+            else
+            {
+                r_dcache_fsm = DCACHE_IDLE;
+                m_drsp.valid = true;
+            }
+
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC.DCACHE_XTN_DC_INVAL_GO> Actual dcache inval" << std::hex
+              << " / NLINE = " << nline << std::endl;
+}
+#endif
 	}
         break;
     }
     //////////////////////////////
-    case DCACHE_XTN_DC_INVAL_END:  	// waiting completion of itlb and dtlb invalidate
+    case DCACHE_XTN_DC_INVAL_END:  	// send response to processor XTN request
     {
         r_dcache_fsm = DCACHE_IDLE;
@@ -3578,6 +3583,6 @@
     {
         paddr_t	nline;
-        size_t	way = r_dcache_miss_way.read();
-        size_t	set = r_dcache_miss_set.read();
+        size_t	way        = r_dcache_miss_way.read();
+        size_t	set        = r_dcache_miss_set.read();
 
         r_dcache.inval( way, 
@@ -3585,29 +3590,23 @@
                         &nline );
 
-        // if itlb & dtlb invalidate are required 
+        // if selective itlb & dtlb invalidate are required 
         // the miss response is not handled before invalidate completed
-        if ( (r_mmu_mode.read() & DATA_TLB_MASK) and 
-             ( r_dcache_in_itlb[way*m_dcache_sets+set] or 
-               r_dcache_in_dtlb[m_dcache_sets*way+set] ) )
-	{	
-	    r_dcache_tlb_inval_line = r_dcache_vci_paddr.read() >> (uint32_log2(m_dcache_words)+2);
-	    r_dcache_itlb_inval_req  = r_dcache_in_itlb[way*m_dcache_sets+set];
-	    r_dcache_in_itlb[way*m_dcache_sets+set] = false;
-	    r_dcache_dtlb_inval_req  = r_dcache_in_dtlb[way*m_dcache_sets+set];
-	    r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
-            r_dcache_fsm = DCACHE_MISS_INVAL_WAIT;
-	}
+        if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
+        {
+            r_dcache_tlb_inval_line  = nline;
+            r_dcache_tlb_inval_count = 0;
+            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+            r_dcache_fsm_save        = DCACHE_MISS_WAIT;
+            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+        }
+        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
+        {
+            r_itlb.reset();
+            r_dtlb.reset();
+            r_dcache_fsm             = DCACHE_MISS_WAIT;
+        }
         else
         {
-            r_dcache_fsm = DCACHE_MISS_WAIT;
-        }
-        break;
-    }
-    ////////////////////////////
-    case DCACHE_MISS_INVAL_WAIT:  // waiting completion of itlb / dtlb invalidate
-    {
-        if ( (not r_dcache_itlb_inval_req.read()) or (not r_dcache_dtlb_inval_req.read()) )
-        {
-            r_dcache_fsm = DCACHE_MISS_WAIT;
+            r_dcache_fsm             = DCACHE_MISS_WAIT;
         }
         break;
@@ -3719,14 +3718,15 @@
                                                 // pop the FIFO and update the cache 
                                                 // update the directory at the last word
-                                                // send a response to ICACHE FSM 
-                                                // in case of itlb miss
-            {
+            {
+                 size_t	way  = r_dcache_miss_way.read();
+                 size_t	set  = r_dcache_miss_set.read();
+                 size_t word = r_dcache_miss_word.read();
 
 #ifdef INSTRUMENTATION
 m_cpt_dcache_data_write++;
 #endif
-                r_dcache.write( r_dcache_miss_way.read(),
-                                r_dcache_miss_set.read(),
-                                r_dcache_miss_word.read(),
+                r_dcache.write( way,
+                                set,
+                                word,
                                 r_vci_rsp_fifo_dcache.read());
 
@@ -3734,5 +3734,5 @@
                 r_dcache_miss_word = r_dcache_miss_word.read() + 1;
                
-                // if last word, update directory, set in_itlb & in_dtlb bits
+                // if last word, update directory, set in_tlb & contains_ptd bits
                 if ( r_dcache_miss_word.read() == (m_dcache_words - 1) ) 
                 {
@@ -3744,4 +3744,7 @@
                                                 r_dcache_miss_way.read(),
                                                 r_dcache_miss_set.read() );
+
+                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+                    r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
                     
                     if      (r_dcache_miss_type.read()==PTE1_MISS) r_dcache_fsm = DCACHE_TLB_PTE1_GET; 
@@ -3818,5 +3821,4 @@
     ////////////////////
     case DCACHE_SC_WAIT:	// waiting VCI response after a processor SC request
-                                // a long write is launched if dirty bit must be set
     {
         // external coherence request
@@ -3840,59 +3842,24 @@
 	else if ( r_vci_rsp_fifo_dcache.rok() )     	// response available
 	{
-            bool sc_success = (r_vci_rsp_fifo_dcache.read() == 0);
             vci_rsp_fifo_dcache_get = true;     
-
-            if ( sc_success and not r_dcache_p0_tlb_dirty.read() )	// Dirty bit must be set
-            {
-                // The PTE physical address is the concatenation of the nline value (from dtlb),
-                // with the word index (obtained from the proper bits of the virtual address)
-                if ( r_dcache_p0_tlb_big.read() )	// PTE1
-                {
-                    r_dcache_p2_pte_paddr = (paddr_t)(r_dcache_p0_tlb_nline.read()*(m_dcache_words<<2)) |
-                                            (paddr_t)((r_dcache_p0_vaddr.read()>>19) & 0x3c);
-                }
-                else					// PTE2
-                {
-                    r_dcache_p2_pte_paddr = (paddr_t)(r_dcache_p0_tlb_nline.read()*(m_dcache_words<<2)) |
-                                            (paddr_t)((r_dcache_p0_vaddr.read()>>9) & 0x38);
-                }
-                r_dcache_p2_sc_success = sc_success;
-                r_dcache_p2_way        = r_dcache_p0_tlb_way.read();
-                r_dcache_p2_set        = r_dcache_p0_tlb_set.read();
-                r_dcache_fsm           = DCACHE_DIRTY_TLB_SET;
-         
-            }
-            else
-            {
-	        m_drsp.valid            = true;
-	        m_drsp.rdata            = r_vci_rsp_fifo_dcache.read();
-                r_dcache_fsm            = DCACHE_IDLE;
-            }
+	    m_drsp.valid            = true;
+	    m_drsp.rdata            = r_vci_rsp_fifo_dcache.read();
+            r_dcache_fsm            = DCACHE_IDLE;
 	}	
         break;
     }
     //////////////////////////
-    case DCACHE_DIRTY_TLB_SET:		// Enter this sub_fsm in case of long write:
-                                        // - in case of WRITE request (r_dcache_p2_type_sc == false)
-                                        // - in case of SC request    (r_dcache_p2_type_sc == true)
-					// Inputs arguments are:
-                                        // - r_dcache_p2_way,
-                                        // - r_dcache_p2_set, 
-                                        // - r_dcache_p2_pte_paddr,
-                                        // - r_dcache_p2_type_sc, 
-                                        // - r_dcache_p2_sc_success,
-                                        // In this first state, we set PTE dirty bit in dtlb
-					// and get PTE in dcache
-    {
-        // set dirty bit in dtlb
-        r_dtlb.set_dirty( r_dcache_p2_way.read(),
-                          r_dcache_p2_set.read() );
-
+    case DCACHE_DIRTY_GET_PTE:		// This sub_fsm set the PTE Dirty bit in memory 
+                                        // before handling a processor WRITE or SC request  
+					// Input argument is r_dcache_dirty_paddr
+                                        // In this first state, we get PTE value in dcache
+                                        // and post a SC request to CMD FSM
+    {
         // get PTE in dcache
-        uint32_t pte = 0;
+        uint32_t pte;
         size_t   way;
         size_t   set;
-        size_t   word;
-        bool     hit = r_dcache.read( r_dcache_p2_pte_paddr.read(),
+        size_t   word;	// unused
+        bool     hit = r_dcache.read( r_dcache_dirty_paddr.read(),
                                       &pte,
                                       &way,
@@ -3903,134 +3870,94 @@
 m_cpt_dcache_dir_read++;
 #endif;
+        assert( hit and "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
+
+        // request sc transaction to CMD_FSM
+        r_dcache_dirty_way  = way; 
+        r_dcache_dirty_set  = set; 
+        r_dcache_vci_sc_req = true;
+        r_dcache_vci_paddr  = r_dcache_dirty_paddr.read();
+        r_dcache_vci_sc_old = pte;
+        r_dcache_vci_sc_new = pte | PTE_D_MASK;
+        r_dcache_fsm        = DCACHE_DIRTY_SC_WAIT;
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC.DCACHE_DIRTY_TLB_SET> Set dirty bit in dtlb:" << std::dec
-              << " / tlb_set = " << r_dcache_p2_set.read()
-              << " / tlb_way = " << r_dcache_p2_way.read() << std::endl;
-    r_dtlb.printTrace();
-    std::cout << "      and get PTE in dcache" << std::hex
-              << " / PADDR = " << r_dcache_p2_pte_paddr.read() 
-              << " / PTE = " << pte << std::dec
-              << " / set = " << set
-              << " / way = " << way << std::endl;
+    std::cout << "  <PROC.DCACHE_DIRTY_GET_PTE> Get PTE in dcache" << std::hex
+              << " / PTE_PADDR = " << r_dcache_dirty_paddr.read() 
+              << " / PTE_VALUE = " << pte << std::dec 
+              << " / CACHE_SET = " << set
+              << " / CACHE_WAY = " << way << std::endl;
 }
 #endif
-        assert( hit and "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
-
-        r_dcache_p2_way       = way;			// register pte way in dcache
-        r_dcache_p2_set       = set;			// register pte set in dcache;
-        r_dcache_p2_word      = word;			// register pte word in dcache;
-        r_dcache_p2_pte_value = pte;			// register pte value
-        r_dcache_fsm          = DCACHE_DIRTY_CACHE_SET;
-        break;
-    }
-    ////////////////////////////
-    case DCACHE_DIRTY_CACHE_SET:	// set PTE dirty bit in dcache
-                                        // request SC tranansaction to CMD FSM 
-    {
-	// set PTE dirty bit in dcache
-        r_dcache.write( r_dcache_p2_way.read(),
-                        r_dcache_p2_set.read(),
-                        r_dcache_p2_word.read(),
-                        r_dcache_p2_pte_value.read() | PTE_D_MASK,
-                        0xF );
-
-#ifdef INSTRUMENTATION
-m_cpt_dcache_data_write++;
-#endif
-        // request sc transaction to CMD_FSM
-        r_dcache_vci_sc_req = true;
-        r_dcache_vci_paddr  = r_dcache_p2_pte_paddr.read();
-        r_dcache_vci_sc_old = r_dcache_p2_pte_value.read();
-        r_dcache_vci_sc_new = r_dcache_p2_pte_value.read() | PTE_D_MASK;
-        r_dcache_fsm        = DCACHE_DIRTY_SC_WAIT;    
+        break;
+    }
+    //////////////////////////
+    case DCACHE_DIRTY_SC_WAIT:		// wait completion of SC for PTE Dirty bit
+                                        // If the PTE update is a success, return to IDLE state.
+                                        // If the PTE update is a failure, invalidate the cache line
+                                        // in DCACHE and invalidate the matching TLB entries.
+    {
+        // external coherence request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            break;
+        }
+
+        if ( r_vci_rsp_data_error.read() )	// bus error
+        {
+            std::cout << "BUS ERROR in DCACHE_DIRTY_SC_WAIT state" << std::endl;
+            std::cout << "This should not happen in this state" << std::endl;
+            exit(0);
+        }
+        else if ( r_vci_rsp_fifo_dcache.rok() )	// response available
+        {
+            vci_rsp_fifo_dcache_get = true;
+            if ( r_vci_rsp_fifo_dcache.read() == 0 )	// exit if dirty bit update atomic
+            {
+                r_dcache_fsm = DCACHE_IDLE;
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC.DCACHE_DIRTY_CACHE_SET> Set PTE dirty bit in dcache"
-              << " / way = " << r_dcache_p2_way.read()
-              << " / set = " << r_dcache_p2_set.read() 
-              << " / word = " << r_dcache_p2_word.read() << std::endl;
-    std::cout << "   and request SC transaction for dirty bit update"
-              << " / address = " << r_dcache_p2_pte_paddr.read()
-              << " / old = " << r_dcache_p2_pte_value.read()
-              << " / new = " << (r_dcache_p2_pte_value.read() | PTE_D_MASK) << std::endl;
+    std::cout << "  <PROC.DCACHE_DIRTY_SC_WAIT> Dirty bit successfully set"
+              << std::endl;
 }
 #endif
-        break;
-    }
-    //////////////////////////
-    case DCACHE_DIRTY_SC_WAIT:		// wait completion of SC for PTE Dirty bit
-                                        // if atomic, write completed : return to IDLE state
-                                        // else, read the mofified PTE to retry the SC
-    {
-        // external coherence request
-        if ( r_tgt_dcache_req ) 
-        {
-            r_dcache_fsm = DCACHE_CC_CHECK;
-            r_dcache_fsm_save = r_dcache_fsm;
-            break;
-        }
-
-        if ( r_vci_rsp_data_error.read() )	// bus error
-        {
-            std::cout << "BUS ERROR in DCACHE_DIRTY_SC_WAIT state" << std::endl;
-            std::cout << "This should not happen in this state" << std::endl;
-            exit(0);
-        }
-        else if ( r_vci_rsp_fifo_dcache.rok() )	// response available
-        {
-            vci_rsp_fifo_dcache_get = true;
-            if ( r_vci_rsp_fifo_dcache.read() == 0 )	// exit if dirty bit update atomic
-            {
-                if ( r_dcache_p2_type_sc.read() )	// long write for SC request
+            }
+            else				// invalidate the cache line and TLBs
+            {
+                paddr_t	nline;
+                size_t  way = r_dcache_dirty_way.read();
+                size_t  set = r_dcache_dirty_set.read();
+
+                r_dcache.inval( r_dcache_dirty_way.read(), 
+                                r_dcache_dirty_set.read(),
+                                &nline );
+
+                if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 		// contains PTE
                 {
-                    m_drsp.valid = true;
-                    m_drsp.rdata = ( r_dcache_p2_sc_success.read() ? 0 : 1 ); 
+                    r_dcache_tlb_inval_line  = nline;
+                    r_dcache_tlb_inval_count = 0;
+                    r_dcache_fsm_save        = DCACHE_IDLE;
+                    r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+                }  
+                if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// contains PTD
+                {
+                    r_itlb.reset();
+                    r_dtlb.reset();
                     r_dcache_fsm = DCACHE_IDLE;
                 }
-                else					// long write for WRITE request
-                {
-                    r_dcache_fsm = DCACHE_IDLE;
-                }
-            }
-            else					// retry if dirty bit update failed
-            {
-                r_dcache_vci_paddr   = r_dcache_p2_pte_paddr;
-                r_dcache_vci_unc_req = true;
-                r_dcache_vci_unc_be  = 0xF;
-                r_dcache_fsm         = DCACHE_DIRTY_UNC_WAIT;
-            }
-        }
-        break;
-    }
-    ///////////////////////////
-    case DCACHE_DIRTY_UNC_WAIT:		// wait completion of PTE read
-                                        // and retry a SC request to
-                                        // set the dirty bit in the PTE
-    {
-        // external coherence request
-        if ( r_tgt_dcache_req ) 
-        {
-            r_dcache_fsm = DCACHE_CC_CHECK;
-            r_dcache_fsm_save = r_dcache_fsm;
-            break;
-        }
-
-        if ( r_vci_rsp_data_error.read() )	// bus error
-        {
-            std::cout << "BUS ERROR in DCACHE_DIRTY_UNC_WAIT state" << std::endl;
-            std::cout << "This should not happen in this state" << std::endl;
-            exit(0);
-        }
-        if ( r_vci_rsp_fifo_dcache.rok() )	// PTE available
-        {
-            r_dcache_vci_sc_req = true;
-            r_dcache_vci_sc_old = r_vci_rsp_fifo_dcache.read();
-            r_dcache_vci_sc_new = r_vci_rsp_fifo_dcache.read() | PTE_D_MASK;
-            r_dcache_fsm        = DCACHE_DIRTY_SC_WAIT;    
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC.DCACHE_DIRTY_SC_WAIT> PTE modified : Inval cache line & TLBs"
+              << std::endl;
+}
+#endif
+            }
         }
         break;
@@ -4128,6 +4055,4 @@
         size_t	way        = r_dcache_cc_way.read();
         size_t	set        = r_dcache_cc_set.read();
-        bool    inval_itlb = false;
-        bool    inval_dtlb = false;
 
         r_dcache.inval( way, 
@@ -4135,43 +4060,33 @@
                         &nline );
 	    
-        // possible itlb & dtlb invalidate requests 
-
-        if ( (r_mmu_mode.read() & DATA_TLB_MASK) and r_dcache_in_dtlb[way*m_dcache_sets+set] ) 
-        {
-            r_dtlb.reset_bypass(nline);
-            r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
-            inval_dtlb = true;
-        }
-        if ( (r_mmu_mode.read() & INS_TLB_MASK) and r_dcache_in_itlb[m_dcache_sets*way+set] )
-        {	
-            r_itlb.reset_bypass(nline);
-            r_dcache_in_itlb[way*m_dcache_sets+set] = false;
-            inval_itlb = true;
-        }
-
-        if ( inval_itlb or inval_dtlb ) // no valid response until itlb / dtlb invalidated
-        {
-            r_dcache_itlb_inval_req  = inval_itlb;
-            r_dcache_dtlb_inval_req  = inval_dtlb;
+        // possible itlb & dtlb invalidate 
+        if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 			// selective inval
+        {
             r_dcache_tlb_inval_line  = nline;
             r_dcache_tlb_inval_count = 0;
             r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
-        }
-        else
-        {
+            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+        }
+        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// flush
+        {
+            r_itlb.reset();
+            r_dtlb.reset();
             r_tgt_dcache_rsp = true;
             r_tgt_dcache_req = false;
             r_dcache_fsm     = r_dcache_fsm_save.read();
         }
+        else								// no inval
+        {
+            r_tgt_dcache_rsp = true;
+            r_tgt_dcache_req = false;
+            r_dcache_fsm     = r_dcache_fsm_save.read();
+        }
 
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC.DCACHE_CC_INVAL> Invalidate cache line :" << std::dec
-	      << " way = " << way
-	      << " / set = " << set;
-    if ( inval_itlb ) std::cout << " / itlb inval required";
-    if ( inval_dtlb ) std::cout << " / dtlb inval required";
-    std::cout << std::endl;
+    std::cout << "  <PROC.DCACHE_CC_INVAL> Invalidate cache line" << std::dec
+	      << " / WAY = " << way
+	      << " / SET = " << set << std::endl;
 }
 #endif
@@ -4186,6 +4101,4 @@
         size_t	 way        = r_dcache_cc_way.read();
         size_t	 set        = r_dcache_cc_set.read();
-        bool     inval_itlb = false;
-        bool     inval_dtlb = false;
         paddr_t  nline	    = r_tgt_paddr.read() >> (uint32_log2(m_dcache_words)+2);
 
@@ -4202,33 +4115,26 @@
         if ( word == r_tgt_word_max.read() )	// last word
         {
-            // possible itlb & dtlb invalidate requests 
-
-            if ( (r_mmu_mode.read() & DATA_TLB_MASK) and r_dcache_in_dtlb[way*m_dcache_sets+set] ) 
-            {
-                r_dtlb.reset_bypass(nline);
-                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
-                inval_dtlb = true;
-            }
-            if ( (r_mmu_mode.read() & INS_TLB_MASK) and r_dcache_in_itlb[way*m_dcache_sets+set] ) 
-            {
-                r_itlb.reset_bypass(nline);
-                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
-                inval_itlb = true;
-            }
-
-            if ( inval_itlb or inval_dtlb ) // no valid response until itlb / dtlb invalidated
-            {
-                r_dcache_itlb_inval_req  = inval_itlb;
-                r_dcache_dtlb_inval_req  = inval_dtlb;
+            // possible itlb & dtlb invalidate 
+            if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 		// selective inval
+            {
                 r_dcache_tlb_inval_line  = nline;
                 r_dcache_tlb_inval_count = 0;
                 r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
-            }
-            else
-            {
+                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+            }
+            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// flush
+            {
+                r_itlb.reset();
+                r_dtlb.reset();
                 r_tgt_dcache_rsp = true;
                 r_tgt_dcache_req = false;
                 r_dcache_fsm     = r_dcache_fsm_save.read();
             }
+            else							// no inval
+            {
+                r_tgt_dcache_rsp = true;
+                r_tgt_dcache_req = false;
+                r_dcache_fsm     = r_dcache_fsm_save.read();
+            }
         }
 
@@ -4236,12 +4142,9 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC.DCACHE_CC_UPDT> Update one word :" << std::dec
-	      << " way = " << way
-	      << " / set = " << set 
-              << " / word = " << word
-              << " / value = " << std::hex << r_tgt_buf[word];
-    if ( inval_itlb ) std::cout << " / itlb inval required";
-    if ( inval_dtlb ) std::cout << " / dtlb inval required";
-    std::cout << std::endl;
+    std::cout << "  <PROC.DCACHE_CC_UPDT> Update one word" << std::dec
+	      << " / WAY = " << way
+	      << " / SET = " << set 
+              << " / WORD = " << word
+              << " / VALUE = " << std::hex << r_tgt_buf[word] << std::endl;
 }
 #endif
@@ -4250,15 +4153,18 @@
     }
     ///////////////////////////
-    case DCACHE_INVAL_TLB_SCAN:     	// scan sequencially all TLB entries for both ITLB & DTLB
+    case DCACHE_INVAL_TLB_SCAN:     	// Scan sequencially all TLB entries for both ITLB & DTLB
                                         // It makes the assumption that (m_itlb_sets == m_dtlb_sets)
                                         // and (m_itlb_ways == m_dtlb_ways)
-                                        // Caution : we enter this state when a DCACHE line is modified,
+                                        // We enter this state when a DCACHE line is modified,
                                         // and there is a copy in itlb or dtlb.
-                                        // It can be caused by a coherence transaction, a XTN inval
-                                        // or a WRITE hit.  Input arguments are:
+                                        // It can be caused by: 
+                                        // - a coherence inval or updt transaction, 
+                                        // - a line inval caused by a cache miss
+                                        // - a processor XTN inval request, 
+                                        // - a WRITE hit,
+                                        // - a Dirty bit update failure
+                                        // Input arguments are:
                                         // - r_dcache_tlb_inval_line
                                         // - r_dcache_tlb_inval_count
-                                        // - r_dcache_itlb_inval_req
-                                        // - r_dcache_dtlb_inval_req
                                         // - r_dcache_fsm_save
     {
@@ -4266,10 +4172,9 @@
         size_t	way  = r_dcache_tlb_inval_count.read()/m_itlb_sets;	// way
         size_t  set  = r_dcache_tlb_inval_count.read()%m_itlb_sets;	// set
-
-        if ( r_dcache_itlb_inval_req.read() )
-        {
-            bool ok = r_itlb.inval( line,
-                                    way,
-                                    set );
+        bool    ok;
+
+        ok = r_itlb.inval( line,
+                            way,
+                            set );
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm and ok )
@@ -4282,11 +4187,7 @@
 }
 #endif
-        }
-
-        if ( r_dcache_dtlb_inval_req.read() )
-        {
-            bool ok = r_dtlb.inval( line,
-                                    way,
-                                    set );
+        ok = r_dtlb.inval( line,
+                           way,
+                           set );
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm and ok )
@@ -4299,16 +4200,13 @@
 }
 #endif
-        }
 
         // return to the calling state when TLB inval completed
         if ( r_dcache_tlb_inval_count.read() == (m_dtlb_sets*m_dtlb_ways-1) )
         {
-            if ( r_dcache_fsm_save.read() != DCACHE_XTN_DC_INVAL_END ) // not an XTN inval
+            if ( r_tgt_dcache_req.read() ) // It's a coherence request
             {
                 r_tgt_dcache_rsp    = true;
                 r_tgt_dcache_req    = false;
             }
-            r_dcache_dtlb_inval_req = false;
-            r_dcache_itlb_inval_req = false;
             r_dcache_fsm            = r_dcache_fsm_save.read();
         }
