Index: trunk/modules/vci_cc_xcache_wrapper_v4/caba/metadata/vci_cc_xcache_wrapper_v4.sd
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v4/caba/metadata/vci_cc_xcache_wrapper_v4.sd	(revision 132)
+++ trunk/modules/vci_cc_xcache_wrapper_v4/caba/metadata/vci_cc_xcache_wrapper_v4.sd	(revision 134)
@@ -21,10 +21,10 @@
 		Uses('common:mapping_table'),
 		Uses('common:iss2'),
-		Uses('caba:write_buffer'),
+		Uses('caba:multi_write_buffer'),
 		Uses('caba:generic_cache', addr_t = 'uint32_t'),
 		],
 	ports = [
 		Port('caba:vci_initiator', 'p_vci_ini_rw'),
-        Port('caba:vci_initiator', 'p_vci_ini_c'),
+		Port('caba:vci_initiator', 'p_vci_ini_c'),
 		Port('caba:vci_target', 'p_vci_tgt'),
 		Port('caba:bit_in', 'p_irq', parameter.Constant('n_irq')),
@@ -45,16 +45,18 @@
 		parameter.Int('dcache_sets'),
 		parameter.Int('dcache_words'),
+		parameter.Int('ram_width_access'),
+		parameter.Int('wbuf_nwords'),
+		parameter.Int('wbuf_nlines'),
+		parameter.Int('wbuf_timeout'),
 		],
-	   extensions = [
-	'dsx:get_ident='
-        'initiator_rw_index:p_vci_ini_rw:mt,'
-        'initiator_c_index:p_vci_ini_c:mc,'
-        'target_index:p_vci_tgt:mc',
-	'dsx:cpu=wrapper:iss_t',
-	'dsx:addressable=target_index',
-    'dsx:on_segment=mc:add_index:initiator_rw_index',
-	'dsx:mapping_type=processor:proc_id',
-   ],
+	extensions = [
+		'dsx:get_ident='
+		'initiator_rw_index:p_vci_ini_rw:mt,'
+		'initiator_c_index:p_vci_ini_c:mc,'
+		'target_index:p_vci_tgt:mc',
+		'dsx:cpu=wrapper:iss_t',
+		'dsx:addressable=target_index',
+		'dsx:on_segment=mc:add_index:initiator_rw_index',
+		'dsx:mapping_type=processor:proc_id',
+		],
 )
-
-
Index: trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h	(revision 132)
+++ trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h	(revision 134)
@@ -32,6 +32,7 @@
 #include <inttypes.h>
 #include <systemc>
+#include <queue>
 #include "caba_base_module.h"
-#include "write_buffer.h"
+#include "multi_write_buffer.h"
 #include "generic_cache.h"
 #include "vci_initiator.h"
@@ -40,4 +41,80 @@
 #include "static_assert.h"
 
+/*
+ * CC_XCACHE_WRAPPER_SELECT_VICTIM :
+ *   The selection and the update of cache (after a read miss)
+ *   are separated in two step
+ *   Also, the cleanup can be send in parallel at the read miss.
+ *
+ * CC_XCACHE_WRAPPER_FIFO_RSP
+ *   Two simple fifo (each 2x32 depth) receive the cache line from
+ *   RAM. Instead of two buffers (m_icache_words and m_dcache_words)
+ *   
+ * CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+ *   Update cache in "2*cache_words" cycles (read+mask, write)
+ *   
+ * CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+ *   Update cache with only modified data (be != 0)
+ *   
+ * CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME
+ *   Write buffer scheme for update step :
+ *     1    - multi_scan
+ *     2    - round_robin_scan
+ *     3    - one_scan
+ *     else - default scheme
+ *
+ * CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY
+ *   Write buffer access is conditionnal with dcache_miss_req and icache_miss_req
+ *     1    - two access authorized
+ *     2    - one access with static priority (dcache prior)
+ *     3    - one access with static priority (icache prior)
+ *     4    - one access with round robin priority
+ * 
+ * CC_XCACHE_WRAPPER_STOP_SIMULATION :
+ *   stop simulation if processor is stall after a long time
+ *   (configurable with "stop_simulation" function)
+ *
+ * CC_XCACHE_WRAPPER_DEBUG :
+ *   Add log to help the debugging
+ *
+ * CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN :
+ *   Number of cycle before to prinf debug message
+ *
+ * CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
+ *   Print transaction between the cpu and the cache
+ */
+
+// implementation
+#ifndef CC_XCACHE_WRAPPER_SELECT_VICTIM
+#define CC_XCACHE_WRAPPER_SELECT_VICTIM             0
+#endif
+#ifndef CC_XCACHE_WRAPPER_FIFO_RSP
+#define CC_XCACHE_WRAPPER_FIFO_RSP                  0
+#endif
+#ifndef CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+#define CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE     1
+#endif
+#ifndef CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+#define CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT 1
+#endif
+#ifndef CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME
+#define CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME        0
+#endif
+#ifndef CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY
+#define CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY          2
+#endif  
+// debugging
+#ifndef CC_XCACHE_WRAPPER_STOP_SIMULATION
+#define CC_XCACHE_WRAPPER_STOP_SIMULATION           1
+#endif
+#ifndef CC_XCACHE_WRAPPER_DEBUG
+#define CC_XCACHE_WRAPPER_DEBUG                     0
+#endif
+#ifndef CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN
+#define CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN           200000
+#endif
+#ifndef CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
+#define CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION  0
+#endif
 
 namespace soclib {
@@ -58,8 +135,11 @@
     typedef uint32_t    	be_t;
     typedef typename vci_param::fast_addr_t vci_addr_t;
+
     enum dcache_fsm_state_e {
         DCACHE_IDLE,
         DCACHE_WRITE_UPDT,
-        DCACHE_WRITE_REQ,
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+        DCACHE_MISS_VICTIM,
+#endif
         DCACHE_MISS_WAIT,
         DCACHE_MISS_UPDT,
@@ -67,4 +147,5 @@
         DCACHE_SC_WAIT,
         DCACHE_INVAL,
+        DCACHE_SYNC,
         DCACHE_ERROR,
         DCACHE_CC_CHECK,
@@ -76,4 +157,7 @@
     enum icache_fsm_state_e {
         ICACHE_IDLE,
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+        ICACHE_MISS_VICTIM,
+#endif
         ICACHE_MISS_WAIT,
         ICACHE_MISS_UPDT,
@@ -94,6 +178,4 @@
         CMD_DATA_WRITE,
         CMD_DATA_SC,
-        CMD_INS_CLEANUP,
-        CMD_DATA_CLEANUP,
     };
 
@@ -106,6 +188,4 @@
         RSP_DATA_WRITE,
         RSP_DATA_SC,
-        RSP_INS_CLEANUP,
-        RSP_DATA_CLEANUP,
     };
 
@@ -122,4 +202,28 @@
     };
 
+    enum cleanup_fsm_state_e {
+        CLEANUP_IDLE,
+        CLEANUP_DCACHE,
+        CLEANUP_ICACHE,
+    };
+
+    enum transaction_type_c_e {
+        // convention with memcache
+        TYPE_DATA_CLEANUP = 0x0,
+        TYPE_INS_CLEANUP  = 0x1
+    };
+
+    enum transaction_type_rw_e {
+        // convention with memcache
+        // b0 : 1 if cached
+        // b1 : 1 if instruction
+        // b2 : 1 if sc
+        TYPE_DATA_UNC     = 0x0,
+        TYPE_DATA_MISS    = 0x1,
+        TYPE_INS_UNC      = 0x2,
+        TYPE_INS_MISS     = 0x3,
+        TYPE_DATA_SC      = 0x4, // sc is data and no cached
+    };
+
 public:
 
@@ -143,8 +247,17 @@
     const size_t        m_dcache_ways;
     const size_t        m_dcache_words;
+    const uint32_t      m_dcache_words_shift;
     const size_t        m_dcache_yzmask;
     const size_t        m_icache_ways;
     const size_t        m_icache_words;
+    const uint32_t      m_icache_words_shift;
     const size_t        m_icache_yzmask;
+    const size_t        m_cache_words; // max between m_dcache_words and m_icache_words
+
+#if CC_XCACHE_WRAPPER_STOP_SIMULATION
+    bool                m_stop_simulation;
+    uint32_t            m_stop_simulation_nb_frz_cycles_max;
+    uint32_t            m_stop_simulation_nb_frz_cycles;
+#endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
 
     // REGISTERS
@@ -154,7 +267,4 @@
     sc_signal<data_t>       r_dcache_wdata_save;
     sc_signal<data_t>       r_dcache_rdata_save;
-    sc_signal<data_64>      r_dcache_ll_data;
-    sc_signal<addr_40>      r_dcache_ll_addr;
-    sc_signal<bool>         r_dcache_ll_valid;
     sc_signal<int>          r_dcache_type_save;
     sc_signal<be_t>         r_dcache_be_save;
@@ -163,8 +273,14 @@
     sc_signal<addr_40>      r_dcache_cleanup_line;
     sc_signal<bool>         r_dcache_miss_req;
+    sc_signal<size_t>       r_dcache_miss_way;
+    sc_signal<size_t>       r_dcache_miss_set;
     sc_signal<bool>         r_dcache_unc_req;
     sc_signal<bool>         r_dcache_sc_req;
-    sc_signal<bool>         r_dcache_write_req;
     sc_signal<bool>         r_dcache_inval_rsp;
+    sc_signal<size_t>       r_dcache_update_addr;
+    sc_signal<data_64>      r_dcache_ll_data;
+    sc_signal<addr_40>      r_dcache_ll_addr;
+    sc_signal<bool>         r_dcache_ll_valid;
+    sc_signal<bool>         r_dcache_previous_unc;
 
     sc_signal<int>          r_icache_fsm;
@@ -172,8 +288,11 @@
     sc_signal<addr_40>      r_icache_addr_save;
     sc_signal<bool>         r_icache_miss_req;
+    sc_signal<size_t>       r_icache_miss_way;
+    sc_signal<size_t>       r_icache_miss_set;
     sc_signal<bool>         r_icache_unc_req;
     sc_signal<bool>         r_icache_cleanup_req;
     sc_signal<addr_40>      r_icache_cleanup_line;
     sc_signal<bool>         r_icache_inval_rsp;
+    sc_signal<size_t>       r_icache_update_addr;
 
     sc_signal<int>          r_vci_cmd_fsm;
@@ -181,4 +300,5 @@
     sc_signal<size_t>       r_vci_cmd_max;       
     sc_signal<size_t>       r_vci_cmd_cpt;       
+    sc_signal<bool>         r_vci_cmd_dcache_prior;
       
     sc_signal<int>          r_vci_rsp_fsm;
@@ -186,11 +306,22 @@
     sc_signal<bool>         r_vci_rsp_data_error;    
     sc_signal<size_t>       r_vci_rsp_cpt;  
-
-    data_t                  *r_icache_miss_buf;    
-    data_t                  *r_dcache_miss_buf;    
+    sc_signal<bool>         r_vci_rsp_ack;
+
+#if CC_XCACHE_WRAPPER_FIFO_RSP
+    std::queue<data_t>      r_icache_miss_buf;
+    std::queue<data_t>      r_dcache_miss_buf;
+#else
+    bool                   *r_icache_miss_val;    //[m_icache_words]
+    data_t                 *r_icache_miss_buf;    //[m_icache_words]
+    bool                   *r_dcache_miss_val;    //[m_dcache_words]
+    data_t                 *r_dcache_miss_buf;    //[m_dcache_words]
+#endif
     sc_signal<bool>         r_icache_buf_unc_valid;
 
-    data_t                  *r_tgt_buf;
-    be_t                    *r_tgt_be;
+    data_t                 *r_tgt_buf;            //[m_cache_words]
+    be_t                   *r_tgt_be;             //[m_cache_words]
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+    sc_signal<uint32_t>     r_cache_word;
+#endif
 
     sc_signal<int>          r_vci_tgt_fsm;
@@ -199,9 +330,9 @@
     sc_signal<bool>         r_tgt_update;
     sc_signal<bool>         r_tgt_update_data;
-    sc_signal<bool>         r_tgt_brdcast;
+  //sc_signal<bool>         r_tgt_brdcast;
     sc_signal<size_t>       r_tgt_srcid;
     sc_signal<size_t>       r_tgt_pktid;
     sc_signal<size_t>       r_tgt_trdid;
-    sc_signal<size_t>       r_tgt_plen;
+  //sc_signal<size_t>       r_tgt_plen;
     sc_signal<bool>         r_tgt_icache_req;
     sc_signal<bool>         r_tgt_dcache_req;
@@ -209,47 +340,59 @@
     sc_signal<bool>         r_tgt_dcache_rsp;
 
-    WriteBuffer<addr_40>        r_wbuf;
+    sc_signal<int>          r_cleanup_fsm;		// controls initiator port of the coherence network
+
+    MultiWriteBuffer<addr_40>   r_wbuf;
     GenericCache<vci_addr_t>    r_icache;
     GenericCache<vci_addr_t>    r_dcache;
 
+#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
+    std::ofstream               log_dcache_transaction_file;
+#endif
+
     // Activity counters
-    uint32_t m_cpt_dcache_data_read;        // DCACHE DATA READ
-    uint32_t m_cpt_dcache_data_write;       // DCACHE DATA WRITE
-    uint32_t m_cpt_dcache_dir_read;         // DCACHE DIR READ
-    uint32_t m_cpt_dcache_dir_write;        // DCACHE DIR WRITE
-
-    uint32_t m_cpt_icache_data_read;        // ICACHE DATA READ
-    uint32_t m_cpt_icache_data_write;       // ICACHE DATA WRITE
-    uint32_t m_cpt_icache_dir_read;         // ICACHE DIR READ
-    uint32_t m_cpt_icache_dir_write;        // ICACHE DIR WRITE
-
-    uint32_t m_cpt_cc_update;               // number of coherence update packets 
-    uint32_t m_cpt_cc_inval;                // number of coherence inval packets
-
-    uint32_t m_cpt_frz_cycles;	            // number of cycles where the cpu is frozen
-    uint32_t m_cpt_total_cycles;	    // total number of cycles 
-
-    uint32_t m_cpt_read;                    // total number of read instructions
-    uint32_t m_cpt_write;                   // total number of write instructions
-    uint32_t m_cpt_data_miss;               // number of read miss
-    uint32_t m_cpt_ins_miss;                // number of instruction miss
-    uint32_t m_cpt_unc_read;                // number of read uncached
-    uint32_t m_cpt_write_cached;            // number of cached write
-
-    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
-    uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
-    uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
-    uint32_t m_cost_ins_miss_frz;           // number of frozen cycles related to ins miss
-
-    uint32_t m_cpt_imiss_transaction;       // number of VCI instruction miss transactions
-    uint32_t m_cpt_dmiss_transaction;       // number of VCI data miss transactions
-    uint32_t m_cpt_unc_transaction;         // number of VCI uncached read transactions
-    uint32_t m_cpt_write_transaction;       // number of VCI write transactions
-
-    uint32_t m_cost_imiss_transaction;      // cumulated duration for VCI IMISS transactions
-    uint32_t m_cost_dmiss_transaction;      // cumulated duration for VCI DMISS transactions
-    uint32_t m_cost_unc_transaction;        // cumulated duration for VCI UNC transactions
-    uint32_t m_cost_write_transaction;      // cumulated duration for VCI WRITE transactions
-    uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions
+    uint32_t m_cpt_dcache_data_read;             // * DCACHE DATA READ
+    uint32_t m_cpt_dcache_data_write;            // * DCACHE DATA WRITE
+    uint32_t m_cpt_dcache_dir_read;              // * DCACHE DIR READ
+    uint32_t m_cpt_dcache_dir_write;             // * DCACHE DIR WRITE
+                                                 
+    uint32_t m_cpt_icache_data_read;             // * ICACHE DATA READ
+    uint32_t m_cpt_icache_data_write;            // * ICACHE DATA WRITE
+    uint32_t m_cpt_icache_dir_read;              // * ICACHE DIR READ
+    uint32_t m_cpt_icache_dir_write;             // * ICACHE DIR WRITE
+
+    uint32_t m_cpt_cc_update_icache;             // number of coherence update packets (for icache)
+    uint32_t m_cpt_cc_update_dcache;             // number of coherence update packets (for dcache)
+    uint32_t m_cpt_cc_inval_broadcast;           // number of coherence inval packets
+    uint32_t m_cpt_cc_inval_icache;              // number of coherence inval packets
+    uint32_t m_cpt_cc_inval_dcache;              // number of coherence inval packets
+    uint32_t m_cpt_cc_update_icache_word_useful; // number of valid word in coherence update packets
+    uint32_t m_cpt_cc_update_dcache_word_useful; // number of valid word in coherence update packets
+
+    uint32_t m_cpt_frz_cycles;	                 // * number of cycles where the cpu is frozen
+    uint32_t m_cpt_total_cycles;	             // total number of cycles 
+
+    uint32_t m_cpt_data_read;                    //   number of data read
+    uint32_t m_cpt_data_read_miss;               //   number of data read miss
+    uint32_t m_cpt_data_read_uncached;           //   number of data read uncached
+    uint32_t m_cpt_data_write;                   //   number of data write
+    uint32_t m_cpt_data_write_miss;              //   number of data write miss
+    uint32_t m_cpt_data_write_uncached;          //   number of data write uncached
+    uint32_t m_cpt_ins_miss;                     // * number of instruction miss
+
+    uint32_t m_cost_write_frz;                   // * number of frozen cycles related to write buffer         
+    uint32_t m_cost_data_miss_frz;               // * number of frozen cycles related to data miss
+    uint32_t m_cost_unc_read_frz;                // * number of frozen cycles related to uncached read
+    uint32_t m_cost_ins_miss_frz;                // * number of frozen cycles related to ins miss
+
+    uint32_t m_cpt_imiss_transaction;            // * number of VCI instruction miss transactions
+    uint32_t m_cpt_dmiss_transaction;            // * number of VCI data miss transactions
+    uint32_t m_cpt_unc_transaction;              // * number of VCI uncached read transactions
+    uint32_t m_cpt_data_write_transaction;       // * number of VCI write transactions
+
+    uint32_t m_cost_imiss_transaction;           // * cumulated duration for VCI IMISS transactions
+    uint32_t m_cost_dmiss_transaction;           // * cumulated duration for VCI DMISS transactions
+    uint32_t m_cost_unc_transaction;             // * cumulated duration for VCI UNC transactions
+    uint32_t m_cost_write_transaction;           // * cumulated duration for VCI WRITE transactions
+    uint32_t m_length_write_transaction;         // * cumulated length for VCI WRITE transactions
 
 protected:
@@ -271,5 +414,9 @@
                        size_t dcache_ways,
                        size_t dcache_sets,
-                       size_t dcache_words );
+                       size_t dcache_words,
+                       size_t wbuf_nwords,
+                       size_t wbuf_nlines,
+                       size_t wbuf_timeout
+                         );
 
     ~VciCcXCacheWrapperV4();
@@ -278,4 +425,8 @@
     void print_cpi();
     void print_stats();
+
+// #if CC_XCACHE_WRAPPER_STOP_SIMULATION
+    void stop_simulation (uint32_t);
+// #endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
 
 private:
@@ -300,5 +451,2 @@
 
 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
-
-
-
Index: trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp	(revision 132)
+++ trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp	(revision 134)
@@ -56,17 +56,60 @@
 
 #include <cassert>
+#include <iomanip>
 #include "arithmetics.h"
 #include "../include/vci_cc_xcache_wrapper_v4.h"
 
-//#define DEBUG_CC_XCACHE_WRAPPER 1
+#if CC_XCACHE_WRAPPER_DEBUG
+# define PRINTF(msg...) do { if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) printf(msg); } while (0); 
+#else
+# define PRINTF(msg...)
+#endif
+
+# define ASSERT(cond,msg) assert ((cond) and msg);
+
+#if CC_XCACHE_WRAPPER_FIFO_RSP
+# define CACHE_MISS_BUF_ALLOC
+# define CACHE_MISS_BUF_DEALLOC
+# define CACHE_MISS_BUF_RESET(c)        while (r_##c##cache_miss_buf.size()>0) {r_##c##cache_miss_buf.pop();}
+# define CACHE_MISS_BUF_REQ_INIT(c)
+# define CACHE_MISS_BUF_RSP_VAL(c,n)    (r_##c##cache_miss_buf.size()>0)
+# define CACHE_MISS_BUF_RSP_ACK(c)      (r_##c##cache_miss_buf.size()<2)
+# define CACHE_MISS_BUF_RSP_DATA(c,n)   r_##c##cache_miss_buf.front()
+# define CACHE_MISS_BUF_RSP_POP(c)      do { r_##c##cache_miss_buf.pop();} while (0)
+# define CACHE_MISS_BUF_RSP_PUSH(c,n,d) do { r_##c##cache_miss_buf.push(d);} while (0)
+# define CACHE_MISS_BUF_RSP_PRINT(c)    do { PRINTF("    * cache_miss_buf - size : %d\n",r_##c##cache_miss_buf.size());} while (0)
+#else
+# define CACHE_MISS_BUF_ALLOC           do { \
+                                        r_icache_miss_val = new bool  [m_icache_words]; \
+                                        r_icache_miss_buf = new data_t[m_icache_words]; \
+                                        r_dcache_miss_val = new bool  [m_dcache_words]; \
+                                        r_dcache_miss_buf = new data_t[m_dcache_words]; \
+                                        } while (0)
+# define CACHE_MISS_BUF_DEALLOC         do { \
+                                        delete [] r_icache_miss_val; \
+                                        delete [] r_icache_miss_buf; \
+                                        delete [] r_dcache_miss_val; \
+                                        delete [] r_dcache_miss_buf; \
+                                        } while (0)
+# define CACHE_MISS_BUF_RESET(c)
+# define CACHE_MISS_BUF_REQ_INIT(c)     do {for (uint32_t i=0; i<m_##c##cache_words;++i) r_##c##cache_miss_val[i] = false;} while (0)
+# define CACHE_MISS_BUF_RSP_VAL(c,n)    r_##c##cache_miss_val[n]
+# define CACHE_MISS_BUF_RSP_ACK(c)      true
+# define CACHE_MISS_BUF_RSP_DATA(c,n)   r_##c##cache_miss_buf[n]
+# define CACHE_MISS_BUF_RSP_POP(c)
+# define CACHE_MISS_BUF_RSP_PUSH(c,n,d) do {r_##c##cache_miss_val[n] = true; r_##c##cache_miss_buf[n] = d;} while (0)
+# define CACHE_MISS_BUF_RSP_PRINT(c)    do {for (uint32_t i=0; i<m_##c##cache_words;++i) PRINTF("%d %x |",r_##c##cache_miss_val[i],r_##c##cache_miss_buf[i]); PRINTF("\n");} while (0)
+#endif
 
 namespace soclib { 
 namespace caba {
-
     namespace {
+
         const char *dcache_fsm_state_str[] = {
             "DCACHE_IDLE",
             "DCACHE_WRITE_UPDT",
-            "DCACHE_WRITE_REQ",
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+            "DCACHE_MISS_VICTIM",
+#endif
             "DCACHE_MISS_WAIT",
             "DCACHE_MISS_UPDT",
@@ -74,4 +117,5 @@
             "DCACHE_SC_WAIT",
             "DCACHE_INVAL",
+            "DCACHE_SYNC",
             "DCACHE_ERROR",
             "DCACHE_CC_CHECK",
@@ -82,4 +126,7 @@
         const char *icache_fsm_state_str[] = {
             "ICACHE_IDLE",
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+            "ICACHE_MISS_VICTIM",
+#endif
             "ICACHE_MISS_WAIT",
             "ICACHE_MISS_UPDT",
@@ -99,6 +146,4 @@
             "CMD_DATA_WRITE",
             "CMD_DATA_SC",
-            "CMD_INS_CLEANUP",
-            "CMD_DATA_CLEANUP",
         };
         const char *rsp_fsm_state_str[] = {
@@ -110,6 +155,4 @@
             "RSP_DATA_WRITE",
             "RSP_DATA_SC",
-            "RSP_INS_CLEANUP",
-            "RSP_DATA_CLEANUP",
         };
         const char *tgt_fsm_state_str[] = {
@@ -123,4 +166,10 @@
             "TGT_RSP_ICACHE",
             "TGT_RSP_DCACHE",
+        };
+
+        const char *cleanup_fsm_state_str[] = {
+            "CLEANUP_IDLE",
+            "CLEANUP_DCACHE",
+            "CLEANUP_ICACHE",
         };
     }
@@ -145,13 +194,17 @@
             size_t dcache_ways,
             size_t dcache_sets,
-            size_t dcache_words )
+            size_t dcache_words,
+            size_t wbuf_nwords,
+            size_t wbuf_nlines,
+            size_t wbuf_timeout
+                                     )
         : 
             soclib::caba::BaseModule(name),
 
-            p_clk("clk"),
-            p_resetn("resetn"),
+            p_clk       ("clk"),
+            p_resetn    ("resetn"),
             p_vci_ini_rw("vci_ini_rw"),
-            p_vci_ini_c("vci_ini_c"),
-            p_vci_tgt("vci_tgt"),
+            p_vci_ini_c ("vci_ini_c"),
+            p_vci_tgt   ("vci_tgt"),
 
             m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()),
@@ -163,8 +216,11 @@
             m_dcache_ways(dcache_ways),
             m_dcache_words(dcache_words),
-            m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
+            m_dcache_words_shift(uint32_log2(dcache_words)+2),
+            m_dcache_yzmask((~0)<<m_dcache_words_shift),
             m_icache_ways(icache_ways),
             m_icache_words(icache_words),
-            m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
+            m_icache_words_shift(uint32_log2(icache_words)+2),
+            m_icache_yzmask((~0)<<m_icache_words_shift),
+            m_cache_words((dcache_words)?dcache_words:icache_words),
 
             r_dcache_fsm("r_dcache_fsm"),
@@ -173,7 +229,4 @@
             r_dcache_wdata_save("r_dcache_wdata_save"),
             r_dcache_rdata_save("r_dcache_rdata_save"),
-            r_dcache_ll_data("r_dcache_ll_data"),
-            r_dcache_ll_addr("r_dcache_ll_addr"),
-            r_dcache_ll_valid("r_dcache_ll_valid"),
             r_dcache_type_save("r_dcache_type_save"),
             r_dcache_be_save("r_dcache_be_save"),
@@ -182,6 +235,14 @@
             r_dcache_cleanup_line("r_dcache_cleanup_line"),
             r_dcache_miss_req("r_dcache_miss_req"),
+            r_dcache_miss_way("r_dcache_miss_way"),
+            r_dcache_miss_set("r_dcache_miss_set"),
             r_dcache_unc_req("r_dcache_unc_req"),
-            r_dcache_write_req("r_dcache_write_req"),
+            r_dcache_sc_req("r_dcache_sc_req"),
+            r_dcache_inval_rsp("r_dcache_inval_rsp"),
+            r_dcache_update_addr("r_dcache_update_addr"),
+            r_dcache_ll_data("r_dcache_ll_data"),
+            r_dcache_ll_addr("r_dcache_ll_addr"),
+            r_dcache_ll_valid("r_dcache_ll_valid"),
+            r_dcache_previous_unc("r_dcache_previous_unc"),
 
             r_icache_fsm("r_icache_fsm"),
@@ -189,6 +250,11 @@
             r_icache_addr_save("r_icache_addr_save"),
             r_icache_miss_req("r_icache_miss_req"),
+            r_icache_miss_way("r_icache_miss_way"),
+            r_icache_miss_set("r_icache_miss_set"),
+            r_icache_unc_req("r_icache_unc_req"),
             r_icache_cleanup_req("r_icache_cleanup_req"),
             r_icache_cleanup_line("r_icache_cleanup_line"),
+            r_icache_inval_rsp("r_icache_inval_rsp"),
+            r_icache_update_addr("r_icache_update_addr"),
 
             r_vci_cmd_fsm("r_vci_cmd_fsm"),
@@ -196,4 +262,5 @@
             r_vci_cmd_max("r_vci_cmd_max"),
             r_vci_cmd_cpt("r_vci_cmd_cpt"),
+            r_vci_cmd_dcache_prior("r_vci_cmd_dcache_prior"),
 
             r_vci_rsp_fsm("r_vci_rsp_fsm"),
@@ -201,6 +268,11 @@
             r_vci_rsp_data_error("r_vci_rsp_data_error"),
             r_vci_rsp_cpt("r_vci_rsp_cpt"),
+            r_vci_rsp_ack("r_vci_rsp_ack"),
 
             r_icache_buf_unc_valid("r_icache_buf_unc_valid"),
+
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+            r_cache_word("r_cache_word"),
+#endif
 
             r_vci_tgt_fsm("r_vci_tgt_fsm"),
@@ -208,19 +280,32 @@
             r_tgt_word("r_tgt_word"),
             r_tgt_update("r_tgt_update"),
+            r_tgt_update_data("r_tgt_update_data"),
+         // r_tgt_brdcast("r_tgt_brdcast"),
             r_tgt_srcid("r_tgt_srcid"),
             r_tgt_pktid("r_tgt_pktid"),
             r_tgt_trdid("r_tgt_trdid"),
+         // r_tgt_plen("r_tgt_plen"),
             r_tgt_icache_req("r_tgt_icache_req"),
             r_tgt_dcache_req("r_tgt_dcache_req"),
-
-            r_wbuf("r_wbuf", dcache_words ),
+            r_tgt_icache_rsp("r_tgt_icache_rsp"),
+            r_tgt_dcache_rsp("r_tgt_dcache_rsp"),
+
+            r_cleanup_fsm("r_cleanup_fsm"),
+
+            r_wbuf("r_wbuf", wbuf_nwords, wbuf_nlines, wbuf_timeout, dcache_words),
             r_icache("icache", icache_ways, icache_sets, icache_words),
             r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
-
             {
-                r_icache_miss_buf = new data_t[icache_words];
-                r_dcache_miss_buf = new data_t[dcache_words];
-                r_tgt_buf         = new data_t[dcache_words];
-                r_tgt_be          = new be_t[dcache_words];
+                // Size of word is 32 bits
+                ASSERT( (icache_words*vci_param::B) < (1<<vci_param::K),
+                        "I need more PLEN bits");
+
+                ASSERT( (vci_param::T > 2) and ((1<<(vci_param::T-1)) >= wbuf_nlines),
+                        "I need more TRDID bits");
+
+                CACHE_MISS_BUF_ALLOC;
+
+                r_tgt_buf = new data_t[m_cache_words];
+                r_tgt_be  = new be_t  [m_cache_words];
 
                 SC_METHOD(transition);
@@ -234,12 +319,24 @@
 
                 typename iss_t::CacheInfo cache_info;
-                cache_info.has_mmu = false;
+                cache_info.has_mmu          = false;
                 cache_info.icache_line_size = icache_words*sizeof(data_t);
-                cache_info.icache_assoc = icache_ways;
-                cache_info.icache_n_lines = icache_sets;
+                cache_info.icache_assoc     = icache_ways;
+                cache_info.icache_n_lines   = icache_sets;
                 cache_info.dcache_line_size = dcache_words*sizeof(data_t);
-                cache_info.dcache_assoc = dcache_ways;
-                cache_info.dcache_n_lines = dcache_sets;
+                cache_info.dcache_assoc     = dcache_ways;
+                cache_info.dcache_n_lines   = dcache_sets;
                 m_iss.setCacheInfo(cache_info);
+
+#if CC_XCACHE_WRAPPER_STOP_SIMULATION
+                m_stop_simulation               = false;
+                m_stop_simulation_nb_frz_cycles = 0;
+#endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
+
+#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
+                std::ostringstream filename("");
+                filename << "Instruction_flow_" << proc_id << ".log";
+                
+                log_dcache_transaction_file.open(filename.str().c_str() ,std::ios::out | std::ios::trunc);
+#endif
             } // end constructor
 
@@ -248,8 +345,12 @@
     ///////////////////////////////////
     {
-        delete [] r_icache_miss_buf;
-        delete [] r_dcache_miss_buf;
-        delete [] r_tgt_be;
+#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
+        log_dcache_transaction_file.close();
+#endif
+
         delete [] r_tgt_buf;
+        delete [] r_tgt_be ;
+
+        CACHE_MISS_BUF_DEALLOC;
     }
 
@@ -266,62 +367,111 @@
     {
         float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
+
+        uint32_t m_cpt_data_read_cached  = m_cpt_data_read-m_cpt_data_read_uncached;
+        uint32_t m_cpt_data_write_cached = m_cpt_data_write-m_cpt_data_write_uncached;
         std::cout << "------------------------------------" << std:: dec << std::endl;
         std::cout << "CPU " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
-        std::cout << "- CPI                = " << (float)m_cpt_total_cycles/run_cycles << std::endl ;
-        std::cout << "- READ RATE          = " << (float)m_cpt_read/run_cycles << std::endl ;
-        std::cout << "- WRITE RATE         = " << (float)m_cpt_write/run_cycles << std::endl;
-        std::cout << "- UNCACHED READ RATE = " << (float)m_cpt_unc_read/m_cpt_read << std::endl ;
-        std::cout << "- CACHED WRITE RATE  = " << (float)m_cpt_write_cached/m_cpt_write << std::endl ;
-        std::cout << "- IMISS_RATE         = " << (float)m_cpt_ins_miss/run_cycles << std::endl;
-        std::cout << "- DMISS RATE         = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl ;
-        std::cout << "- INS MISS COST      = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl;
-        std::cout << "- IMISS TRANSACTION  = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl;
-        std::cout << "- DMISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl;
-        std::cout << "- DMISS TRANSACTION  = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl;
-        std::cout << "- UNC COST           = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl;
-        std::cout << "- UNC TRANSACTION    = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl;
-        std::cout << "- WRITE COST         = " << (float)m_cost_write_frz/m_cpt_write << std::endl;
-        std::cout << "- WRITE TRANSACTION  = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl;
-        std::cout << "- WRITE LENGTH       = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl;
+        std::cout << "- CPI                            : " << (float)m_cpt_total_cycles/run_cycles << std::endl ;
+        std::cout << "- IPC                            : " << (float)run_cycles/m_cpt_total_cycles << std::endl ;
+        std::cout << "- DATA READ *                    : " << m_cpt_data_read << std::endl ;
+        std::cout << "  + Uncached                     : " << m_cpt_data_read_uncached << " (" << (float)m_cpt_data_read_uncached*100.0/(float)m_cpt_data_read << "%)" << std::endl ;
+        std::cout << "  + Cached and miss              : " << m_cpt_data_read_miss << " (" << (float)m_cpt_data_read_miss*100.0/(float)m_cpt_data_read_cached << "%)" << std::endl;
+        std::cout << "- DATA WRITE *                   : " << m_cpt_data_write << std::endl ;
+        std::cout << "  + Uncached                     : " << m_cpt_data_write_uncached << " (" << (float)m_cpt_data_write_uncached*100.0/(float)m_cpt_data_write << "%)" << std::endl ;
+        std::cout << "  + Cached and miss              : " << m_cpt_data_write_miss << " (" << (float)m_cpt_data_write_miss*100.0/(float)m_cpt_data_write_cached << "%)" << std::endl;
+        // std::cout << "- WRITE RATE                     : " << (float)m_cpt_data_write/run_cycles << std::endl;
+        // std::cout << "- UNCACHED READ RATE             : " << (float)m_cpt_data_read_uncached/m_cpt_data_read << std::endl ;
+        // std::cout << "- CACHED WRITE RATE              : " << (float)m_cpt_data_write_cached/m_cpt_data_write << std::endl ;
+        // std::cout << "- IMISS_RATE                     : " << (float)m_cpt_ins_miss/run_cycles << std::endl;
+        // std::cout << "- DMISS RATE                     : " << (float)m_cpt_data_miss/(m_cpt_data_read-m_cpt_data_read_uncached) << std::endl ;
+        // std::cout << "- INS MISS COST                  : " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl;
+        // std::cout << "- IMISS TRANSACTION              : " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl;
+        // std::cout << "- DMISS COST                     : " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl;
+        // std::cout << "- DMISS TRANSACTION              : " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl;
+        // std::cout << "- UNC COST                       : " << (float)m_cost_unc_read_frz/m_cpt_data_read_uncached << std::endl;
+        // std::cout << "- UNC TRANSACTION                : " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl;
+        // std::cout << "- WRITE COST                     : " << (float)m_cost_write_frz/m_cpt_data_write << std::endl;
+        // std::cout << "- WRITE TRANSACTION              : " << (float)m_cost_write_transaction/m_cpt_data_write_transaction << std::endl;
+        // std::cout << "- WRITE LENGTH                   : " << (float)m_length_write_transaction/m_cpt_data_write_transaction << std::endl;
+
+        std::cout << "- CC_UPDATE_ICACHE               : " << m_cpt_cc_update_icache  << std::endl;
+        std::cout << "  + AVERAGE WORD USEFUL          : " << (float)m_cpt_cc_update_icache_word_useful/(float)m_cpt_cc_update_icache << " on " << m_icache_words << " words" << std::endl; 
+        std::cout << "- CC_UPDATE_DCACHE               : " << m_cpt_cc_update_dcache  << std::endl;
+        std::cout << "  + AVERAGE WORD USEFUL          : " << (float)m_cpt_cc_update_dcache_word_useful/(float)m_cpt_cc_update_dcache << " on " << m_dcache_words << " words" << std::endl; 
+        uint32_t m_cpt_cc_inval = m_cpt_cc_inval_broadcast+m_cpt_cc_inval_icache+m_cpt_cc_inval_dcache;
+        std::cout << "- CC_INVALID                     : " << m_cpt_cc_inval << std::endl;
+        std::cout << "  + ICACHE Only                  : " << (float)m_cpt_cc_inval_icache   *100.0/(float)m_cpt_cc_inval << "%" << std::endl;
+        std::cout << "  + DCACHE Only                  : " << (float)m_cpt_cc_inval_dcache   *100.0/(float)m_cpt_cc_inval << "%" << std::endl;
+        std::cout << "  + BROADCAST                    : " << (float)m_cpt_cc_inval_broadcast*100.0/(float)m_cpt_cc_inval << "%" << std::endl;
+        std::cout << "* : accepted or not by the cache" << std::endl ;
+
+        r_wbuf.printStatistics();
     }
+
     ////////////////////////////////////
     tmpl(void)::print_trace(size_t mode)
     ////////////////////////////////////
     {
+        // b0 : write buffer print trace
+        // b1 : write buffer verbose
+        // b2 : dcache print trace
+        // b3 : icache print trace
+
         typename iss_t::InstructionRequest  ireq;
         typename iss_t::DataRequest         dreq;
+
         m_iss.getRequests( ireq, dreq );
-
-        std::cout << std::dec << "CC_XCACHE_WRAPPER " << name() << std::endl;
-        std::cout << " proc state  : PC = " << std::hex << ireq.addr << " / AD = " << dreq.addr 
-                  << std::dec << " / V = " << dreq.valid << " / TYPE = " << dreq.type << std::endl;
-        std::cout << " cache state : " << icache_fsm_state_str[r_icache_fsm] << " / "
-                                       << dcache_fsm_state_str[r_dcache_fsm] << " / "
-                                       << cmd_fsm_state_str[r_vci_cmd_fsm] << " / "
-                                       << rsp_fsm_state_str[r_vci_rsp_fsm] << " / "
-                                       << tgt_fsm_state_str[r_vci_tgt_fsm] << std::endl;
-        if( r_vci_tgt_fsm != TGT_IDLE ) 
-        {
-            std::cout << "    ... coherence request address = " << std::hex << r_tgt_addr.read() << std::endl;
-        }
+        std::cout << std::dec << "Proc \"" << name() << "\"" << std::endl;
+        std::cout << ireq << std::endl;
+        std::cout << dreq << std::endl;
+        std::cout << "  " << dcache_fsm_state_str[r_dcache_fsm]
+                  << "  " << icache_fsm_state_str[r_icache_fsm]
+                  << "  " << cmd_fsm_state_str[r_vci_cmd_fsm]
+                  << "  " << rsp_fsm_state_str[r_vci_rsp_fsm]
+                  << "  " << tgt_fsm_state_str[r_vci_tgt_fsm]
+                  << "  " << cleanup_fsm_state_str[r_cleanup_fsm] << std::endl;
+
         if(mode & 0x1)
         {
-            r_wbuf.printTrace();
+            r_wbuf.printTrace((mode>>1)&1);
         }
+        if(mode & 0x4)
+        {
+            std::cout << "  Data cache" << std::endl;
+            r_dcache.printTrace();
+        }
+        if(mode & 0x8)
+        {
+            std::cout << "  Instruction cache" << std::endl;
+            r_icache.printTrace();
+        }
+
+        // if(mode & 0x10)
+        // {
+        //     std::cout << "  Icache miss buffer : ";
+        //     CACHE_MISS_BUF_RSP_PRINT(i);
+        //     std::cout << std::endl;
+
+        //     std::cout << "  Dcache miss buffer : ";
+        //     CACHE_MISS_BUF_RSP_PRINT(d);
+        //     std::cout << std::endl;
+        // }
     }
+
     //////////////////////////
     tmpl(void)::transition()
     //////////////////////////
     {
-        if ( ! p_resetn.read() ) {
+        if ( not p_resetn.read() ) {
 
             m_iss.reset();
 
             // FSM states
-            r_dcache_fsm = DCACHE_IDLE;
-            r_icache_fsm = ICACHE_IDLE;
+            r_dcache_fsm  = DCACHE_IDLE;
+            r_icache_fsm  = ICACHE_IDLE;
             r_vci_cmd_fsm = CMD_IDLE;
             r_vci_rsp_fsm = RSP_IDLE;
             r_vci_tgt_fsm = TGT_IDLE;
+            r_cleanup_fsm = CLEANUP_IDLE;
 
             // write buffer & caches
@@ -337,10 +487,17 @@
             r_dcache_unc_req     = false;
             r_dcache_sc_req      = false;
-            r_dcache_write_req   = false;
             r_dcache_cleanup_req = false;
+            r_dcache_previous_unc= false;
 
             // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
             r_tgt_icache_req     = false;
             r_tgt_dcache_req     = false;
+            r_tgt_icache_rsp     = false;
+            r_tgt_dcache_rsp     = false;
+
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+            r_cache_word         = 0;
+#endif
+
 
             // internal messages in DCACHE et ICACHE FSMs
@@ -351,29 +508,42 @@
             r_dcache_ll_valid      = false;
             r_icache_buf_unc_valid = false;
+
+            r_vci_cmd_dcache_prior = false;
+
             r_vci_rsp_data_error   = false;
             r_vci_rsp_ins_error    = false;
+
+            CACHE_MISS_BUF_RESET(i);
+            CACHE_MISS_BUF_RESET(d);
 
             // activity counters
             m_cpt_dcache_data_read  = 0;
             m_cpt_dcache_data_write = 0;
-            m_cpt_dcache_dir_read  = 0;
-            m_cpt_dcache_dir_write = 0;
+            m_cpt_dcache_dir_read   = 0;
+            m_cpt_dcache_dir_write  = 0;
             m_cpt_icache_data_read  = 0;
             m_cpt_icache_data_write = 0;
-            m_cpt_icache_dir_read  = 0;
-            m_cpt_icache_dir_write = 0;
-
-            m_cpt_cc_update = 0;
-            m_cpt_cc_inval = 0;
-
-            m_cpt_frz_cycles = 0;
+            m_cpt_icache_dir_read   = 0;
+            m_cpt_icache_dir_write  = 0;
+
+            m_cpt_cc_update_icache             = 0;
+            m_cpt_cc_update_dcache             = 0;
+            m_cpt_cc_inval_broadcast           = 0;
+            m_cpt_cc_inval_icache              = 0;
+            m_cpt_cc_inval_dcache              = 0;
+            m_cpt_cc_update_icache_word_useful = 0;
+            m_cpt_cc_update_dcache_word_useful = 0;
+
+            m_cpt_frz_cycles   = 0;
             m_cpt_total_cycles = 0;
 
-            m_cpt_read = 0;
-            m_cpt_write = 0;
-            m_cpt_data_miss = 0;
-            m_cpt_ins_miss = 0;
-            m_cpt_unc_read = 0;
-            m_cpt_write_cached = 0;
+            m_cpt_data_read            = 0;
+            m_cpt_data_read_miss       = 0;
+            m_cpt_data_read_uncached   = 0;
+            m_cpt_data_write           = 0;
+            m_cpt_data_write_miss      = 0;
+            m_cpt_data_write_uncached  = 0;
+
+            m_cpt_ins_miss     = 0;
 
             m_cost_write_frz = 0;
@@ -385,5 +555,5 @@
             m_cpt_dmiss_transaction = 0;
             m_cpt_unc_transaction = 0;
-            m_cpt_write_transaction = 0;
+            m_cpt_data_write_transaction = 0;
 
             m_cost_imiss_transaction = 0;
@@ -396,12 +566,24 @@
         }
 
-#if DEBUG_CC_XCACHE_WRAPPER
-        std::cout << "--------------------------------------------" << std::endl;
-        std::cout << std::dec << "CC_XCACHE_WRAPPER " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
-        std::cout             << " tgt fsm    = " << tgt_fsm_state_str[r_vci_tgt_fsm] << std::endl
-            << " dcache fsm = " << dcache_fsm_state_str[r_dcache_fsm] << std::endl
-            << " icache fsm = " << icache_fsm_state_str[r_icache_fsm] << std::endl
-            << " cmd fsm    = " << cmd_fsm_state_str[r_vci_cmd_fsm] << std::endl
-            << " rsp fsm    = " << rsp_fsm_state_str[r_vci_rsp_fsm] << std::endl;
+        // printf("%d\n",(uint32_t)m_cpt_total_cycles);
+
+        PRINTF("--------------------------------------------\n");
+        PRINTF("  * CC_XCACHE_WRAPPER \"%s\" - Time = %d\n",name().c_str(),(uint32_t)m_cpt_total_cycles);
+        PRINTF("    * fsm dcache          = %s\n",dcache_fsm_state_str[r_dcache_fsm]);
+        PRINTF("    * fsm icache          = %s\n",icache_fsm_state_str[r_icache_fsm]);
+        PRINTF("    * fsm cmd             = %s\n",cmd_fsm_state_str[r_vci_cmd_fsm]);
+        PRINTF("    * fsm rsp             = %s\n",rsp_fsm_state_str[r_vci_rsp_fsm]);
+        PRINTF("    * fsm tgt             = %s\n",tgt_fsm_state_str[r_vci_tgt_fsm]);
+        PRINTF("    * fsm cleanup         = %s\n",cleanup_fsm_state_str[r_cleanup_fsm]);
+        PRINTF("    * ll info             : %d %llx %llx\n",r_dcache_ll_valid.read(), (uint64_t)r_dcache_ll_addr.read(), (uint64_t)r_dcache_ll_data.read());
+        PRINTF("    * dcache_previous_unc : %d\n",r_dcache_previous_unc.read());
+        // CACHE_MISS_BUF_RSP_PRINT(i);
+        // CACHE_MISS_BUF_RSP_PRINT(d);
+
+#if CC_XCACHE_WRAPPER_DEBUG
+        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
+            {
+                r_wbuf.printTrace(1);
+            }
 #endif
 
@@ -444,4 +626,6 @@
                 if ( p_vci_tgt.cmdval.read() ) 
                 {
+                    PRINTF("    * <TGT> request\n");
+
                     addr_40 address = p_vci_tgt.address.read();
 
@@ -450,16 +634,16 @@
                         std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
                         std::cout << "coherence request is not a write" << std::endl;
-                        std::cout << "oddress = " << std::hex << address << std::endl;
-                        std::cout << "srcid   = " << std::hex << p_vci_tgt.srcid.read() << std::endl;
+                        std::cout << "oddress = " << std::hex << address << std::dec << std::endl;
+                        std::cout << "srcid   = " << p_vci_tgt.srcid.read() << std::endl;
                         exit(0);
                     }
 
                     // multi-update or multi-invalidate for data type
-                    if ( ((address&0x3) != 0x3) && (! m_segment.contains(address)) ) 
+                    if ( ((address&0x3) != 0x3) and (not m_segment.contains(address)) ) 
                     {
                         std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
                         std::cout << "out of segment coherence request" << std::endl;
-                        std::cout << "oddress = " << std::hex << address << std::endl;
-                        std::cout << "srcid   = " << std::hex << p_vci_tgt.srcid.read() << std::endl;
+                        std::cout << "oddress = " << std::hex << address << std::dec << std::endl;
+                        std::cout << "srcid   = " << p_vci_tgt.srcid.read() << std::endl;
                         exit(0);
                     }
@@ -470,9 +654,13 @@
                     r_tgt_trdid = p_vci_tgt.trdid.read();
                     r_tgt_pktid = p_vci_tgt.pktid.read();
-                    r_tgt_plen  = p_vci_tgt.plen.read();
+                 // r_tgt_plen  = p_vci_tgt.plen.read();
                     
+                    PRINTF("    * <TGT> address : %llx\n",(uint64_t)address);
+                    PRINTF("    * <TGT> address : %llx\n",(uint64_t)((((addr_40) ((p_vci_tgt.be.read() & 0x3) << 32)) | 
+                                                                      ((addr_40) (p_vci_tgt.wdata.read()))) * m_dcache_words * 4));
+
                     if ( (address&0x3) == 0x3 )   // broadcast invalidate for data or instruction type
                     {
-                        if ( ! p_vci_tgt.eop.read() ) 
+                        if ( not p_vci_tgt.eop.read() ) 
                         {
                             std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
@@ -481,15 +669,15 @@
                         }
                         r_tgt_update = false; 
-                        r_tgt_brdcast= true;
+                        // r_tgt_brdcast= true;
                         r_vci_tgt_fsm = TGT_REQ_BROADCAST;
-                        m_cpt_cc_inval++ ;
+                        m_cpt_cc_inval_broadcast++ ;
                     }
                     else                    // multi-update or multi-invalidate for data type
                     { 
                         uint32_t cell = address - m_segment.baseAddress(); // addr_40
-                        r_tgt_brdcast = false;
+                        // r_tgt_brdcast = false;
                         if (cell == 0) 
                         {                                       // invalidate data
-                            if ( ! p_vci_tgt.eop.read() ) 
+                            if ( not p_vci_tgt.eop.read() ) 
                             {
                                 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
@@ -499,9 +687,9 @@
                             r_tgt_update = false; 
                             r_vci_tgt_fsm = TGT_REQ_DCACHE;
-                            m_cpt_cc_inval++ ;
+                            m_cpt_cc_inval_dcache++ ;
                         } 
                         else if (cell == 4)                     // invalidate instruction
                         {                         
-                            if ( ! p_vci_tgt.eop.read() ) 
+                            if ( not p_vci_tgt.eop.read() ) 
                             {
                                 std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
@@ -511,7 +699,7 @@
                             r_tgt_update = false; 
                             r_vci_tgt_fsm = TGT_REQ_ICACHE;
-                            m_cpt_cc_inval++ ;
+                            m_cpt_cc_inval_icache++ ;
                         } 
-                        else if ( (cell == 8) || (cell==12) )    // update data or instruction
+                        else if ( (cell == 8) or (cell==12) )    // update data or instruction
                         {                                
                             if ( p_vci_tgt.eop.read() ) 
@@ -522,10 +710,15 @@
                             }
                             if(cell == 8)
+                            {
+                                m_cpt_cc_update_dcache++;
                                 r_tgt_update_data = true;
+                            }
                             else
+                            {
+                                m_cpt_cc_update_icache++;
                                 r_tgt_update_data = false;
+                            }
                             r_tgt_update = true; 
                             r_vci_tgt_fsm = TGT_UPDT_WORD;
-                            m_cpt_cc_update++ ;
                         } 
 
@@ -556,5 +749,5 @@
                 {
                     size_t word = r_tgt_word.read();
-                    if ( word >= m_dcache_words ) 
+                    if ( word >= m_cache_words ) 
                     {
                         std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
@@ -565,8 +758,25 @@
                     std::cout << "PROC " << m_srcid_rw << " update, data : " << p_vci_tgt.wdata.read() << " be : " << std::hex << p_vci_tgt.be.read() << std::dec << std::endl;
 #endif
+
                     r_tgt_buf[word] = p_vci_tgt.wdata.read();
-                    r_tgt_be[word] = p_vci_tgt.be.read();
+                    r_tgt_be [word] = p_vci_tgt.be.read();
+
+                    if (p_vci_tgt.be.read())
+                    {
+                        if(r_tgt_update_data.read())
+                            m_cpt_cc_update_dcache_word_useful++ ;
+                        else
+                            m_cpt_cc_update_icache_word_useful++ ;
+                    }
+
                     r_tgt_word = word + 1;
                     if (p_vci_tgt.eop.read()){
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+                      uint32_t word=0;
+                      for (; word<m_cache_words; ++word)
+                          if (r_tgt_be[word] != 0)
+                              break;
+                      r_cache_word = word;
+#endif
                       if(r_tgt_update_data.read()){
                         r_vci_tgt_fsm = TGT_REQ_DCACHE;
@@ -579,5 +789,5 @@
 
             case TGT_REQ_BROADCAST:
-                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+                if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() ) 
                 {
                     r_vci_tgt_fsm = TGT_RSP_BROADCAST; 
@@ -589,5 +799,5 @@
             case TGT_REQ_ICACHE:
                 {
-                    if ( !r_tgt_icache_req.read() ) 
+                    if ( not r_tgt_icache_req.read() ) 
                     {
                         r_vci_tgt_fsm = TGT_RSP_ICACHE; 
@@ -598,5 +808,5 @@
 
             case TGT_REQ_DCACHE:
-                if ( !r_tgt_dcache_req.read() ) 
+                if ( not r_tgt_dcache_req.read() ) 
                 {
                     r_vci_tgt_fsm = TGT_RSP_DCACHE; 
@@ -606,8 +816,8 @@
 
             case TGT_RSP_BROADCAST:
-                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+                if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() ) 
                 {
                     // one response
-                    if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
+                    if ( not r_tgt_icache_rsp or not r_tgt_dcache_rsp )
                     {
                         if ( p_vci_tgt.rspack.read() )
@@ -620,5 +830,5 @@
 
                     // if data and instruction have the inval line, need two responses  
-                    if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
+                    if ( r_tgt_icache_rsp and r_tgt_dcache_rsp )
                     {
                         if ( p_vci_tgt.rspack.read() )
@@ -629,5 +839,5 @@
 
                     // if there is no need for a response
-                    if ( !r_tgt_icache_rsp && !r_tgt_dcache_rsp )
+                    if ( not r_tgt_icache_rsp and not r_tgt_dcache_rsp )
                     {
                         r_vci_tgt_fsm = TGT_IDLE;
@@ -639,5 +849,5 @@
             case TGT_RSP_ICACHE:
                 {
-                    if ( (p_vci_tgt.rspack.read() || !r_tgt_icache_rsp.read()) && !r_tgt_icache_req.read() ) 
+                    if ( (p_vci_tgt.rspack.read() or not r_tgt_icache_rsp.read()) and not r_tgt_icache_req.read() ) 
                     {
                         r_vci_tgt_fsm = TGT_IDLE;
@@ -649,5 +859,5 @@
             case TGT_RSP_DCACHE:
                 {
-                    if ( (p_vci_tgt.rspack.read() || !r_tgt_dcache_rsp.read()) && !r_tgt_dcache_req.read() ) 
+                    if ( (p_vci_tgt.rspack.read() or not r_tgt_dcache_rsp.read()) and not r_tgt_dcache_req.read() ) 
                     {
                         r_vci_tgt_fsm = TGT_IDLE;
@@ -667,4 +877,5 @@
         // - r_icache_unc_req set
         // - r_icache_buf_unc_valid set
+        // - r_vci_rsp_icache_miss_ok reset
         // - r_vci_rsp_ins_error reset
         // - r_tgt_icache_req reset
@@ -692,11 +903,12 @@
         typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
 
-        typename iss_t::DataRequest  dreq = ISS_DREQ_INITIALIZER;
-        typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
+        typename iss_t::DataRequest         dreq = ISS_DREQ_INITIALIZER;
+        typename iss_t::DataResponse        drsp = ISS_DRSP_INITIALIZER;
 
         m_iss.getRequests( ireq, dreq );
 
-#if DEBUG_CC_XCACHE_WRAPPER
-        std::cout << " Instruction Request: " << ireq << std::endl;
+#if CC_XCACHE_WRAPPER_DEBUG
+        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
+            std::cout << "    * Instruction Request  : " << ireq << std::endl;
 #endif
 
@@ -715,18 +927,36 @@
                         bool    icache_hit = false;
                         bool    icache_cached = m_cacheability_table[(vci_addr_t)ireq.addr];
+                        bool    icache_cleanup_hit = r_icache_cleanup_req and (((addr_40)ireq.addr >> (addr_40)m_icache_words_shift) == r_icache_cleanup_line.read());
+
                         // icache_hit & icache_ins evaluation
                         if ( icache_cached ) {
                             icache_hit = r_icache.read((vci_addr_t) ireq.addr, &icache_ins);
                         } else {
-                            icache_hit = ( r_icache_buf_unc_valid && ((addr_40) ireq.addr == (addr_40)r_icache_addr_save) );
-                            icache_ins = r_icache_miss_buf[0];
+                            // if uncache, again in the icache_miss_buf
+                            icache_hit = ( r_icache_buf_unc_valid and ((addr_40) ireq.addr == (addr_40)r_icache_addr_save));
+                            icache_ins = CACHE_MISS_BUF_RSP_DATA(i,0);
+                            CACHE_MISS_BUF_RSP_POP(i);
                         }
-                        if ( ! icache_hit ) {
+
+                        PRINTF("    * <ICACHE> hit %d - cached %d - cleanup_hit %d\n",icache_hit, icache_cached, icache_cleanup_hit);
+
+                        ASSERT( not (icache_hit and icache_cleanup_hit),
+                                "Icache hit and icache_cleanup_hit");
+
+                        if ( not icache_hit and not icache_cleanup_hit) {
                             m_cpt_ins_miss++;
                             m_cost_ins_miss_frz++;
                             r_icache_addr_save = (addr_40) ireq.addr;
+
+                            CACHE_MISS_BUF_REQ_INIT(i);
+
                             if ( icache_cached ) {
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                                r_icache_fsm = ICACHE_MISS_VICTIM;
+#else
                                 r_icache_fsm = ICACHE_MISS_WAIT;
+#endif
                                 r_icache_miss_req = true;
+                               
                             } else {
                                 r_icache_fsm = ICACHE_UNC_WAIT;
@@ -744,4 +974,25 @@
                 }
                 //////////////////////
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+            case ICACHE_MISS_VICTIM:
+                {
+                    if (not r_icache_cleanup_req)
+                    {
+                        size_t     way;
+                        size_t     set;
+                        vci_addr_t addr = (vci_addr_t) r_icache_addr_save.read();
+                        vci_addr_t victim;
+                        
+                        r_icache_cleanup_req  = r_icache.victim_select(addr, &victim, &way, &set );
+                        r_icache_cleanup_line = (addr_40) victim;
+                        r_icache_miss_way     = way;
+                        r_icache_miss_set     = set;
+                        
+                        r_icache_fsm = ICACHE_MISS_WAIT;
+                    }
+                    break;
+                }
+#endif
+                //////////////////////
             case ICACHE_MISS_WAIT:
                 {
@@ -751,20 +1002,41 @@
                         r_icache_fsm_save = r_icache_fsm.read();
                         break;
-                    } 
-                    if ( !r_icache_miss_req && !r_icache_inval_rsp ) { // Miss read response and no invalidation
-                        if ( r_vci_rsp_ins_error ) {
-                            r_icache_fsm = ICACHE_ERROR;
-                        } else {
-                            r_icache_fsm = ICACHE_MISS_UPDT;
-                        }
-                    }
-                    if ( !r_icache_miss_req && r_icache_inval_rsp ) { // Miss read response and invalidation
-                        if ( r_vci_rsp_ins_error ) {
-                            r_icache_inval_rsp = false;
-                            r_icache_fsm = ICACHE_ERROR;
-                        } else {
-                            r_icache_inval_rsp = false;
-                            r_icache_fsm = ICACHE_CC_CLEANUP;
-                        }
+                    }
+
+                    bool val = CACHE_MISS_BUF_RSP_VAL(i,0);
+
+                    PRINTF("    * <ICACHE> val                  : %d\n",val);
+
+                    if (val)
+                    {
+                        PRINTF("    * <ICACHE> r_icache_inval_rsp   : %d\n",(int) r_icache_inval_rsp  );
+                        PRINTF("    * <ICACHE> r_vci_rsp_ins_error  : %d\n",(int) r_vci_rsp_ins_error );
+                        PRINTF("    * <ICACHE> r_icache_cleanup_req : %d\n",(int) r_icache_cleanup_req);
+
+                        // if (not r_icache_inval_rsp )
+                        // {
+                            // Miss read response and no invalidation
+                            if ( r_vci_rsp_ins_error ) {
+                                r_icache_fsm = ICACHE_ERROR;
+                            } else {
+#if not CC_XCACHE_WRAPPER_SELECT_VICTIM
+                                if (not r_icache_cleanup_req.read())
+#endif
+                                {
+                                    r_icache_update_addr = 0;
+                                    r_icache_fsm         = ICACHE_MISS_UPDT;
+                                }
+                            }
+                        // }
+                        // else
+                        // {
+                        //     r_icache_inval_rsp = false;
+                            
+                        //     // Miss read response and invalidation
+                        //     if ( r_vci_rsp_ins_error )
+                        //         r_icache_fsm = ICACHE_ERROR;
+                        //     else
+                        //         r_icache_fsm = ICACHE_CC_CLEANUP;
+                        // }
                     }
                     break;
@@ -778,6 +1050,10 @@
                         r_icache_fsm_save = r_icache_fsm.read();
                         break;
-                    } 
-                    if ( !r_icache_unc_req ) {
+                    }
+
+                    bool ok = CACHE_MISS_BUF_RSP_VAL(i,0);
+
+                    if (ok)
+                    {
                         if ( r_vci_rsp_ins_error ) {
                             r_icache_fsm = ICACHE_ERROR;
@@ -803,31 +1079,76 @@
             case ICACHE_MISS_UPDT: 
                 {
-                    if ( r_tgt_icache_req ) {   // external request
-                        r_icache_fsm = ICACHE_CC_CHECK;
-                        r_icache_fsm_save = r_icache_fsm.read();
-                        break;
-                    } 
-                    if(!r_icache_cleanup_req.read() && !r_icache_inval_rsp){
-                        vci_addr_t ad   = 0;
-                        ad              = (vci_addr_t) r_icache_addr_save.read();
-                        data_t*   buf   = r_icache_miss_buf;
-                        vci_addr_t victim_index = 0;
-                        m_cpt_icache_dir_write++;
-                        m_cpt_icache_data_write++;
-                        if ( ireq.valid ) m_cost_ins_miss_frz++;
-
-                        r_icache_cleanup_req  = r_icache.update(ad, buf, &victim_index);
-                        r_icache_cleanup_line = (addr_40) victim_index;
-
-                        r_icache_fsm        = ICACHE_IDLE;
-                        break;
-                    }
-                    if(r_icache_inval_rsp){
-                        if ( ireq.valid ) m_cost_ins_miss_frz++;
-                        r_icache_inval_rsp  = false;
-                        r_icache_fsm = ICACHE_CC_CLEANUP;
-                        break;
-                    }
-                    if ( ireq.valid ) m_cost_ins_miss_frz++;
+                    size_t     word = r_icache_update_addr.read();
+                    vci_addr_t addr = (vci_addr_t) r_icache_addr_save.read();
+                    size_t     way  = 0;
+                    size_t     set  = 0;
+
+                    // need invalid rsp, don't select a victim
+                    if (not r_icache_inval_rsp )
+                    {
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                        way = r_icache_miss_way.read();
+                        set = r_icache_miss_set.read();
+#else
+
+                        // First word : select an victim !
+                        if (word == 0)
+                        {
+                            vci_addr_t victim;
+                        
+                            // r_icache_cleanup_req is false because is the transition condition to go in ICACHE_MISS_UPDT state
+                            r_icache_cleanup_req  = r_icache.victim_select(addr, &victim, &way, &set );
+                            r_icache.victim_update_tag(addr, way, set);
+                        
+                            r_icache_cleanup_line = (addr_40) victim;
+                            r_icache_miss_way     = way;
+                            r_icache_miss_set     = set;
+                        }
+                        else
+                        {
+                            way = r_icache_miss_way.read();
+                            set = r_icache_miss_set.read();
+                        }
+#endif
+                    }
+                    bool val = CACHE_MISS_BUF_RSP_VAL(i,word);
+
+                    if (val)
+                    {
+                        PRINTF("    * <ICACHE> rsp_val            : %d/%d\n",(int)r_icache_update_addr,m_icache_words);
+                        PRINTF("    * <ICACHE> r_icache_inval_rsp : %d\n",(int)r_icache_inval_rsp);
+                        PRINTF("    * <ICACHE> ins : %x\n",(int)CACHE_MISS_BUF_RSP_DATA(i,word));
+
+                        // m_cpt_icache_dir_write++;
+                        // m_cpt_icache_data_write++;
+                        // if ( ireq.valid ) m_cost_ins_miss_frz++;
+
+                        // if need invalid rsp, don't modify the cache, but pop the buf_rsp
+                        if (not r_icache_inval_rsp )
+                            r_icache.write(way, set, word, CACHE_MISS_BUF_RSP_DATA(i,word));
+                        CACHE_MISS_BUF_RSP_POP(i);
+
+                        r_icache_update_addr = ++word;
+                            
+                        // if last word, finish the update
+                        if (word >= m_icache_words)
+                        {
+                            // Last word : if previous invalid_rsp, can cleanup, else update the TAG
+                            if (r_icache_inval_rsp)
+                            {
+                                r_icache_inval_rsp  = false;
+                                r_icache_fsm = ICACHE_CC_CLEANUP;
+                            }
+                            else
+                            {
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                                r_icache.victim_update_tag(addr, way, set);
+#endif
+                                r_icache_fsm = ICACHE_IDLE;
+                            }
+                        }
+                    }
+
+                    break;
                 }
                 ////////////////////
@@ -842,7 +1163,7 @@
                     }
                     // cleanup
-                    if(!r_icache_cleanup_req){
+                    if(not r_icache_cleanup_req){
                         r_icache_cleanup_req = true;
-                        r_icache_cleanup_line = r_icache_addr_save.read() >> (uint32_log2(m_icache_words) + 2);   
+                        r_icache_cleanup_line = r_icache_addr_save.read() >> m_icache_words_shift;
                         r_icache_fsm = ICACHE_IDLE;
                     }
@@ -853,10 +1174,10 @@
                 {
 
-                    m_cpt_icache_dir_read += m_icache_ways;
+                    m_cpt_icache_dir_read  += m_icache_ways;
                     m_cpt_icache_data_read += m_icache_ways;
-                    addr_40  ad           = r_tgt_addr;
+                    addr_40 ad = r_tgt_addr;
                     data_t  icache_rdata = 0;
 
-                    if(( ( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT ) ) && 
+                    if((r_icache_fsm_save == ICACHE_MISS_WAIT) and 
                             ( (r_icache_addr_save.read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) {
                         r_icache_inval_rsp = true;
@@ -870,5 +1191,35 @@
                     } else {
                         bool    icache_hit   = r_icache.read(ad, &icache_rdata);
-                        if ( icache_hit && r_tgt_update ) {
+                        if ( icache_hit and r_tgt_update ) 
+                        {
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                            uint32_t word  = r_cache_word;
+                            data_t   mask  = vci_param::be2mask(r_tgt_be[word]);
+                            data_t   rdata = 0;
+
+                            r_icache.read(ad+word*4,&rdata);
+                            r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & rdata);
+                            
+                            word ++;
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+                            for (; word<m_icache_words; ++word)
+                                if (r_tgt_be[word] != 0)
+                                    break;
+#endif
+
+                            if (word==m_icache_words)
+                            {
+                                r_icache_fsm = ICACHE_CC_UPDT;
+
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+                                for (word=0; word<m_icache_words; ++word)
+                                    if (r_tgt_be[word] != 0)
+                                        break;
+#else
+                                word = 0;
+#endif
+                            }
+                            r_cache_word = word;
+#else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
                             r_icache_fsm = ICACHE_CC_UPDT;
                             // complete the line buffer in case of update
@@ -879,5 +1230,6 @@
                                 r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata);
                             }
-                        } else if ( icache_hit && !r_tgt_update ) {
+#endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                        } else if ( icache_hit and not r_tgt_update ) {
                             r_icache_fsm = ICACHE_CC_INVAL;
                         } else { // instruction not found (can happen)
@@ -908,7 +1260,30 @@
             case ICACHE_CC_UPDT:
                 {                       
+                    addr_40 ad = r_tgt_addr.read();
                     m_cpt_icache_dir_write++;
                     m_cpt_icache_data_write++;
-                    addr_40    ad  = r_tgt_addr.read();
+
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                    uint32_t word  = r_cache_word;
+
+                    if(r_tgt_be[word])
+                        r_icache.write(ad+word*4, r_tgt_buf[word]);
+
+                    word ++;
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+                    for (; word<m_icache_words; ++word)
+                        if (r_tgt_be[word] != 0)
+                            break;
+#endif
+
+                    if (word==m_icache_words)
+                    {
+                        r_tgt_icache_req = false;
+                        r_tgt_icache_rsp = true;
+                        r_icache_fsm     = r_icache_fsm_save.read();
+                        word = 0;
+                    }
+                    r_cache_word = word;
+#else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
                     data_t* buf    = r_tgt_buf;
                     for(size_t i=0; i<m_icache_words;i++){
@@ -918,4 +1293,6 @@
                     r_tgt_icache_rsp = true;
                     r_icache_fsm     = r_icache_fsm_save.read();
+#endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+
                     break;
                 }    
@@ -923,6 +1300,7 @@
         } // end switch r_icache_fsm
 
-#if DEBUG_CC_XCACHE_WRAPPER
-        std::cout << " Instruction Response: " << irsp << std::endl;
+#if CC_XCACHE_WRAPPER_DEBUG
+        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
+            std::cout << "    * Instruction Response : " << irsp << std::endl;
 #endif
 
@@ -940,5 +1318,4 @@
         // - r_dcache_miss_req set
         // - r_dcache_unc_req set
-        // - r_dcache_write_req set
         // - r_dcache_cleanup_req set
         // - r_vci_rsp_data_error reset
@@ -984,49 +1361,11 @@
         ///////////////////////////////////////////////////////////////////////////////////
 
-#if DEBUG_CC_XCACHE_WRAPPER
-        std::cout << " Data Request: " << dreq << std::endl;
-#endif
-
-        //if( (m_cpt_total_cycles % 10000) ==0 ) std::cout << std::dec << "Proc " << m_srcid << " Data Request: " << dreq << std::endl;
+#if CC_XCACHE_WRAPPER_DEBUG
+        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
+            std::cout << "    * Data        Request  : " << dreq << std::endl;
+#endif
 
         switch ( r_dcache_fsm ) {
 
-            /////////////////////
-            case DCACHE_WRITE_REQ:
-                { 
-                    if ( r_tgt_dcache_req ) {   // external request
-                        r_dcache_fsm = DCACHE_CC_CHECK;
-                        r_dcache_fsm_save = r_dcache_fsm;
-                        break;
-                    }
-                    // try to post the write request in the write buffer
-                    if ( !r_dcache_write_req ) {    // no previous write transaction     
-                        if ( r_wbuf.wok(r_dcache_addr_save) ) {   // write request in the same cache line
-                            r_wbuf.write(r_dcache_addr_save, r_dcache_be_save, r_dcache_wdata_save);
-                            // close the write packet if uncached
-                            if ( !r_dcache_cached_save ){
-                                r_dcache_write_req = true ;
-                            }
-                        } else {    
-                            // close the write packet if write request not in the same cache line
-                            r_dcache_write_req = true;  
-                            if(!m_srcid_rw) {
-                            }
-                            m_cost_write_frz++;
-                            break;  // posting request not possible : stay in DCACHE_WRITEREQ state
-                        }
-                    } else {    //  previous write transaction not completed
-                        m_cost_write_frz++;
-                        break;  // posting request not possible : stay in DCACHE_WRITEREQ state  
-                    }
-
-                    // close the write packet if the next processor request is not a write 
-                    if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE) ) {
-                        r_dcache_write_req = true ;
-                    }
-
-                    // The next state and the processor request parameters are computed 
-                    // as in the DCACHE_IDLE state (see below ...)
-                }
                 /////////////////
             case DCACHE_IDLE:
@@ -1038,97 +1377,184 @@
                     } 
 
-                    if ( dreq.valid ) {              
-                        bool        dcache_hit     = false;
-                        data_t      dcache_rdata   = 0;
-                        bool        dcache_cached;
+                    if ( dreq.valid ) {
+                        PRINTF("    * <DCACHE> Have dreq\n");
+
+                        data_t      dcache_rdata       = 0;
+                        // dcache_cached and dcache_hit don't used with dreq.type == {DATA_SC, XTN_READ, XTN_WRITE}
+                        bool        dcache_cached      = m_cacheability_table[(vci_addr_t)dreq.addr];
+                        bool        dcache_hit         = r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
+                        bool        dcache_cleanup_hit = r_dcache_cleanup_req and (((addr_40)dreq.addr >> (addr_40)m_dcache_words_shift) == r_dcache_cleanup_line.read());
+
+                        PRINTF("    * <DCACHE> hit %d - cached %d - cleanup_hit %d\n",dcache_hit, dcache_cached, dcache_cleanup_hit);
+                        
                         m_cpt_dcache_data_read += m_dcache_ways;
-                        m_cpt_dcache_dir_read += m_dcache_ways;
-
-                        // dcache_cached evaluation
-                        switch (dreq.type) {
-                            case iss_t::DATA_SC:
-                            case iss_t::XTN_READ:
-                            case iss_t::XTN_WRITE:
-                                dcache_cached = false;
-                                break;
-                            default:
-                                dcache_cached = m_cacheability_table[(vci_addr_t)dreq.addr];
-                        }
-
-                        // dcache_hit & dcache_rdata evaluation
-                        if ( dcache_cached ) {
-                            dcache_hit = r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
-                        } else {
-                            dcache_hit = false;
-                        }
+                        m_cpt_dcache_dir_read  += m_dcache_ways;
 
                         switch( dreq.type ) {
                             case iss_t::DATA_READ:
                             case iss_t::DATA_LL:
-                                m_cpt_read++;
-                                if ( dcache_hit ) {
-                                    r_dcache_fsm = DCACHE_IDLE;
-                                    drsp.valid = true;
-                                    drsp.rdata = dcache_rdata;
-                                    if(dreq.type == iss_t::DATA_LL){
-                                        r_dcache_ll_valid = true;
-                                        r_dcache_ll_data = dcache_rdata;
-                                        r_dcache_ll_addr = (vci_addr_t) dreq.addr;
+                                {
+                                    m_cpt_data_read++; // new dcache read
+
+                                    if (dcache_hit) // no special test for uncached read, because it's always miss
+                                        {
+                                            // address is in the cache : return the word
+                                            r_dcache_fsm = DCACHE_IDLE;
+                                            drsp.valid   = true;
+                                            drsp.rdata   = dcache_rdata; // return read data (cf dcache_hit)
+                                            
+                                            // if the request is a Load Linked instruction, save request information
+                                            if(dreq.type == iss_t::DATA_LL)
+                                                {
+                                                    PRINTF("    * <DCACHE> ll_valid = true\n");
+
+                                                    r_dcache_ll_valid = true;
+                                                    r_dcache_ll_data = dcache_rdata;
+                                                    r_dcache_ll_addr = (vci_addr_t) dreq.addr;
 #ifdef COHERENCE_DEBUG
-                                        std::cout << "Value returned for LL at address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
-                                        r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
-                                        std::cout << "Value stored at this  address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
-#endif
-                                    }
-                                } else {
-                                    if ( dcache_cached ) {
-                                        m_cpt_data_miss++;
-                                        m_cost_data_miss_frz++;
-                                        r_dcache_miss_req = true;
-                                        r_dcache_fsm = DCACHE_MISS_WAIT;
-                                    } else {
-                                        m_cpt_unc_read++;
-                                        m_cost_unc_read_frz++;
-                                        r_dcache_unc_req = true;
-                                        r_dcache_fsm = DCACHE_UNC_WAIT;
-                                    }
+                                                    std::cout << "Value returned for LL at address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
+                                                    r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
+                                                    std::cout << "Value stored at this  address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
+#endif
+                                                }
+                                        }
+                                    else
+                                        {
+                                            if (not dcache_cleanup_hit)
+                                            {
+                                                CACHE_MISS_BUF_REQ_INIT(d);
+                                                
+                                                // Miss : send signal at the CMD_FSM (via r_dcache_miss_req or r_dcache_unc_req)
+                                                if ( dcache_cached ) {
+                                                    m_cpt_data_read_miss++;
+                                                    m_cost_data_miss_frz++;
+                                                    r_dcache_miss_req = true;
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                                                    r_dcache_fsm = DCACHE_MISS_VICTIM;
+#else
+                                                    r_dcache_fsm = DCACHE_MISS_WAIT;
+#endif
+                                                    
+                                                } else {
+                                                    if (not r_dcache_previous_unc.read()) // strongly order to the uncached access
+                                                    {
+                                                        r_dcache_previous_unc = true;
+                                                        
+                                                        m_cpt_data_read_uncached++;
+                                                        m_cost_unc_read_frz++;
+                                                        r_dcache_unc_req = true;
+                                                        r_dcache_fsm = DCACHE_UNC_WAIT;
+                                                    }
+                                                }
+                                            }
+                                        }
                                 }
                                 break;
                             case iss_t::DATA_SC:
                             {
-                                m_cpt_unc_read++;
-                                m_cost_unc_read_frz++;
-                                if(r_dcache_ll_valid.read() && (r_dcache_ll_addr.read() == (vci_addr_t)dreq.addr)){
-                                    r_dcache_sc_req = true;
-                                    r_dcache_fsm = DCACHE_SC_WAIT;
-                                } else {
-                                    drsp.valid = true;
-                                    drsp.rdata = 1; // SC rsp NOK
-                                    r_dcache_ll_valid = false;
+                                PRINTF("    * <DCACHE> DATA_SC - ll_valid = %d\n",r_dcache_ll_valid.read());
+
+                                if (not r_dcache_previous_unc.read() and not dcache_cleanup_hit) // strongly order to the uncached access
+                                {
+                                    //m_cpt_data_read_unc++; // instruction must read the memory in uncached mode
+                                    m_cost_unc_read_frz++;
+                                    
+                                    // if previous load linked (with the same address), make a transaction
+                                    // else, keep in IDLE state and return 1 (no OK)
+                                    if(r_dcache_ll_valid.read() and (r_dcache_ll_addr.read() == (vci_addr_t)dreq.addr)){
+                                        PRINTF("    * <DCACHE> have previous load linked\n");
+                                        
+                                        r_dcache_previous_unc = true;
+
+                                        r_dcache_sc_req   = true;
+
+                                        CACHE_MISS_BUF_REQ_INIT(d);
+
+                                        r_dcache_fsm = DCACHE_SC_WAIT;
+                                    } else {
+                                        PRINTF("    * <DCACHE> don't have previous load linked\n");
+                                        
+                                        drsp.valid = true;
+                                        drsp.rdata = 1; // SC rsp NOK
+                                        r_dcache_ll_valid = false;
+                                    }
                                 }
+
                                 break;
                             }
                             case iss_t::XTN_READ:
                             case iss_t::XTN_WRITE:
-                                    // only DCACHE INVALIDATE request are supported
-                                    if ( dreq.addr/4 == iss_t::XTN_DCACHE_INVAL ){
-                                        r_dcache_fsm = DCACHE_INVAL;
-                                    } else {
-                                        r_dcache_fsm = DCACHE_IDLE;
-                                    }
-                                    drsp.valid = true;
+                                {
+                                    bool drsp_valid = false;
+                                    // only DCACHE INVALIDATE and SYNC request are supported
+                                    switch (dreq.addr>>2)
+                                        {
+                                        case iss_t::XTN_DCACHE_INVAL : 
+                                            {
+                                                drsp_valid = true;
+                                                r_dcache_fsm = DCACHE_INVAL;
+                                                break;
+                                            }
+                                        case iss_t::XTN_SYNC :
+                                            {
+                                                // Test if write buffer is already empty
+                                                //  * gain : 1 cycle
+                                                //  * cost : can be on the critical path
+                                                if (r_wbuf.empty())
+                                                    {
+                                                        drsp_valid = true;
+                                                        r_dcache_fsm = DCACHE_IDLE;
+                                                    }
+                                                else
+                                                    {
+                                                        drsp_valid = false;
+                                                        r_dcache_fsm = DCACHE_SYNC;
+                                                    }
+                                                break;
+                                            }
+                                        default :
+                                            {
+                                                // std::cout << "Warning in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                                                // std::cout << "Unsupported  external access : " << (dreq.addr>>2) << std::endl;
+
+                                                r_dcache_fsm = DCACHE_IDLE;
+                                            }
+                                        }//end switch (dreq.addr>>2)
+
+                                    drsp.valid = drsp_valid;
                                     drsp.rdata = 0;
                                     break;
+                                }
                             case iss_t::DATA_WRITE:
-                                    m_cpt_write++;
-                                    if ( dcache_hit && dcache_cached ) {
-                                        r_dcache_fsm = DCACHE_WRITE_UPDT;
-                                        m_cpt_write_cached++;
-                                    } else {
-                                        r_dcache_fsm = DCACHE_WRITE_REQ;
+
+                                if (dcache_cached or not r_dcache_previous_unc.read()) // strongly order to the uncached access
+                                {
+                                    bool drsp_valid;
+
+                                    drsp_valid = r_wbuf.write((addr_40) dreq.addr, dreq.be, dreq.wdata, dcache_cached);
+
+                                    if (drsp_valid)
+                                    {
+                                        m_cpt_data_write++;
+                                        
+                                        if (not dcache_cached)
+                                        {
+                                            r_dcache_previous_unc = true;
+                                            m_cpt_data_write_uncached++;
+                                        }
+                                        else if (not dcache_hit)
+                                            m_cpt_data_write_miss++;
+                                        
+                                        if ( dcache_hit) {
+                                            r_dcache_fsm = DCACHE_WRITE_UPDT;
+                                        } else {
+                                            r_dcache_fsm = DCACHE_IDLE;
+                                        }
                                     }
-                                    drsp.valid = true;
+
+                                    drsp.valid = drsp_valid;
                                     drsp.rdata = 0;
-                                    break;
+                                }
+                                break;
                         } // end switch dreq.type
 
@@ -1139,15 +1565,9 @@
                         r_dcache_rdata_save     = dcache_rdata;
                         r_dcache_cached_save    = dcache_cached;
-
+                        
                     } else {    // end if dreq.valid
                         r_dcache_fsm = DCACHE_IDLE;
                     }
-                    // processor request are not accepted in the WRITE_REQUEST state
-                    // when the write buffer is not writeable
-                    if ( (r_dcache_fsm == DCACHE_WRITE_REQ) &&
-                            (r_dcache_write_req || !r_wbuf.wok(r_dcache_addr_save)) ) {
-                        drsp.valid = false;
-                        drsp.rdata = 0;
-                    }
+                    
                     break;
                 }
@@ -1160,7 +1580,31 @@
                     vci_addr_t ad = r_dcache_addr_save.read();
                     r_dcache.write(ad, wdata);
-                    r_dcache_fsm = DCACHE_WRITE_REQ;
+
+                    r_dcache_fsm = DCACHE_IDLE;
+
                     break;
                 }
+                //////////////////////
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+            case DCACHE_MISS_VICTIM:
+                {
+                    if (not r_dcache_cleanup_req.read())
+                     {
+                         size_t     way;
+                         size_t     set;
+                         vci_addr_t addr = (vci_addr_t) r_dcache_addr_save.read();
+                         vci_addr_t victim;
+                         
+                         r_dcache_cleanup_req  = r_dcache.victim_select(addr, &victim, &way, &set );
+                         r_dcache_cleanup_line = (addr_40) victim;
+                         r_dcache_miss_way     = way;
+                         r_dcache_miss_set     = set;
+                         
+                         r_dcache_fsm = DCACHE_MISS_WAIT;
+                     }
+                    
+                    break;
+                }
+#endif
                 //////////////////////
             case DCACHE_MISS_WAIT:
@@ -1173,21 +1617,38 @@
                         break;
                     }
-                    if ( !r_dcache_miss_req && !r_dcache_inval_rsp ) { // Miss read response and no invalidation
-                        if ( r_vci_rsp_data_error ) {
+
+                    bool val = CACHE_MISS_BUF_RSP_VAL(d,0);
+                    if (val)
+                    {
+                        // if (not r_dcache_inval_rsp )
+                        //  {
+
+                        // Miss read response and no invalidation
+                        if ( r_vci_rsp_data_error )
+                        {
                             r_dcache_fsm = DCACHE_ERROR;
-                        } else {
-                            r_dcache_fsm = DCACHE_MISS_UPDT;
+                        } 
+                        else 
+                        {
+#if not CC_XCACHE_WRAPPER_SELECT_VICTIM
+                            if (not r_dcache_cleanup_req.read())
+#endif
+                            {
+                                r_dcache_update_addr = 0;
+                                r_dcache_fsm         = DCACHE_MISS_UPDT;
+                            }
                         }
-                        break;
-                    }
-                    if ( !r_dcache_miss_req && r_dcache_inval_rsp ) { // Miss read response and invalidation
-                        if ( r_vci_rsp_data_error ) {
-                            r_dcache_inval_rsp  = false;
-                            r_dcache_fsm = DCACHE_ERROR;
-                        } else {
-                            r_dcache_inval_rsp  = false;
-                            r_dcache_fsm = DCACHE_CC_CLEANUP;
-                        }
-                        break;
+                        //  }
+                        // else
+                        // {
+                        //     r_dcache_inval_rsp  = false;
+
+                        //     // Miss read response and invalidation
+                        //     if ( r_vci_rsp_data_error ) {
+                        //         r_dcache_fsm = DCACHE_ERROR;
+                        //     } else {
+                        //         r_dcache_fsm = DCACHE_CC_CLEANUP;
+                        //     }
+                        // }
                     }
                     break;
@@ -1195,35 +1656,73 @@
                 //////////////////////
             case DCACHE_MISS_UPDT:
-
-                {
-                        if ( r_tgt_dcache_req.read() ) {   // external request
-                        r_dcache_fsm = DCACHE_CC_CHECK;
-                        r_dcache_fsm_save = r_dcache_fsm;
-                        break;
-                    }
-                    if( !r_dcache_cleanup_req.read() && !r_dcache_inval_rsp ){
-                        vci_addr_t  ad  = 0;
-                        ad = (vci_addr_t) r_dcache_addr_save.read();
-                        data_t* buf = new data_t[m_dcache_words];
-                        for(size_t i=0; i<m_dcache_words; i++) {
-                            buf[i] = r_dcache_miss_buf[i];
+                {
+                    size_t     word = r_dcache_update_addr.read();
+                    vci_addr_t addr = (vci_addr_t) r_dcache_addr_save.read();
+                    size_t     way  = 0;
+                    size_t     set  = 0;
+                    
+                    // need invalid rsp, don't select a victim
+                    if (not r_dcache_inval_rsp )
+                    {
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                        way = r_dcache_miss_way.read();
+                        set = r_dcache_miss_set.read();
+#else
+                        // First word : select an victim !
+                        if (word == 0)
+                        {
+                            vci_addr_t victim;
+                        
+                            // r_dcache_cleanup_req is false (condition to enter in DCACHE_MISS_UPDT
+                            r_dcache_cleanup_req  = r_dcache.victim_select(addr, &victim, &way, &set );
+                            r_dcache.victim_update_tag(addr, way, set);
+                            r_dcache_cleanup_line = (addr_40) victim;
+
+                            r_dcache_miss_way     = way;
+                            r_dcache_miss_set     = set;
                         }
-                        vci_addr_t  victim_index = 0;
-                        if ( dreq.valid ) m_cost_data_miss_frz++;
-                        m_cpt_dcache_data_write++;
-                        m_cpt_dcache_dir_write++;
-
-                        r_dcache_cleanup_req = r_dcache.update(ad, buf, &victim_index);
-                        r_dcache_cleanup_line = (addr_40) victim_index;
-
-                        r_dcache_fsm = DCACHE_IDLE;
-                        delete [] buf;
-                        break;
-                    }
-                    if( r_dcache_inval_rsp ){
-                        r_dcache_inval_rsp  = false;
-                        r_dcache_fsm = DCACHE_CC_CLEANUP;
-                        break;
-                    }
+                        else
+                        {
+                            way = r_dcache_miss_way.read();
+                            set = r_dcache_miss_set.read();
+                        }
+#endif
+                    }
+
+                    bool val = CACHE_MISS_BUF_RSP_VAL(d,word);
+                    if (val)
+                    {
+                        // m_cpt_dcache_dir_write++;
+                        // if ( ireq.valid ) m_cost_data_miss_frz++;
+
+                        // if need invalid rsp, don't modify the cache, but pop the buf_rsp
+                        if (not r_dcache_inval_rsp )
+                        {
+                            r_dcache.write(way, set, word, CACHE_MISS_BUF_RSP_DATA(d,word));
+                            m_cpt_dcache_data_write++;
+                        }
+
+                        CACHE_MISS_BUF_RSP_POP(d);
+                        r_dcache_update_addr = ++word;
+                            
+                        // if last word, finish the update
+                        if (word >= m_dcache_words)
+                        {
+                            // Last word : if previous invalid_rsp, can cleanup, else update the TAG
+                            if (r_dcache_inval_rsp)
+                            {
+                                r_dcache_inval_rsp  = false;
+                                r_dcache_fsm = DCACHE_CC_CLEANUP;
+                            }
+                            else
+                            {
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                                r_dcache.victim_update_tag(addr, way, set);
+#endif
+                                r_dcache_fsm = DCACHE_IDLE;
+                            }
+                        }
+                    }
+                
                     break;
                 }
@@ -1237,16 +1736,24 @@
                         break;
                     } 
-                    if ( !r_dcache_unc_req ) {
+
+                    bool ok = CACHE_MISS_BUF_RSP_VAL(d,0);
+
+                    if (ok) {
                         if ( r_vci_rsp_data_error ) {
                             r_dcache_fsm = DCACHE_ERROR;
                         } else {
+                            data_t rdata = CACHE_MISS_BUF_RSP_DATA(d,0);
+                            CACHE_MISS_BUF_RSP_POP(d);
+
                             if(dreq.type == iss_t::DATA_LL){
+                                PRINTF("    * <DCACHE> ll_valid = true\n");
+
                                 r_dcache_ll_valid = true;
-                                r_dcache_ll_data = r_dcache_miss_buf[0];
+                                r_dcache_ll_data = rdata;
                                 r_dcache_ll_addr = (vci_addr_t) dreq.addr;
                             }
                             r_dcache_fsm = DCACHE_IDLE;
                             drsp.valid = true;
-                            drsp.rdata = r_dcache_miss_buf[0];
+                            drsp.rdata = rdata;
                         }
                     }
@@ -1262,5 +1769,8 @@
                         break;
                     } 
-                    if ( !r_dcache_sc_req ) {
+
+                    bool ok = CACHE_MISS_BUF_RSP_VAL(d,0);
+
+                    if (ok) {
                         if ( r_vci_rsp_data_error ) {
                             r_dcache_fsm = DCACHE_ERROR;
@@ -1268,5 +1778,6 @@
                             r_dcache_fsm = DCACHE_IDLE;
                             drsp.valid = true;
-                            drsp.rdata = r_dcache_miss_buf[0];
+                            drsp.rdata = CACHE_MISS_BUF_RSP_DATA(d,0);
+                            CACHE_MISS_BUF_RSP_POP(d);
                             r_dcache_ll_valid = false;
                         }
@@ -1292,12 +1803,27 @@
                         break;
                     }
-                    if( !r_dcache_cleanup_req.read() ){
+                    if( not r_dcache_cleanup_req.read() ){
                         m_cpt_dcache_dir_read += m_dcache_ways;
                         vci_addr_t  ad  = r_dcache_addr_save.read();
                         r_dcache_cleanup_req = r_dcache.inval(ad);
-                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> (uint32_log2(m_dcache_words)+2);
+                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> m_dcache_words_shift;
 
                         r_dcache_fsm = DCACHE_IDLE;
                     }
+                    break;
+                }
+            case DCACHE_SYNC :
+                {
+                    if ( r_tgt_dcache_req ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    } 
+
+                    if (r_wbuf.empty())
+                        {
+                            drsp.valid = true; // end, can accept the sync request
+                            r_dcache_fsm = DCACHE_IDLE;
+                        }
                     break;
                 }
@@ -1305,11 +1831,8 @@
             case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
                 {
-
-                    m_cpt_dcache_dir_read += m_dcache_ways;
-                    m_cpt_dcache_data_read += m_dcache_ways;
-                    addr_40  ad           = r_tgt_addr;
+                    addr_40  ad          = r_tgt_addr;
                     data_t  dcache_rdata = 0;
 
-                    if(( ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) && 
+                    if((r_dcache_fsm_save == DCACHE_MISS_WAIT) and 
                             ( (r_dcache_addr_save.read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) {
                         r_dcache_inval_rsp = true;
@@ -1323,8 +1846,42 @@
                     } else {
                         bool    dcache_hit   = r_dcache.read(ad, &dcache_rdata);
+
+                        m_cpt_dcache_data_read += m_dcache_ways;
+                        m_cpt_dcache_dir_read += m_dcache_ways;
+
 #ifdef COHERENCE_DEBUG
                         std::cout << "PROC " << m_srcid_rw << " DCACHE_CC_CHECK, hit ? : " << dcache_hit << std::endl;
 #endif
-                        if ( dcache_hit && r_tgt_update ) {
+                        if ( dcache_hit and r_tgt_update ) 
+                        {
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                            uint32_t word  = r_cache_word;
+                            data_t   mask  = vci_param::be2mask(r_tgt_be[word]);
+                            data_t   rdata = 0;
+
+                            r_dcache.read(ad+word*4,&rdata);
+                            
+                            r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & rdata);
+
+                            word ++;
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+                            for (; word<m_dcache_words; ++word)
+                                if (r_tgt_be[word] != 0)
+                                    break;
+#endif
+
+                            if (word==m_dcache_words)
+                            {
+                                r_dcache_fsm = DCACHE_CC_UPDT;
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+                                for (word=0; word<m_dcache_words; ++word)
+                                    if (r_tgt_be[word] != 0)
+                                        break;
+#else
+                                word = 0;
+#endif
+                            }
+                            r_cache_word = word;
+#else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
                             // complete the line buffer in case of update
                             for(size_t i=0; i<m_dcache_words; i++){
@@ -1335,5 +1892,6 @@
                             }
                             r_dcache_fsm = DCACHE_CC_UPDT;
-                        } else if ( dcache_hit && !r_tgt_update ) {
+#endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                        } else if ( dcache_hit and not r_tgt_update ) {
                             r_dcache_fsm = DCACHE_CC_INVAL;
                         } else {
@@ -1352,20 +1910,51 @@
             case DCACHE_CC_UPDT:    // update directory and data cache        
                 {
+                    addr_40 ad = r_tgt_addr;
+
                     m_cpt_dcache_dir_write++;
                     m_cpt_dcache_data_write++;
-                    addr_40  ad      = r_tgt_addr;
-                    data_t* buf     = r_tgt_buf;
-#ifdef COHERENCE_DEBUG
+
+# ifdef COHERENCE_DEBUG
                     std::cout << "PROC " << m_srcid_rw << " DCACHE_CC_UPDT, update : " << std::endl;
-#endif
+# endif
+
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                    uint32_t word  = r_cache_word;
+                    
+                    if(r_tgt_be[word])
+                        r_dcache.write(ad+word*4, r_tgt_buf[word]);
+# ifdef COHERENCE_DEBUG
+                    std::cout << " address " << std::hex << ad+word*4 << " data " << std::dec << r_tgt_buf[word] << std::endl;
+                    data_t rdata = 0xAAAAAAAA;
+                    r_dcache.read(ad+word*4,&rdata);
+                    std::cout << "data written " << rdata << std::endl; 
+# endif
+
+                    word ++;
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+                    for (; word<m_dcache_words; ++word)
+                        if (r_tgt_be[word] != 0)
+                            break;
+#endif
+                    
+                    if (word==m_dcache_words)
+                    {
+                        r_tgt_dcache_req = false;
+                        r_tgt_dcache_rsp = true;
+                        r_dcache_fsm = r_dcache_fsm_save;
+                        word = 0;
+                    }
+                    r_cache_word = word;
+#else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                    data_t* buf = r_tgt_buf;
                     for(size_t i=0; i<m_dcache_words; i++){
                         if(r_tgt_be[i]) {
                             r_dcache.write( ad + i*4, buf[i]);
-#ifdef COHERENCE_DEBUG
+# ifdef COHERENCE_DEBUG
                             std::cout << " address " << std::hex << ad+i*4 << " data " << std::dec << buf[i] << std::endl;
                             data_t rdata = 0xAAAAAAAA;
                             r_dcache.read(ad + i*4,&rdata);
                             std::cout << "data written " << rdata << std::endl; 
-#endif
+# endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
                         }
                     }
@@ -1373,4 +1962,5 @@
                     r_tgt_dcache_rsp = true;
                     r_dcache_fsm = r_dcache_fsm_save;
+#endif
                     break;
                 }
@@ -1396,7 +1986,7 @@
                     }        
                     // cleanup
-                    if(!r_dcache_cleanup_req){
+                    if(not r_dcache_cleanup_req){
                         r_dcache_cleanup_req = true;
-                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> (uint32_log2(m_dcache_words) + 2);
+                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> m_dcache_words_shift;
                         r_dcache_fsm = DCACHE_IDLE;
                     }
@@ -1405,7 +1995,22 @@
 
         } // end switch r_dcache_fsm
-
-#if DEBUG_CC_XCACHE_WRAPPER
-        std::cout << " Data Response: " << drsp << std::endl;
+        
+        ////////// write buffer state update  /////////////
+        // The update() method must be called at each cycle to update the internal state.
+        // All pending write requests must be locked in case of SYNC
+        bool wbuf_flush=(r_dcache_fsm == DCACHE_SYNC);
+#if   (CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME==1)
+        r_wbuf.update_multi_scan      (wbuf_flush);
+#elif (CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME==2)
+        r_wbuf.update_round_robin_scan(wbuf_flush);
+#elif (CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME==3)
+        r_wbuf.update_one_scan        (wbuf_flush);
+#else
+        r_wbuf.update                 (wbuf_flush);
+#endif
+
+#if CC_XCACHE_WRAPPER_DEBUG
+        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
+            std::cout << "    * Data        Response : " << drsp << std::endl;
 #endif
 
@@ -1418,6 +2023,137 @@
         }
 
-        if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) ) m_cpt_frz_cycles++;
-
+        if ( (ireq.valid and not irsp.valid) or 
+             (dreq.valid and not drsp.valid))
+        {
+            m_cpt_frz_cycles++;
+#if CC_XCACHE_WRAPPER_STOP_SIMULATION
+            m_stop_simulation_nb_frz_cycles ++;
+            
+            if (m_stop_simulation and (m_stop_simulation_nb_frz_cycles >= m_stop_simulation_nb_frz_cycles_max))
+            {
+                std::cout << std::dec << "CC_XCACHE_WRAPPER \"" << name() << "\" : cycle " << m_cpt_total_cycles << ", the cpu is frozen since " << m_stop_simulation_nb_frz_cycles << " cycles." << std::endl;
+                ASSERT(false,"CPU : anormal activity"); // exit
+            }
+        }
+        else
+        {
+            m_stop_simulation_nb_frz_cycles = 0; // reinit counter
+#endif //CC_XCACHE_WRAPPER_STOP_SIMULATION
+        }
+
+
+#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
+        if (dreq.valid and drsp.valid)
+        {
+            log_dcache_transaction_file 
+                << "[" << m_cpt_total_cycles << "]"
+                << std::hex
+                << " @ "     << std::setw(8) << (uint32_t)dreq.addr
+                << " be "    << std::setw(1) << (uint32_t)dreq.be
+                << " W "     << std::setw(8) << (uint32_t)dreq.wdata
+                << " R "     << std::setw(8) << (uint32_t)drsp.rdata
+                << " error "            << (uint32_t)drsp.error
+                << std::dec
+                << " "  << type_str(dreq.type);
+
+            if ((dreq.type == iss_t::XTN_READ) or 
+                (dreq.type == iss_t::XTN_WRITE))
+                //log_dcache_transaction_file << xtn_str(dreq.addr>>2);
+                switch (dreq.addr>>2)
+                {
+                case iss_t::XTN_DCACHE_INVAL : log_dcache_transaction_file << " INVAL"; break;
+                case iss_t::XTN_SYNC         : log_dcache_transaction_file << " SYNC"; break;
+                default                      : log_dcache_transaction_file << " invalid"; break;
+                }                                                                            
+
+            log_dcache_transaction_file << std::endl;
+
+            // printf("[%d] @ %.8x be %.1x W %.8x R %.8x error %d - %s"
+            //        ,(uint32_t)m_cpt_total_cycles
+            //        ,(uint32_t)dreq.addr
+            //        ,(uint32_t)dreq.be
+            //        ,(uint32_t)dreq.wdata
+            //        ,(uint32_t)drsp.rdata
+            //        ,(uint32_t)drsp.error
+            //        ,type_str(dreq.type));
+            // if ((dreq.type == iss_t::XTN_READ) or 
+            //     (dreq.type == iss_t::XTN_WRITE))
+            //     //     printf(" %s",xtn_str(dreq.addr>>2));
+            //     switch (dreq.addr>>2)
+            //     {
+            //     case iss_t::XTN_DCACHE_INVAL : printf(" INVAL"); break;
+            //     case iss_t::XTN_SYNC         : printf(" SYNC"); break;
+            //     default                      : printf(" invalid"); break;
+            //     }                                                                            
+            // printf("\n");
+        }
+#endif //CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
+
+        ////////////////////////////////////////////////////////////////////////////
+        // This CLEANUP FSM controls the transmission of the cleanup transactions
+        // on the coherence network. It controls the following ressources:
+        // - r_cleanup_fsm
+        // - r_dcache_cleanup_req (reset)
+        // - r_icache_cleanup_req (reset)
+        // 
+        // This FSM handles cleanup requests from both the DCACHE FSM & ICACHE FSM
+        // - Instruction Cleanup  : r_icache_cleanup_req 
+        // - Data Cleanup         : r_dcache_cleanup_req 
+        // In case of simultaneous requests, the data request have highest priority.
+        // There is only one cleanup transaction at a given time (sequencial behavior)
+        // because the same FSM controls both command & response. 
+        // The the r_icache_cleanup_req & r_dcache_cleanup_req are reset only
+        // when the response packet is received.
+        // Error handling :
+        // As the coherence trafic is controled by hardware, errors are not reported
+        // to software : In case of errors, the simulation stops.
+        ////////////////////////////////////////////////////////////////////////////
+
+        switch (r_cleanup_fsm) {
+
+            case CLEANUP_IDLE:
+            {    
+                if ( p_vci_ini_c.cmdack )
+                {
+                    if      (r_dcache_cleanup_req) 	r_cleanup_fsm = CLEANUP_DCACHE;
+                    else if (r_icache_cleanup_req) 	r_cleanup_fsm = CLEANUP_ICACHE;
+                }
+                break;
+            }
+            case CLEANUP_DCACHE:
+            {
+                if ( p_vci_ini_c.rspval )
+                {
+                    PRINTF("      * <CLEANUP> rerror : %d (%d)\n",(uint32_t)p_vci_ini_c.rerror.read(),0x2 & ( (1 << vci_param::E) - 1));
+
+                    ASSERT(p_vci_ini_c.reop and (p_vci_ini_c.rtrdid.read() == TYPE_DATA_CLEANUP),
+                            "illegal response packet received for a cleanup transaction");
+                    ASSERT(p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL,
+                           "error signaled in a cleanup response" );
+                    
+                    r_cleanup_fsm = CLEANUP_IDLE;
+                    r_dcache_cleanup_req = false;
+                    // m_cpt_cc_cleanup_data++; TODO
+                }
+                break;
+            }
+            case CLEANUP_ICACHE:
+            {
+                if ( p_vci_ini_c.rspval )
+                {
+                    PRINTF("      * <CLEANUP> rerror : %d (%d)\n",(uint32_t)p_vci_ini_c.rerror.read(),0x2 & ( (1 << vci_param::E) - 1));
+
+                    ASSERT(p_vci_ini_c.reop and (p_vci_ini_c.rtrdid.read() == TYPE_INS_CLEANUP),
+                           "illegal response packet received for a cleanup transaction");
+                    ASSERT(p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL, 
+                           "error signaled in a cleanup response" );
+                    
+                    r_cleanup_fsm = CLEANUP_IDLE;
+                    r_icache_cleanup_req = false;
+                    // m_cpt_cc_cleanup_ins++; TODO
+                }
+                break;
+            }
+        } // end switch r_cleanup_fsm    
 
         ////////////////////////////////////////////////////////////////////////////
@@ -1427,14 +2163,18 @@
         // - r_vci_cmd_max
         // - r_vci_cmd_cpt
-        // - wbuf reset
+        // - wbuf (reset)
+        // - r_icache_miss_req (reset)
+        // - r_icache_unc_req (reset)
+        // - r_dcache_miss_req (reset)
+        // - r_dcache_sc_req (reset)
         //
         // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
         // There is 7 request types, with the following priorities : 
-        // 1 - Instruction Miss     : r_icache_miss_req
-        // 2 - Data Write           : r_dcache_write_req
-        // 3 - Data Read Miss       : r_dcache_miss_req 
-        // 4 - Data Read Uncached   : r_dcache_unc_req 
-        // 5 - Instruction Cleanup  : r_icache_cleanup_req 
-        // 6 - Data Cleanup         : r_dcache_cleanup_req 
+        // 1 - Data Read Miss         : r_dcache_miss_req and miss in the write buffer
+        // 2 - Data Read Uncachable   : r_dcache_unc_req  and miss in the write buffer
+        // 3 - Instruction Miss       : r_icache_miss_req and miss in the write buffer
+        // 4 - Instruction Uncachable : r_icache_unc_req  and miss in the write buffer
+        // 5 - Data Write             : r_wbuf.rok()      
+        // 6 - Data Store Conditionnal: r_dcache_sc_req
         // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM 
         // and RSP_FSM exit simultaneously the IDLE state.
@@ -1447,40 +2187,95 @@
         //////////////////////////////////////////////////////////////////////////////
 
+        r_vci_cmd_dcache_prior = not r_vci_cmd_dcache_prior;
+
         switch (r_vci_cmd_fsm) {
 
             case CMD_IDLE:
-                if (r_vci_rsp_fsm != RSP_IDLE) break;
+                {
+                // if (r_vci_rsp_fsm != RSP_IDLE) break;
+
+                size_t	min;
+                size_t	max;
 
                 r_vci_cmd_cpt = 0;
-                if ( r_icache_cleanup_req ) { 
-                    r_vci_cmd_fsm = CMD_INS_CLEANUP; 
-                } else if ( r_dcache_cleanup_req ) { 
-                    r_vci_cmd_fsm = CMD_DATA_CLEANUP;
-                } else if ( r_icache_miss_req ) { 
+
+                // Requests :
+
+                // multi_write_buffer access is conditionnal with dcache_miss_req and icache_miss_req
+
+#if   (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==1)
+                //  1) two access authorized
+                bool dcache_miss_req =  r_dcache_miss_req;
+                bool icache_miss_req =  r_icache_miss_req;
+#elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==2)
+                //  2) one access with static priority (dcache prior)
+                bool dcache_miss_req = r_dcache_miss_req; // dcache prior
+                bool icache_miss_req = not dcache_miss_req and r_icache_miss_req;
+#elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==3)
+                //  3) one access with static priority (icache prior)
+                bool icache_miss_req = r_icache_miss_req;
+                bool dcache_miss_req = not icache_miss_req and r_dcache_miss_req; // dcache prior
+#elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==4)
+                //  4) one access with round robin priority
+                bool dcache_miss_req = ((r_dcache_miss_req and not r_icache_miss_req) or // only dcache
+                                        (r_dcache_miss_req and r_vci_cmd_dcache_prior)); // dcache prior
+                bool icache_miss_req = not dcache_miss_req and r_icache_miss_req;
+#else
+#error "Invalid value to CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY"
+#endif
+                // 1 - Data Read
+                if (dcache_miss_req and r_wbuf.miss(r_dcache_addr_save))
+                { 
+                    r_vci_cmd_fsm = CMD_DATA_MISS;
+                    r_dcache_miss_req = false;
+                    m_cpt_dmiss_transaction++; 
+                } 
+
+                // 2 - Data Read Uncachable
+                else if ( r_dcache_unc_req )
+                { 
+                    r_vci_cmd_fsm = CMD_DATA_UNC;
+                    r_dcache_unc_req = false;
+                 // m_cpt_data_unc_transaction++; 
+                }
+
+                // 3 - Instruction Miss
+                else if (icache_miss_req and r_wbuf.miss(r_icache_addr_save))
+                { 
                     r_vci_cmd_fsm = CMD_INS_MISS; 
+                    r_icache_miss_req = false;
                     m_cpt_imiss_transaction++;
-                } else if ( r_icache_unc_req ) { 
+                } 
+
+                // 4 - Instruction Uncachable
+                else if ( r_icache_unc_req )
+                { 
                     r_vci_cmd_fsm = CMD_INS_UNC; 
-                    m_cpt_imiss_transaction++;
-                } else if ( r_dcache_write_req ) { 
+                    r_icache_unc_req = false;
+                 // m_cpt_ins_unc_transaction++;
+                }
+
+                // 5 - Data Write
+                else if ( r_wbuf.rok(&min, &max) ) 
+                { 
                     r_vci_cmd_fsm = CMD_DATA_WRITE;
-                    r_vci_cmd_cpt = r_wbuf.getMin();
-                    r_vci_cmd_min = r_wbuf.getMin();
-                    r_vci_cmd_max = r_wbuf.getMax(); 
-                    m_cpt_write_transaction++; 
-                    m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1); 
-                } else if ( r_dcache_miss_req ) { 
-                    r_vci_cmd_fsm = CMD_DATA_MISS;
-                    m_cpt_dmiss_transaction++; 
-                } else if ( r_dcache_unc_req ) { 
-                    r_vci_cmd_fsm = CMD_DATA_UNC;
-                    m_cpt_unc_transaction++; 
-                } else if ( r_dcache_sc_req ) { 
+                    r_vci_cmd_cpt = min;
+                    r_vci_cmd_min = min;
+                    r_vci_cmd_max = max;
+                    m_cpt_data_write_transaction++; 
+                    m_length_write_transaction += (max-min+1); 
+                } 
+
+                // 6 - Data Store Conditionnal
+                else if ( r_dcache_sc_req ) 
+                { 
                     r_vci_cmd_fsm = CMD_DATA_SC;
                     r_vci_cmd_max = 1; 
                     m_cpt_unc_transaction++; 
-                }
-                break;
-
+                    r_dcache_sc_req = false;
+                }
+
+                break;
+                }
             case CMD_DATA_WRITE:
                 if ( p_vci_ini_rw.cmdack.read() ) {
@@ -1488,5 +2283,5 @@
                     if (r_vci_cmd_cpt == r_vci_cmd_max) {
                         r_vci_cmd_fsm = CMD_IDLE ;
-                        r_wbuf.reset() ;
+                        r_wbuf.sent() ;
                     }
                 }
@@ -1509,10 +2304,4 @@
                 }
                 break;
-            case CMD_INS_CLEANUP:
-            case CMD_DATA_CLEANUP:
-                if ( p_vci_ini_c.cmdack.read() ) {
-                    r_vci_cmd_fsm = CMD_IDLE;
-                }
-                break;
 
         } // end  switch r_vci_cmd_fsm
@@ -1523,9 +2312,4 @@
         // - r_icache_miss_buf[m_icache_words]
         // - r_dcache_miss_buf[m_dcache_words]
-        // - r_icache_miss_req reset
-        // - r_icache_unc_req reset
-        // - r_dcache_miss_req reset
-        // - r_icache_cleanup_req reset
-        // - r_dcache_cleanup_req reset
         // - r_vci_rsp_data_error set
         // - r_vci_rsp_ins_error set
@@ -1552,120 +2336,153 @@
 
             case RSP_IDLE:
-                if(p_vci_ini_rw.rspval.read()||
-                        p_vci_ini_c.rspval.read())
-                {
-                    std::cout << "CC_XCache " << m_srcid_rw << " Unexpected response" << std::endl;
-                }
-                assert( ! p_vci_ini_rw.rspval.read() && ! p_vci_ini_c.rspval.read() && "Unexpected response" );
-                if (r_vci_cmd_fsm != CMD_IDLE) break;
-
-                r_vci_rsp_cpt = 0;
-                if      ( r_icache_cleanup_req )    r_vci_rsp_fsm = RSP_INS_CLEANUP;
-                else if ( r_dcache_cleanup_req )    r_vci_rsp_fsm = RSP_DATA_CLEANUP;
-                else if ( r_icache_miss_req )       r_vci_rsp_fsm = RSP_INS_MISS;
-                else if ( r_icache_unc_req )        r_vci_rsp_fsm = RSP_INS_UNC;
-                else if ( r_dcache_write_req )      r_vci_rsp_fsm = RSP_DATA_WRITE;
-                else if ( r_dcache_miss_req )       r_vci_rsp_fsm = RSP_DATA_MISS;
-                else if ( r_dcache_unc_req )        r_vci_rsp_fsm = RSP_DATA_UNC;
-                else if ( r_dcache_sc_req )         r_vci_rsp_fsm = RSP_DATA_SC;
+
+                if( p_vci_ini_rw.rspval.read() )
+                {
+                    PRINTF("      * <RSP> have rsp - trdid : %x\n",(uint32_t)p_vci_ini_rw.rtrdid.read());
+
+                    r_vci_rsp_cpt = 0;
+
+                    if ((p_vci_ini_rw.rtrdid.read()>>(vci_param::T-1)) != 0 )
+                        r_vci_rsp_fsm = RSP_DATA_WRITE;
+                    else
+                    {
+                        switch (p_vci_ini_rw.rtrdid.read())
+                        {
+                        case TYPE_INS_MISS     : r_vci_rsp_fsm = RSP_INS_MISS;     break;
+                        case TYPE_INS_UNC      : r_vci_rsp_fsm = RSP_INS_UNC;      break;
+                        case TYPE_DATA_MISS    : r_vci_rsp_fsm = RSP_DATA_MISS;    break;
+                        case TYPE_DATA_UNC     : r_vci_rsp_fsm = RSP_DATA_UNC;     break;
+                        case TYPE_DATA_SC      : r_vci_rsp_fsm = RSP_DATA_SC;      break;
+                        default : 
+                            {
+                                ASSERT(false, "Unexpected response");
+                            }
+                        }
+                    }
+                }
                 break;
 
             case RSP_INS_MISS:
+
                 m_cost_imiss_transaction++;
-                if ( ! p_vci_ini_rw.rspval.read() )
-                    break;
-                assert( (r_vci_rsp_cpt < m_icache_words) &&
-                        "The VCI response packet for instruction miss is too long" );
-                r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
-                r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
-
-                if ( p_vci_ini_rw.reop.read() ) {
-                    assert( ((r_vci_rsp_cpt == m_icache_words - 1) ||
-                             p_vci_ini_rw.rerror.read() ||
-                             (r_vci_rsp_ins_error.read()&0x1))&&
-                            "The VCI response packet for instruction miss is too short");
-                    r_icache_miss_req = false;
+                PRINTF("      * <RSP> rspval/ack : %d - %d\n",(uint32_t)p_vci_ini_rw.rspval.read(), (uint32_t)r_vci_rsp_ack);
+
+                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                {
+                    PRINTF("      * <RSP> have rsp - r_vci_rsp_cpt : %d/%d\n",(uint32_t)r_vci_rsp_cpt.read(),(uint32_t)m_icache_words);
+                    PRINTF("      * <RSP> ins : %x\n",(int)p_vci_ini_rw.rdata.read());
+
+                    ASSERT( (r_vci_rsp_cpt < m_icache_words),
+                            "The VCI response packet for instruction miss is too long" );
+                    r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+                    CACHE_MISS_BUF_RSP_PUSH(i,r_vci_rsp_cpt,(data_t)p_vci_ini_rw.rdata.read());
+                    if ( p_vci_ini_rw.reop.read() ) 
+                    {
+                        PRINTF("      * <RSP> have reop\n");
+
+                        ASSERT( ((r_vci_rsp_cpt == m_icache_words - 1) or
+                                 p_vci_ini_rw.rerror.read() or
+                                 (r_vci_rsp_ins_error.read()&0x1)),
+                                "The VCI response packet for instruction miss is too short");
+                        r_vci_rsp_cpt    = 0;
+                        r_vci_rsp_fsm    = RSP_IDLE;
+
+                    }
+                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+                }
+                break;
+
+            case RSP_INS_UNC:
+
+                m_cost_imiss_transaction++;
+                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                {
+                    ASSERT(p_vci_ini_rw.reop.read(),
+                           "illegal VCI response packet for uncached instruction");
+
+                    CACHE_MISS_BUF_RSP_PUSH(i,0,(data_t)p_vci_ini_rw.rdata.read());
+
                     r_vci_rsp_fsm = RSP_IDLE;
-                }
-                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
-                break;
-
-            case RSP_INS_UNC:
-                m_cost_imiss_transaction++;
-                if ( ! p_vci_ini_rw.rspval.read() )
-                    break;
-                assert(p_vci_ini_rw.reop.read() &&
-                        "illegal VCI response packet for uncached instruction");
-                r_icache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
-                r_vci_rsp_fsm = RSP_IDLE;
-                r_icache_unc_req = false;
-                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+
+                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+                }
                 break;
 
             case RSP_DATA_MISS:
+
                 m_cost_dmiss_transaction++;
-                if ( ! p_vci_ini_rw.rspval.read() )
-                    break;
-                assert(r_vci_rsp_cpt != m_dcache_words &&
-                        "illegal VCI response packet for data read miss");
-                r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
-                r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
-                if ( p_vci_ini_rw.reop.read() ) {
-                    assert( ((r_vci_rsp_cpt == m_dcache_words - 1) 
-                             || (p_vci_ini_rw.rerror.read()&0x1)
-                             || r_vci_rsp_data_error.read()) &&
-                            "illegal VCI response packet for data read miss");
-                    r_dcache_miss_req = false;
+                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                {
+                    PRINTF("      * <RSP> have rspval - error : %d\n",(int)p_vci_ini_rw.rerror.read());
+
+                    ASSERT(r_vci_rsp_cpt < m_dcache_words,
+                           "illegal VCI response packet for data read miss");
+                    r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+
+                    CACHE_MISS_BUF_RSP_PUSH(d,r_vci_rsp_cpt,(data_t)p_vci_ini_rw.rdata.read());
+
+                    if ( p_vci_ini_rw.reop.read() ) {
+                        ASSERT( ((r_vci_rsp_cpt == m_dcache_words - 1) 
+                                 or (p_vci_ini_rw.rerror.read()&0x1)
+                                 or r_vci_rsp_data_error.read()),
+                                "illegal VCI response packet for data read miss");
+                        r_vci_rsp_cpt     = 0;
+                        r_vci_rsp_fsm     = RSP_IDLE;
+                    }
+                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                }
+                break;
+
+            case RSP_DATA_WRITE:
+
+                m_cost_write_transaction++;
+                if (p_vci_ini_rw.rspval.read())
+                {
+                    PRINTF("      * <RSP> have rspval - error : %d\n",(int)p_vci_ini_rw.rerror.read());
+
+                    ASSERT(p_vci_ini_rw.reop.read(),
+                           "A VCI response packet must contain one flit for a write transaction");
                     r_vci_rsp_fsm = RSP_IDLE;
-                }
-                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
-                break;
-
-            case RSP_DATA_WRITE:
-                m_cost_write_transaction++;
-                if ( ! p_vci_ini_rw.rspval.read() )
-                    break;
-                if ( p_vci_ini_rw.reop.read() ) {
-                    r_vci_rsp_fsm = RSP_IDLE;
-                    r_dcache_write_req = false;
-                }
-                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) m_iss.setWriteBerr();
+                    bool cached = r_wbuf.completed(p_vci_ini_rw.rtrdid.read() - (1<<(vci_param::T-1)) );
+
+                    PRINTF("      * <RSP> cached : %d\n",cached);
+
+                    if (not cached)
+                        r_dcache_previous_unc = false;
+
+                    if ((p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL) m_iss.setWriteBerr();
+                }
                 break;
 
             case RSP_DATA_UNC:
                 m_cost_unc_transaction++;
-                if ( ! p_vci_ini_rw.rspval.read() )
-                    break;
-                assert(p_vci_ini_rw.reop.read() &&
-                        "illegal VCI response packet for data read uncached");
-                r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
-                r_vci_rsp_fsm = RSP_IDLE;
-                r_dcache_unc_req = false;
-                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                {
+                    ASSERT(p_vci_ini_rw.reop.read(),
+                           "illegal VCI response packet for data read uncached");
+
+                    CACHE_MISS_BUF_RSP_PUSH(d,0,(data_t)p_vci_ini_rw.rdata.read());
+
+                    r_vci_rsp_fsm = RSP_IDLE;
+                    r_dcache_previous_unc = false;
+
+                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                }
                 break;
 
             case RSP_DATA_SC:
                 m_cost_unc_transaction++;
-                if ( ! p_vci_ini_rw.rspval.read() )
-                    break;
-                assert(p_vci_ini_rw.reop.read() &&
-                        "illegal VCI response packet for data SC");
-                r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
-                r_vci_rsp_fsm = RSP_IDLE;
-                r_dcache_sc_req = false;
-                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
-                break;
-
-            case RSP_INS_CLEANUP:
-            case RSP_DATA_CLEANUP:
-                if ( ! p_vci_ini_c.rspval.read() )
-                    break;
-                assert( p_vci_ini_c.reop.read() &&
-                        "illegal VCI response packet for icache cleanup");
-                assert( ((p_vci_ini_c.rerror.read()&0x1) == vci_param::ERR_NORMAL) &&
-                        "error in response packet for icache cleanup");
-                if ( r_vci_rsp_fsm == RSP_INS_CLEANUP ) r_icache_cleanup_req = false;
-                else                                    r_dcache_cleanup_req = false;
-                r_vci_rsp_fsm = RSP_IDLE;
+                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                {
+                    ASSERT(p_vci_ini_rw.reop.read(),
+                           "illegal VCI response packet for data SC");
+
+                    CACHE_MISS_BUF_RSP_PUSH(d,0,(data_t)p_vci_ini_rw.rdata.read());
+
+                    r_vci_rsp_fsm = RSP_IDLE;
+                    r_dcache_previous_unc = false;
+
+                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                }
                 break;
 
@@ -1678,8 +2495,73 @@
     //////////////////////////////////////////////////////////////////////////////////
     {
+
         // VCI initiator response
-
-        p_vci_ini_rw.rspack = true;
-        p_vci_ini_c.rspack = true;
+        switch ( r_cleanup_fsm.read() ) {
+
+            case CLEANUP_IDLE:
+                p_vci_ini_c.rspack  = false;
+                p_vci_ini_c.cmdval  = r_icache_cleanup_req || r_dcache_cleanup_req;
+                if ( r_dcache_cleanup_req )
+                {
+                    p_vci_ini_c.address =  r_dcache_cleanup_line.read() * (m_dcache_words << 2);
+                    p_vci_ini_c.trdid   = TYPE_DATA_CLEANUP;
+                }
+                else
+                {
+                    p_vci_ini_c.address =  r_icache_cleanup_line.read() * (m_icache_words << 2); 
+                    p_vci_ini_c.trdid   = TYPE_INS_CLEANUP;
+                }
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0xF;
+                p_vci_ini_c.plen   = 4;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = m_srcid_c;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop    = true;
+                break;
+
+           case CLEANUP_DCACHE:
+                p_vci_ini_c.rspack  = true;
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.trdid  = 0; 
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+                break;
+
+           case CLEANUP_ICACHE:
+                p_vci_ini_c.rspack  = true;
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.trdid  = 0; 
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+                break;
+           } // end switch r_cleanup_fsm
 
         // VCI initiator command
@@ -1704,20 +2586,4 @@
                 p_vci_ini_rw.eop     = false;
 
-                p_vci_ini_c.cmdval  = false;
-                p_vci_ini_c.address = 0;
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0;
-                p_vci_ini_c.plen   = 0;
-                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
-                p_vci_ini_c.trdid  = 0;
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = 0;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop = false;
-
                 break;
 
@@ -1737,8 +2603,8 @@
                         break;
                     default:
-                        assert("this should not happen");
+                        ASSERT(false,"this should not happen");
                 }
                 p_vci_ini_rw.plen = 4;
-                p_vci_ini_rw.trdid  = 0;   // data cache uncached read
+                p_vci_ini_rw.trdid  = TYPE_DATA_UNC;   // data cache uncached read
                 p_vci_ini_rw.pktid  = 0;
                 p_vci_ini_rw.srcid  = m_srcid_rw;
@@ -1750,20 +2616,4 @@
                 p_vci_ini_rw.eop    = true;
 
-                p_vci_ini_c.cmdval  = false;
-                p_vci_ini_c.address = 0;
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0;
-                p_vci_ini_c.plen   = 0;
-                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
-                p_vci_ini_c.trdid  = 0;
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = 0;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop = false;
-
                 break;
 
@@ -1772,5 +2622,5 @@
                 p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
                 if(r_vci_cmd_max.read() == 3){
-                    assert(false && "Not handled yet");
+                    ASSERT(false, "Not handled yet");
                 } else { // r_vci_cmd_cpt == 1
                     switch(r_vci_cmd_cpt.read()){
@@ -1786,5 +2636,5 @@
                 p_vci_ini_rw.cmd    = vci_param::CMD_STORE_COND;
                 p_vci_ini_rw.plen   = 4*(r_vci_cmd_max.read()+1);
-                p_vci_ini_rw.trdid  = 0;   // data cache uncached read
+                p_vci_ini_rw.trdid  = TYPE_DATA_SC;   // data cache uncached read
                 p_vci_ini_rw.pktid  = 0;
                 p_vci_ini_rw.srcid  = m_srcid_rw;
@@ -1796,20 +2646,4 @@
                 p_vci_ini_rw.eop    = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
 
-                p_vci_ini_c.cmdval  = false;
-                p_vci_ini_c.address = 0;
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0;
-                p_vci_ini_c.plen   = 0;
-                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
-                p_vci_ini_c.trdid  = 0;
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = 0;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop = false;
-
                 break;
 
@@ -1821,5 +2655,5 @@
                 p_vci_ini_rw.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
                 p_vci_ini_rw.cmd     = vci_param::CMD_WRITE;
-                p_vci_ini_rw.trdid   = 0;  // data cache write
+                p_vci_ini_rw.trdid   = r_wbuf.getIndex() + (1<<(vci_param::T-1));
                 p_vci_ini_rw.pktid   = 0;
                 p_vci_ini_rw.srcid   = m_srcid_rw;
@@ -1831,20 +2665,4 @@
                 p_vci_ini_rw.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
 
-                p_vci_ini_c.cmdval  = false;
-                p_vci_ini_c.address = 0;
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0;
-                p_vci_ini_c.plen   = 0;
-                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
-                p_vci_ini_c.trdid  = 0;
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = 0;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop = false;
-
                 break;
 
@@ -1855,5 +2673,5 @@
                 p_vci_ini_rw.plen   = m_dcache_words << 2;
                 p_vci_ini_rw.cmd    = vci_param::CMD_READ;
-                p_vci_ini_rw.trdid  = 1;   // data cache cached read
+                p_vci_ini_rw.trdid  = TYPE_DATA_MISS;   // data cache cached read
                 p_vci_ini_rw.pktid  = 0;
                 p_vci_ini_rw.srcid  = m_srcid_rw;
@@ -1865,20 +2683,4 @@
                 p_vci_ini_rw.eop = true;
 
-                p_vci_ini_c.cmdval  = false;
-                p_vci_ini_c.address = 0;
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0;
-                p_vci_ini_c.plen   = 0;
-                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
-                p_vci_ini_c.trdid  = 0;
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = 0;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop = false;
-
                 break;
 
@@ -1889,5 +2691,5 @@
                 p_vci_ini_rw.plen   = m_icache_words << 2;
                 p_vci_ini_rw.cmd    = vci_param::CMD_READ;
-                p_vci_ini_rw.trdid  = 3;   // ins cache cached read
+                p_vci_ini_rw.trdid  = TYPE_INS_MISS;   // ins cache cached read
                 p_vci_ini_rw.pktid  = 0;
                 p_vci_ini_rw.srcid  = m_srcid_rw;
@@ -1899,20 +2701,4 @@
                 p_vci_ini_rw.eop = true;
 
-                p_vci_ini_c.cmdval  = false;
-                p_vci_ini_c.address = 0;
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0;
-                p_vci_ini_c.plen   = 0;
-                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
-                p_vci_ini_c.trdid  = 0;
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = 0;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop = false;
-
                 break;
 
@@ -1923,5 +2709,5 @@
                 p_vci_ini_rw.plen   = 4;
                 p_vci_ini_rw.cmd    = vci_param::CMD_READ;
-                p_vci_ini_rw.trdid  = 2;   // ins cache uncached read
+                p_vci_ini_rw.trdid  = TYPE_INS_UNC;   // ins cache uncached read
                 p_vci_ini_rw.pktid  = 0;
                 p_vci_ini_rw.srcid  = m_srcid_rw;
@@ -1933,96 +2719,23 @@
                 p_vci_ini_rw.eop = true;
 
-                p_vci_ini_c.cmdval  = false;
-                p_vci_ini_c.address = 0;
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0;
-                p_vci_ini_c.plen   = 0;
-                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
-                p_vci_ini_c.trdid  = 0;
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = 0;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop = false;
-
-
-                break;
-
-            case CMD_INS_CLEANUP:
-                p_vci_ini_rw.cmdval = false;
-                p_vci_ini_rw.address = 0;
-                p_vci_ini_rw.wdata  = 0;
-                p_vci_ini_rw.be     = 0;
-                p_vci_ini_rw.plen   = 0;
-                p_vci_ini_rw.cmd    = vci_param::CMD_NOP;
-                p_vci_ini_rw.trdid  = 0;
-                p_vci_ini_rw.pktid  = 0;
-                p_vci_ini_rw.srcid  = 0;
-                p_vci_ini_rw.cons   = false;
-                p_vci_ini_rw.wrap   = false;
-                p_vci_ini_rw.contig = false;
-                p_vci_ini_rw.clen   = 0;
-                p_vci_ini_rw.cfixed = false;
-                p_vci_ini_rw.eop    = false;
-
-                p_vci_ini_c.cmdval  = true;
-                p_vci_ini_c.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0;
-                p_vci_ini_c.plen   = 4;
-                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
-                p_vci_ini_c.trdid  = 1; // cleanup instruction
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = m_srcid_c;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop = true;
-
-                break;
-
-
-            case CMD_DATA_CLEANUP:
-                p_vci_ini_rw.cmdval = false;
-                p_vci_ini_rw.address = 0;
-                p_vci_ini_rw.wdata  = 0;
-                p_vci_ini_rw.be     = 0;
-                p_vci_ini_rw.plen   = 0;
-                p_vci_ini_rw.cmd    = vci_param::CMD_NOP;
-                p_vci_ini_rw.trdid  = 0;
-                p_vci_ini_rw.pktid  = 0;
-                p_vci_ini_rw.srcid  = 0;
-                p_vci_ini_rw.cons   = false;
-                p_vci_ini_rw.wrap   = false;
-                p_vci_ini_rw.contig = false;
-                p_vci_ini_rw.clen   = 0;
-                p_vci_ini_rw.cfixed = false;
-                p_vci_ini_rw.eop    = false;
-
-                p_vci_ini_c.cmdval  = true;
-                p_vci_ini_c.address = r_dcache_cleanup_line.read() * (m_dcache_words<<2);
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0;
-                p_vci_ini_c.plen   = 4;
-                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
-                p_vci_ini_c.trdid  = 0; // cleanup data
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = m_srcid_c;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop = true;
-
                 break;
 
         } // end switch r_vci_cmd_fsm
 
+        bool ack;
+
+        switch (r_vci_rsp_fsm.read() ) {
+        case RSP_IDLE       : ack = false; break;
+        case RSP_DATA_WRITE : ack = true; break;
+        case RSP_INS_MISS   :
+        case RSP_INS_UNC    : ack = CACHE_MISS_BUF_RSP_ACK(i); break;
+        case RSP_DATA_MISS  :
+        case RSP_DATA_UNC   :
+        case RSP_DATA_SC    : ack = CACHE_MISS_BUF_RSP_ACK(d); break;
+        } // end switch r_vci_cmd_fsm
+
+        r_vci_rsp_ack       = ack;
+        p_vci_ini_rw.rspack = ack;
+        
         // VCI_TGT
 
@@ -2038,5 +2751,5 @@
             case TGT_RSP_BROADCAST:
                 p_vci_tgt.cmdack  = false;
-                p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
+                p_vci_tgt.rspval  = not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() and ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
                 p_vci_tgt.rsrcid  = r_tgt_srcid.read();
                 p_vci_tgt.rpktid  = r_tgt_pktid.read();
@@ -2049,5 +2762,5 @@
             case TGT_RSP_ICACHE:
                 p_vci_tgt.cmdack  = false;
-                p_vci_tgt.rspval  = !r_tgt_icache_req.read() && r_tgt_icache_rsp.read();
+                p_vci_tgt.rspval  = not r_tgt_icache_req.read() and r_tgt_icache_rsp.read();
                 p_vci_tgt.rsrcid  = r_tgt_srcid.read();
                 p_vci_tgt.rpktid  = r_tgt_pktid.read();
@@ -2060,5 +2773,5 @@
             case TGT_RSP_DCACHE:
                 p_vci_tgt.cmdack  = false;
-                p_vci_tgt.rspval  = !r_tgt_dcache_req.read() && r_tgt_dcache_rsp.read();
+                p_vci_tgt.rspval  = not r_tgt_dcache_req.read() and r_tgt_dcache_rsp.read();
                 p_vci_tgt.rsrcid  = r_tgt_srcid.read();
                 p_vci_tgt.rpktid  = r_tgt_pktid.read();
@@ -2079,4 +2792,26 @@
     } // end genMoore()
 
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(void)::stop_simulation (uint32_t nb_frz_cycles)
+    //////////////////////////////////////////////////////////////////////////////////
+    {
+#if CC_XCACHE_WRAPPER_STOP_SIMULATION
+        if (nb_frz_cycles == 0)
+            {
+                PRINTF("CC_XCACHE_WRAPPER \"%s\" : don't stop the simulation.\n",name().c_str());
+                m_stop_simulation = false;
+            }
+        else
+            {
+                PRINTF("CC_XCACHE_WRAPPER \"%s\" : stop the simulation after %d cycles.\n",name().c_str(),nb_frz_cycles);
+                m_stop_simulation = true;
+                m_stop_simulation_nb_frz_cycles_max = nb_frz_cycles;
+            }
+#else
+        std::cout << "CC_XCACHE_WRAPPER \"" << name() << "\" : flag CC_XCACHE_WRAPPER_STOP_SIMULATION is unset, you can't use stop_simulation." << std::endl;
+#endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
+        
+    }
+
 }} // end namespace
 
@@ -2089,6 +2824,2 @@
 
 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
-
-
-
-
Index: trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp	(revision 132)
+++ trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp	(revision 134)
@@ -33,7 +33,14 @@
 //#define DDEBUG // Directory debug
 //#define LOCK_DEBUG // Lock debug
-//#define DEBUG_VCI_MEM_CACHE 1
-#define DEBUG_START_CYCLE 8750000
+#define DEBUG_VCI_MEM_CACHE 0
+#define DEBUG_START_CYCLE   200000
 #define RANDOMIZE_SC
+
+#if DEBUG_VCI_MEM_CACHE
+# define PRINTF(msg...) do { if (m_cpt_cycles > DEBUG_START_CYCLE) printf(msg); } while (0); 
+#else
+# define PRINTF(msg...)
+#endif
+
 namespace soclib { namespace caba {
 
@@ -641,4 +648,7 @@
         {
           if ( p_vci_tgt.cmdval ) {
+
+              PRINTF("  * <TGT> Request from %d at address %llx\n",(uint32_t)p_vci_tgt.srcid.read(),(uint64_t)p_vci_tgt.address.read());
+
             assert( (p_vci_tgt.srcid.read() < m_initiators) && 
             "VCI_MEM_CACHE error in direct request : received SRCID is larger than the number of initiators");
@@ -653,5 +663,4 @@
               }
             }
-
 
             if ( !reached ) 
@@ -666,5 +675,6 @@
               r_tgt_cmd_fsm = TGT_CMD_READ;
             } 
-            else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ) && ( p_vci_tgt.trdid.read() == 0x0 ))
+            // else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ) && ( p_vci_tgt.trdid.read() == 0x0 ))
+            else if ( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE )
             {  
               r_tgt_cmd_fsm = TGT_CMD_WRITE;
@@ -838,4 +848,6 @@
     ////////////////////////////////////////////////////////////////////////////////////
 
+    PRINTF("  * TOP : Request from %d at address %llx\n",(uint32_t)m_cmd_read_srcid_fifo.read(),(uint64_t)m_cmd_read_addr_fifo.read());
+
     switch ( r_read_fsm.read() ) {
 
@@ -844,4 +856,6 @@
         {
           if (m_cmd_read_addr_fifo.rok()) {
+            PRINTF("  * <READ> Request from %d at address %llx\n",(uint32_t)m_cmd_read_srcid_fifo.read(),(uint64_t)m_cmd_read_addr_fifo.read());
+
             m_cpt_read++;
             r_read_fsm = READ_DIR_LOCK;
@@ -2591,5 +2605,5 @@
             hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
             if(!hit_inval) {
-#ifdef DEBUG_VCI_MEM_CACHE
+#if DEBUG_VCI_MEM_CACHE
 if(m_cpt_cycles > DEBUG_START_CYCLE)
               std::cout << "MEM_CACHE WARNING: cleanup with no corresponding entry at address : " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::dec << std::endl;
