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 226)
+++ /trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp	(revision 227)
@@ -1422,16 +1422,10 @@
                 if ( not cache_hit )	// cache miss
                 {
-                    // in case of icache miss we send a request to CMD FSM, but we are
-                    // blocked in IDLE state if the previous cleanup is not completed
-                    if ( not r_icache_cleanup_req.read() )
-                    {
 
 #ifdef INSTRUMENTATION
 m_cpt_icache_miss++;
 #endif
-                        r_icache_fsm      = ICACHE_MISS_VICTIM;
-                        r_icache_miss_req = true;
-                    }
-                    break;
+                    r_icache_fsm      = ICACHE_MISS_VICTIM;
+                    r_icache_miss_req = true;
                 }
                 else			// cache hit
@@ -1632,27 +1626,32 @@
                                            // when the selected slot is not empty
     {
-        if ( m_ireq.valid ) m_cost_ins_miss_frz++;
-
-        bool	valid;
-        size_t  way;
-        size_t  set;
-        paddr_t victim;
-
-        valid = r_icache.victim_select(r_icache_vci_paddr.read(),
-                                       &victim, 
-                                       &way, 
-                                       &set);
-        r_icache_miss_way     = way;
-        r_icache_miss_set     = set;
-
-        if ( valid )
-        {
-            r_icache_cleanup_req  = true;
-            r_icache_cleanup_line = victim;
-            r_icache_fsm          = ICACHE_MISS_INVAL;
-        }
-        else
-        {
-            r_icache_fsm          = ICACHE_MISS_WAIT;
+        m_cost_ins_miss_frz++;
+
+        size_t index; 	// unused
+        bool hit = r_cleanup_buffer.hit( r_icache_vci_paddr.read()>>(uint32_log2(m_icache_words)+2), &index );
+        if ( not hit and not r_icache_cleanup_req.read() )
+        {
+            bool	valid;
+            size_t  	way;
+            size_t  	set;
+            paddr_t 	victim;
+
+            valid = r_icache.victim_select(r_icache_vci_paddr.read(),
+                                           &victim, 
+                                           &way, 
+                                           &set);
+            r_icache_miss_way     = way;
+            r_icache_miss_set     = set;
+
+            if ( valid )
+            {
+                r_icache_cleanup_req  = true;
+                r_icache_cleanup_line = victim;
+                r_icache_fsm          = ICACHE_MISS_INVAL;
+            }
+            else
+            {
+                r_icache_fsm          = ICACHE_MISS_WAIT;
+            }
         }
         break;
@@ -2017,5 +2016,6 @@
                 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_tlb_inval_line  = r_dcache_p1_paddr.read()>>
+                                             (uint32_log2(m_dcache_words<<2)); 
 	        r_dcache_in_tlb[way*m_dcache_sets+set] = false;
             }
@@ -2143,5 +2143,5 @@
         //    coherence transaction.   
 
-        // TLB inval required
+        // TLB inval required after a write hit
         if ( tlb_inval_required )
         {
@@ -2544,4 +2544,10 @@
 m_cpt_dcache_spec_miss++;
 #endif
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC.DCACHE_IDLE> Speculative access miss" << std::endl;
+}
+#endif
                             }
                             // if cache miss, try to get the missing line
@@ -2551,12 +2557,8 @@
 m_cpt_dcache_miss++;
 #endif
-                                // blocked in IDLE state if previous cleanup not completed
-                                if ( not r_dcache_cleanup_req.read() )
-                                {
-                                    r_dcache_vci_paddr    = paddr;
-                                    r_dcache_vci_miss_req = true;
-                                    r_dcache_miss_type    = PROC_MISS;
-                                    r_dcache_fsm          = DCACHE_MISS_VICTIM;
-                                }
+                                r_dcache_vci_paddr    = paddr;
+                                r_dcache_vci_miss_req = true;
+                                r_dcache_miss_type    = PROC_MISS;
+                                r_dcache_fsm          = DCACHE_MISS_VICTIM;
                             }
                             // if cache hit return the data
@@ -3387,6 +3389,6 @@
                                 // A cleanup request is generated for each valid line 
                                 // and we are blocked until the previous cleanup is completed
-				// Finally, both the itlb and dtlb are reset, because
-                                // all TLB entries (including global entries) must be invalidated.
+				// Finally, both the itlb and dtlb are flushed
+                                // (including global entries) 
     {
         if ( not r_dcache_cleanup_req )
@@ -3405,15 +3407,13 @@
             }
 
+            r_dcache_in_tlb[m_dcache_sets*way+set]       = false;
+            r_dcache_contains_ptd[m_dcache_sets*way+set] = false;
+
             r_dcache_flush_count = r_dcache_flush_count.read() + 1;
 
-            if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) )	// last slot
+            if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) ) // last 
             {
                 r_dtlb.reset();    
                 r_itlb.reset(); 
-                for (size_t line = 0; line < m_dcache_ways*m_dcache_sets; line++)
-                {
-                    r_dcache_in_tlb[line]       = false;
-                    r_dcache_contains_ptd[line] = false;
-                }
                 r_dcache_fsm = DCACHE_IDLE;
                 m_drsp.valid = true;
@@ -3582,30 +3582,34 @@
     }
     ////////////////////////
-    case DCACHE_MISS_VICTIM:		// Selects a victim line
-                                	// Set the r_dcache_cleanup_req flip-flop 
-                                	// when the selected slot is not empty
-    {
-        bool      valid;
-        size_t    way;
-        size_t    set;
-        paddr_t   victim;
-
-        valid = r_dcache.victim_select( r_dcache_vci_paddr.read(),
-                                        &victim,
-                                        &way,
-                                        &set );
-        r_dcache_miss_way = way;
-        r_dcache_miss_set = set;
-
-        if ( valid )
-        {
-            r_dcache_cleanup_req  = true;
-            r_dcache_cleanup_line = victim;
-            r_dcache_fsm          = DCACHE_MISS_INVAL;
-        }
-        else
-        {
-            r_dcache_fsm          = DCACHE_MISS_WAIT;
-        }
+    case DCACHE_MISS_VICTIM:		// Selects a victim line if there is no pending cleanup 
+                                        // on the missing line, and if a new cleanup can be posted.
+                                	// Set the r_dcache_cleanup_req flip-flop if required
+    {
+        size_t index; 	// unused
+        bool hit = r_cleanup_buffer.hit( r_dcache_vci_paddr.read()>>(uint32_log2(m_dcache_words)+2), &index );
+        if ( not hit and not r_dcache_cleanup_req.read() )
+        {
+            bool      valid;
+            size_t    way;
+            size_t    set;
+            paddr_t   victim;
+
+            valid = r_dcache.victim_select( r_dcache_vci_paddr.read(),
+                                            &victim,
+                                            &way,
+                                            &set );
+            r_dcache_miss_way = way;
+            r_dcache_miss_set = set;
+
+            if ( valid )
+            {
+                r_dcache_cleanup_req  = true;
+                r_dcache_cleanup_line = victim;
+                r_dcache_fsm          = DCACHE_MISS_INVAL;
+            }
+            else
+            {
+                r_dcache_fsm          = DCACHE_MISS_WAIT;
+            }
 
 #if DEBUG_DCACHE
@@ -3613,10 +3617,11 @@
 {
     std::cout << "  <PROC.DCACHE_MISS_VICTIM> Select a slot:" << std::dec
-              << " / way = "   << way 
-              << " / set = "   << set
-              << " / valid = "  << valid
-              << " / line = " << std::hex << victim << std::endl; 
+              << " / WAY = "   << way 
+              << " / SET = "   << set
+              << " / VALID = "  << valid
+              << " / LINE = " << std::hex << victim << std::endl; 
 }
 #endif
+        }
         break;
     }
@@ -3951,6 +3956,6 @@
     //////////////////////////
     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
+                                        // If PTE update is a success, return to IDLE state.
+                                        // If PTE update is a failure, invalidate cache line
                                         // in DCACHE and invalidate the matching TLB entries.
     {
@@ -3984,6 +3989,14 @@
 #endif
             }
-            else					// invalidate the cache line and TLBs
-            {
+            else					// invalidate the cache line TLBs
+            {
+
+#if DEBUG_DCACHE
+if ( m_debug_dcache_fsm )
+{
+    std::cout << "  <PROC.DCACHE_DIRTY_SC_WAIT> PTE modified : Inval cache line & TLBs"
+              << std::endl;
+}
+#endif
                 paddr_t	nline;
                 size_t  way = r_dcache_dirty_way.read();
@@ -3991,8 +4004,10 @@
 		bool hit;
 
-                hit = r_dcache.inval( r_dcache_dirty_way.read(), 
-                                r_dcache_dirty_set.read(),
-                                &nline );
+                hit = r_dcache.inval( way, 
+                                      set,
+                                      &nline );
+
 		assert(hit && "PTE should still be in dcache");
+
                 // request cleanup
 	        r_dcache_cleanup_req  = true;
@@ -4007,5 +4022,5 @@
                     r_dcache_in_tlb[way*m_dcache_sets+set] = false;
                 }  
-                if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 	// contains PTD
+                else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) // contains PTD
                 {
                     r_itlb.reset();
@@ -4014,11 +4029,8 @@
                     r_dcache_fsm = DCACHE_IDLE;
                 }
-#if DEBUG_DCACHE
-if ( m_debug_dcache_fsm )
-{
-    std::cout << "  <PROC.DCACHE_DIRTY_SC_WAIT> PTE modified : Inval cache line & TLBs"
-              << std::endl;
-}
-#endif
+                else
+                {
+                    r_dcache_fsm = DCACHE_IDLE;
+                }
             }
         }
@@ -4261,9 +4273,10 @@
 
         // 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_tlb_inval_count.read() == ((m_dtlb_sets*m_dtlb_ways)-1) )
         {
             r_dcache_fsm = r_dcache_fsm_scan_save.read();
         }
         r_dcache_tlb_inval_count = r_dcache_tlb_inval_count.read() + 1;
+        break;
     }   
     } // end switch r_dcache_fsm
@@ -4638,21 +4651,20 @@
     } // end switch r_vci_rsp_fsm
 
-    ////////////////////////////////////////////////////////////////////////////////
-    // The CLEANUP FSM send the cleanup commands on the coherence network,
-    // and supports simultaneous cleanup transactions, but two simultaneous
-    // transactions mut address different cache lines.
-    // Therefore, the line number is registered in an associative
-    // registration buffer (Content Adressable Memory) by the CLEANUP FSM,
-    // and the corresponding slot (identified by the VCI TRDID field) is cleared 
-    // when the cleanup transaction response is received.
-    // It handles cleanup requests from both the DCACHE FSM & ICACHE FSM
-    // with a round robin priority, and can support up to 4 simultaneous 
-    // cleanup transactions (4 slots in the registration buffer).
-    // The r_dcache_cleanup_req (or r_icache_cleanup_req) flip-flops are reset
-    // when the command has been sent.
+    /////////////////////////////////////////////////////////////////////////////////////
+    // The CLEANUP FSM is in charge to send the cleanup commands on the coherence 
+    // network. It has two clients (DCACHE FSM and ICACHE FSM) that are served
+    // with a round-robin priority. All cleanup commands are registered in the 
+    // r_cleanup_buffer, because we must avoid to send a Read Miss command 
+    // for line (X) if there is a pending cleanup for line (X): the r_cleanup_buffer 
+    // is tested by the ICACHE FSM and DCACHE FSM before posting a miss request.
+    // The CLEANUP FSM resets the r_*cache_cleanup request flip-flops as soon as 
+    // the request has been sent and registered in the buffer.
+    // The buffer itself is cleared when the cleanup response is received.
+    // We use an assocative registration buffer (CAM) in order to support several
+    // simultaneous cleanup transactions (up to 4 simultaneous clenups).
     // The VCI TRDID field is used to distinguish data/instruction cleanups:
     // - if data cleanup        : TRDID = 2*index + 0
     // - if instruction cleanup : TRDID = 2*index + 1
-    ////////////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////////////////////
 
     switch ( r_cleanup_fsm.read() ) 
@@ -4665,8 +4677,9 @@
             if ( r_dcache_cleanup_req.read() )      // dcache request
             {
-                ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(), 
-                                                      &index );   
+                ok = r_cleanup_buffer.write( r_dcache_cleanup_line.read(), 
+                                             &index );   
                 if ( ok )   // successful registration
                 {
+                    r_dcache_cleanup_req = false;
                     r_cleanup_fsm   = CLEANUP_DATA_GO; 
                     r_cleanup_trdid = index<<1;
@@ -4675,8 +4688,9 @@
             else if ( r_icache_cleanup_req.read() ) // icache request
             {
-                ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(), 
-                                                      &index );   
+                ok = r_cleanup_buffer.write( r_icache_cleanup_line.read(), 
+                                             &index );   
                 if ( ok )   // successful registration
                 {
+                    r_icache_cleanup_req = false;
                     r_cleanup_fsm   = CLEANUP_INS_GO; 
                     r_cleanup_trdid = (index<<1) + 1;
@@ -4692,8 +4706,9 @@
             if ( r_icache_cleanup_req.read() )      // icache request
             {
-                ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(),
-                                                      &index );   
+                ok = r_cleanup_buffer.write( r_icache_cleanup_line.read(),
+                                             &index );   
                 if ( ok )   // successful registration
                 {
+                    r_icache_cleanup_req = false;
                     r_cleanup_fsm   = CLEANUP_INS_GO;
                     r_cleanup_trdid = (index<<1) + 1;
@@ -4702,8 +4717,9 @@
             else if ( r_dcache_cleanup_req.read() ) // dcache request
             {
-                ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(),
-                                                      &index );   
+                ok = r_cleanup_buffer.write( r_dcache_cleanup_line.read(),
+                                             &index );   
                 if ( ok )   // successful registration
                 {
+                    r_dcache_cleanup_req = false;
                     r_cleanup_fsm   = CLEANUP_DATA_GO;
                     r_cleanup_trdid = index<<1;
@@ -4717,5 +4733,4 @@
             if ( p_vci_ini_c.cmdack.read() )
             {
-                r_dcache_cleanup_req = false;
                 r_cleanup_fsm        = CLEANUP_INS_IDLE;
 
@@ -4731,10 +4746,9 @@
             break;
         }
-        ////////////////////////
+        ////////////////////
         case CLEANUP_INS_GO:
         {
             if ( p_vci_ini_c.cmdack.read() )
             {
-                r_icache_cleanup_req = false;
                 r_cleanup_fsm        = CLEANUP_DATA_IDLE;
 
@@ -4753,7 +4767,7 @@
 
     //////////////// Handling  cleanup responses //////////////////
-    if ( p_vci_ini_c.rspval.read() )    // valid response
-    {
-        r_cleanup_buffer.cancel_index( p_vci_ini_c.rtrdid.read() >> 1);
+    if ( p_vci_ini_c.rspval.read() )   
+    {
+        r_cleanup_buffer.inval( p_vci_ini_c.rtrdid.read() >> 1);
     }
 
