Index: /trunk/modules/vci_cc_xcache_wrapper_v4_cmp/caba/metadata/vci_cc_xcache_wrapper_v4_cmp.sd
===================================================================
--- /trunk/modules/vci_cc_xcache_wrapper_v4_cmp/caba/metadata/vci_cc_xcache_wrapper_v4_cmp.sd	(revision 152)
+++ /trunk/modules/vci_cc_xcache_wrapper_v4_cmp/caba/metadata/vci_cc_xcache_wrapper_v4_cmp.sd	(revision 152)
@@ -0,0 +1,62 @@
+
+# -*- python -*-
+
+__id__ = "$Id: vci_cc_xcache_wrapper_v4_cmp.sd 134 2011-01-24 16:36:50Z kane $"
+__version__ = "$Revision: 134 $"
+
+Module('caba:vci_cc_xcache_wrapper_v4_cmp',
+	classname = 'soclib::caba::VciCcXCacheWrapperV4_CMP',
+	tmpl_parameters = [
+		parameter.Module('vci_param', default = 'caba:vci_param'),
+		parameter.Module('iss_t'),
+		],
+	header_files = [
+		'../source/include/vci_cc_xcache_wrapper_v4_cmp.h',
+		],
+	implementation_files = [
+		'../source/src/vci_cc_xcache_wrapper_v4_cmp.cpp',
+		],
+	uses = [
+		Uses('caba:base_module'),
+		Uses('common:mapping_table'),
+		Uses('common:iss2'),
+		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_target', 'p_vci_tgt'),
+		Port('caba:bit_in', 'p_irq', parameter.Constant('n_irq')),
+		Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+		Port('caba:clock_in', 'p_clk', auto = 'clock'),
+		],
+	instance_parameters = [
+		parameter.Int('proc_id'),
+		parameter.Module('mtp', 'common:mapping_table'),
+		parameter.Module('mtc', 'common:mapping_table'),
+		parameter.IntTab('initiator_rw_index'),
+		parameter.IntTab('initiator_c_index'),
+		parameter.IntTab('target_index'),
+		parameter.Int('icache_ways'),
+		parameter.Int('icache_sets'),
+		parameter.Int('icache_words'),
+		parameter.Int('dcache_ways'),
+		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',
+		],
+)
Index: /trunk/modules/vci_cc_xcache_wrapper_v4_cmp/caba/source/include/vci_cc_xcache_wrapper_v4_cmp.h
===================================================================
--- /trunk/modules/vci_cc_xcache_wrapper_v4_cmp/caba/source/include/vci_cc_xcache_wrapper_v4_cmp.h	(revision 152)
+++ /trunk/modules/vci_cc_xcache_wrapper_v4_cmp/caba/source/include/vci_cc_xcache_wrapper_v4_cmp.h	(revision 152)
@@ -0,0 +1,582 @@
+/* -*- c++ -*-
+ *
+ * SOCLIB_LGPL_HEADER_BEGIN
+ * 
+ * This file is part of SoCLib, GNU LGPLv2.1.
+ * 
+ * SoCLib is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 of the License.
+ * 
+ * SoCLib is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SoCLib; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ * 
+ * SOCLIB_LGPL_HEADER_END
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain
+ */
+ 
+#ifndef SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_V4_CMP_H
+#define SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_V4_CMP_H
+
+#include <inttypes.h>
+#include <fstream>
+#include <systemc>
+#include <queue>
+#include "caba_base_module.h"
+#include "multi_write_buffer.h"
+#include "generic_cache.h"
+#include "vci_initiator.h"
+#include "vci_target.h"
+#include "mapping_table.h"
+#include "static_assert.h"
+
+/*
+ * ----------------------------------------------------------
+ * Implementation
+ * ----------------------------------------------------------
+ *
+ * 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)
+ *    1     - nb_icache+nb_dcache simple fifo
+ *    2     - 2 simple fifo
+ *    else  - 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_VCI_CMD_PRIORITY
+ *   Write buffer access is conditionnal with dcache_miss_req and icache_miss_req
+ *     1    - one access with static priority (dcache prior)
+ *     2    - one access with static priority (icache prior)
+ *     3    - one access with round robin priority
+ *     4    - two access authorized
+ * 
+ * CC_XCACHE_WRAPPER_MULTI_CACHE
+ *     1    - icache static partitionnement
+ *     2    - icache dedicated
+ *
+ * CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS
+ *   (In multi-cache) 
+ *   A dcache used by a cpu and in miss_wait state can be use by
+ *   an another cpu to make a load cached access.
+ * 
+ * CC_XCACHE_WRAPPER_STORE_AFTER_STORE
+ *   Store access in dcache (and hit) is make in two cycle :
+ *    - first read directory and read data
+ *    - second make a mask with old data and write new data.
+ *   If data part has a write enable per byte, read data access can be suppress
+ *   and we can pipeline consecutive store access.
+ *
+ * ----------------------------------------------------------
+ * Debug
+ * ----------------------------------------------------------
+ *
+ * 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_FILE_TRANSACTION
+ *   Print transaction between :
+ *     - the cpu and the cache (icache and dcache)
+ *     - vci
+ *     - cleanup
+ *     - coherency
+ *
+ * MWBUF_VHDL_TESTBENCH
+ *   generate a vhdl testbench for multi write buffer
+ */
+
+// implementation
+#ifndef CC_XCACHE_WRAPPER_FIFO_RSP
+#define CC_XCACHE_WRAPPER_FIFO_RSP                    2
+#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_VCI_CMD_PRIORITY
+#define CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY            3
+#endif
+#ifndef CC_XCACHE_WRAPPER_MULTI_CACHE
+#define CC_XCACHE_WRAPPER_MULTI_CACHE                 2
+// if multi_cache : 
+// <tsar toplevel>/modules/vci_mem_cache_v4_cmp/caba/source/include/mem_cache_directory_v4_cmp.h : L1_MULTI_CACHE 1
+// <soclib toplevel>/soclib/lib/multi_write_buffer/include/multi_write_buffer.h          : CC_XCACHE_MULTI_CACHE 1
+#endif
+#ifndef CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS
+#define CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS  1
+#endif
+#ifndef CC_XCACHE_WRAPPER_STORE_AFTER_STORE
+#define CC_XCACHE_WRAPPER_STORE_AFTER_STORE           1
+#endif
+  
+// debug
+#ifndef CC_XCACHE_WRAPPER_VERBOSE
+#define CC_XCACHE_WRAPPER_VERBOSE                     0
+#endif
+#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             0
+#endif
+#ifndef CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+#define CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION      0
+#define CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH "log"
+#endif
+#ifndef MWBUF_VHDL_TESTBENCH
+#define MWBUF_VHDL_TESTBENCH                          0
+#endif
+
+// don't change
+#if not CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+#undef  CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
+#define CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT   0
+#endif
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+////////////////////////////////////////////
+template<typename vci_param, typename iss_t>
+class VciCcXCacheWrapperV4_CMP
+///////////////////////////////////////////
+    : public soclib::caba::BaseModule
+{
+    typedef uint64_t            vhdl_tb_t;
+    typedef sc_dt::sc_uint<40> 	addr_40;
+    typedef sc_dt::sc_uint<64>  data_64;
+    typedef uint32_t    	data_t;
+    typedef uint32_t    	tag_t;
+    typedef uint32_t    	be_t;
+    typedef typename vci_param::fast_addr_t vci_addr_t;
+    typedef  enum
+        {
+            WRITE_THROUGH,
+            RELEASE_WRITE_THROUGH
+        } write_policy_t;
+    
+    enum dcache_fsm_state_e {
+        DCACHE_IDLE,
+        DCACHE_WRITE_UPDT,
+        DCACHE_MISS_VICTIM,
+        DCACHE_MISS_WAIT,
+        DCACHE_MISS_UPDT,
+        DCACHE_UNC_WAIT,
+        DCACHE_SC_WAIT,
+        DCACHE_INVAL,
+        DCACHE_SYNC,
+        DCACHE_ERROR,
+        DCACHE_CC_CHECK,
+        DCACHE_CC_INVAL,
+        DCACHE_CC_UPDT,
+        DCACHE_CC_CLEANUP,
+    };
+
+    enum icache_fsm_state_e {
+        ICACHE_IDLE,
+        ICACHE_MISS_VICTIM,
+        ICACHE_MISS_WAIT,
+        ICACHE_MISS_UPDT,
+        ICACHE_UNC_WAIT,
+        ICACHE_ERROR,
+        ICACHE_CC_CLEANUP, 
+        ICACHE_CC_CHECK,
+        ICACHE_CC_INVAL,
+        ICACHE_CC_UPDT,
+    };
+
+    enum cmd_fsm_state_e {
+        CMD_IDLE,
+        CMD_INS_MISS,
+        CMD_INS_UNC,
+        CMD_DATA_MISS,
+        CMD_DATA_UNC,
+        CMD_DATA_WRITE,
+        CMD_DATA_SC,
+    };
+
+    enum rsp_fsm_state_e {
+        RSP_IDLE,
+        RSP_INS_MISS,
+        RSP_INS_UNC,
+        RSP_DATA_MISS,
+        RSP_DATA_UNC,
+        RSP_DATA_WRITE,
+        RSP_DATA_SC,
+    };
+
+    enum tgt_fsm_state_e {
+        TGT_IDLE,
+        TGT_UPDT_WORD,
+        TGT_UPDT_DATA,
+        TGT_REQ_BROADCAST,
+        TGT_REQ_ICACHE,
+        TGT_REQ_DCACHE,
+        TGT_RSP_BROADCAST,
+        TGT_RSP_ICACHE,
+        TGT_RSP_DCACHE,
+    };
+
+    enum cleanup_fsm_state_e {
+        CLEANUP_IDLE,
+        CLEANUP_REQ,
+        CLEANUP_RSP_DCACHE,
+        CLEANUP_RSP_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:
+
+    // PORTS
+    sc_in<bool>                             p_clk;
+    sc_in<bool>                             p_resetn;
+    sc_in<bool>                          ** p_irq;//[m_nb_cpu][iss_t::n_irq];
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_rw;
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_c;
+    soclib::caba::VciTarget<vci_param>      p_vci_tgt;
+
+private:
+
+    // STRUCTURAL PARAMETERS
+    const soclib::common::AddressDecodingTable<vci_addr_t, bool>    m_cacheability_table;
+    const soclib::common::Segment                                   m_segment;
+    iss_t            ** m_iss; //[m_nb_cpu]
+    const uint32_t      m_srcid_rw;   
+    const uint32_t      m_srcid_c;   
+    
+    const size_t         m_nb_cpu;
+    const size_t         m_nb_icache;
+    const size_t         m_nb_dcache;
+    const size_t         m_nb_cache;
+    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 write_policy_t m_write_policy;
+    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; //[m_nb_cpu]
+#endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
+
+    // REGISTERS
+    sc_signal<uint32_t>     r_cpu_prior;
+    sc_signal<uint32_t>   * r_icache_lock;//[m_nb_icache]
+    sc_signal<uint32_t>   * r_dcache_lock;//[m_nb_dcache]
+    sc_signal<bool>       * r_dcache_sync;//[m_nb_dcache]
+
+    sc_signal<int>        * r_dcache_fsm;          //[m_nb_dcache]
+    sc_signal<int>        * r_dcache_fsm_save;     //[m_nb_dcache]
+    sc_signal<addr_40>    * r_dcache_addr_save;    //[m_nb_dcache]
+    sc_signal<data_t>     * r_dcache_wdata_save;   //[m_nb_dcache]
+    sc_signal<data_t>     * r_dcache_rdata_save;   //[m_nb_dcache]
+    sc_signal<int>        * r_dcache_type_save;    //[m_nb_dcache]
+    sc_signal<be_t>       * r_dcache_be_save;      //[m_nb_dcache]
+    sc_signal<bool>       * r_dcache_cached_save;  //[m_nb_dcache]
+    sc_signal<uint32_t>   * r_dcache_num_cpu_save; //[m_nb_dcache]
+    sc_signal<bool>       * r_dcache_cleanup_req;  //[m_nb_dcache]
+    sc_signal<addr_40>    * r_dcache_cleanup_line; //[m_nb_dcache]
+    sc_signal<bool>       * r_dcache_miss_req;     //[m_nb_dcache]
+    sc_signal<size_t>     * r_dcache_miss_way;     //[m_nb_dcache]
+    sc_signal<size_t>     * r_dcache_miss_set;     //[m_nb_dcache]
+    sc_signal<bool>       * r_dcache_unc_req;      //[m_nb_dcache]
+    sc_signal<bool>       * r_dcache_sc_req;       //[m_nb_dcache]
+    sc_signal<bool>       * r_dcache_inval_rsp;    //[m_nb_dcache]
+    sc_signal<size_t>     * r_dcache_update_addr;  //[m_nb_dcache]
+    sc_signal<data_64>   ** r_dcache_ll_data;      //[m_nb_dcache][m_nb_cpu]
+    sc_signal<addr_40>   ** r_dcache_ll_addr;      //[m_nb_dcache][m_nb_cpu]
+    sc_signal<bool>      ** r_dcache_ll_valid;     //[m_nb_dcache][m_nb_cpu]
+    sc_signal<bool>       * r_dcache_previous_unc; //[m_nb_dcache]
+                                                   
+    sc_signal<int>        * r_icache_fsm;          //[m_nb_icache]
+    sc_signal<int>        * r_icache_fsm_save;     //[m_nb_icache]
+    sc_signal<addr_40>    * r_icache_addr_save;    //[m_nb_icache]
+    sc_signal<bool>       * r_icache_miss_req;     //[m_nb_icache]
+    sc_signal<size_t>     * r_icache_miss_way;     //[m_nb_icache]
+    sc_signal<size_t>     * r_icache_miss_set;     //[m_nb_icache]
+    sc_signal<bool>       * r_icache_unc_req;      //[m_nb_icache]
+    sc_signal<bool>       * r_icache_cleanup_req;  //[m_nb_icache]
+    sc_signal<addr_40>    * r_icache_cleanup_line; //[m_nb_icache]
+    sc_signal<bool>       * r_icache_inval_rsp;    //[m_nb_icache]
+    sc_signal<size_t>     * r_icache_update_addr;  //[m_nb_icache]
+    sc_signal<bool>       * r_icache_buf_unc_valid;//[m_nb_icache]
+
+    sc_signal<int>          r_vci_cmd_fsm;
+    sc_signal<size_t>       r_vci_cmd_min;       
+    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<uint32_t>     r_vci_cmd_num_cache;
+
+    sc_signal<int>          r_vci_rsp_fsm;
+    sc_signal<size_t>       r_vci_rsp_cpt;  
+              bool          s_vci_rsp_ack;
+    sc_signal<uint32_t>     r_vci_rsp_num_cache;
+    sc_signal<bool>       * r_vci_rsp_ins_error;  //[m_nb_icache]
+    sc_signal<bool>       * r_vci_rsp_data_error; //[m_nb_dcache]
+
+#if   (CC_XCACHE_WRAPPER_FIFO_RSP==1)
+    std::queue<data_t>    * r_icache_miss_buf;    //[m_nb_icache]
+    std::queue<data_t>    * r_dcache_miss_buf;    //[m_nb_dcache]
+#elif (CC_XCACHE_WRAPPER_FIFO_RSP==2)
+    typedef struct 
+    {
+        data_t   data;
+        uint32_t num_cache;
+    } miss_buf_t;
+
+    std::queue<miss_buf_t>  r_icache_miss_buf;
+    std::queue<miss_buf_t>  r_dcache_miss_buf;
+#else
+    bool                 ** r_icache_miss_val;    //[m_nb_icache][m_icache_words]
+    data_t               ** r_icache_miss_buf;    //[m_nb_icache][m_icache_words]
+    bool                 ** r_dcache_miss_val;    //[m_nb_dcache][m_dcache_words]
+    data_t               ** r_dcache_miss_buf;    //[m_nb_dcache][m_dcache_words]
+#endif
+    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;
+    sc_signal<addr_40>      r_tgt_iaddr;
+    sc_signal<addr_40>      r_tgt_daddr;
+    sc_signal<size_t>       r_tgt_word;
+    sc_signal<bool>         r_tgt_update;
+    sc_signal<bool>         r_tgt_update_data;
+  //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<uint32_t>     r_tgt_num_cache;
+    sc_signal<bool>       * r_tgt_icache_req; //[m_nb_icache]
+    sc_signal<bool>       * r_tgt_icache_rsp; //[m_nb_icache]
+    sc_signal<bool>       * r_tgt_dcache_req; //[m_nb_dcache]
+    sc_signal<bool>       * r_tgt_dcache_rsp; //[m_nb_dcache]
+
+    sc_signal<int>          r_cleanup_fsm;		// controls initiator port of the coherence network
+    sc_signal<uint32_t>     r_cleanup_num_cache;
+    sc_signal<bool>         r_cleanup_icache;
+
+    MultiWriteBuffer<addr_40>** r_wbuf;
+    GenericCache<vci_addr_t> ** r_icache;
+    GenericCache<vci_addr_t> ** r_dcache;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+    bool                        generate_log_transaction_file_icache;
+    bool                        generate_log_transaction_file_dcache;
+    bool                        generate_log_transaction_file_cmd;
+    bool                        generate_log_transaction_file_tgt;
+    bool                        generate_log_transaction_file_cleanup;
+
+    std::ofstream             * log_transaction_file_icache; //[m_nb_cpu]
+    std::ofstream             * log_transaction_file_dcache; //[m_nb_cpu]
+    std::ofstream               log_transaction_file_cmd;
+    std::ofstream               log_transaction_file_tgt;
+    std::ofstream               log_transaction_file_cleanup;
+#endif
+
+#if MWBUF_VHDL_TESTBENCH
+    bool                        simulation_started;
+    bool                        generate_vhdl_testbench_mwbuf;
+    std::ofstream             * vhdl_testbench_mwbuf; //[m_nb_dcache]
+#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_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
+
+    uint32_t * m_cpt_icache_access; //[m_nb_icache]
+    uint32_t * m_cpt_dcache_access; //[m_nb_dcache]
+    uint32_t * m_cpt_dcache_hit_after_miss_read;  //[m_nb_dcache]
+    uint32_t * m_cpt_dcache_hit_after_miss_write; //[m_nb_dcache]
+    uint32_t * m_cpt_dcache_store_after_store; //[m_nb_dcache]
+    uint32_t * m_cpt_icache_miss_victim_wait; //[m_nb_icache]
+    uint32_t * m_cpt_dcache_miss_victim_wait; //[m_nb_dcache]
+
+    uint32_t ** m_cpt_fsm_dcache;  //[m_nb_dcache]
+    uint32_t ** m_cpt_fsm_icache;  //[m_nb_icache]
+    uint32_t  * m_cpt_fsm_cmd;
+    uint32_t  * m_cpt_fsm_rsp;
+    uint32_t  * m_cpt_fsm_tgt;
+    uint32_t  * m_cpt_fsm_cleanup;
+
+    // Non blocking multi-cache
+    typename iss_t::InstructionRequest  * ireq        ; //[m_nb_icache]
+    typename iss_t::InstructionResponse * irsp        ; //[m_nb_icache]
+    bool                                * ireq_cached ; //[m_nb_icache]
+    uint32_t                            * ireq_num_cpu; //[m_nb_dcache]
+    typename iss_t::DataRequest         * dreq        ; //[m_nb_dcache]
+    typename iss_t::DataResponse        * drsp        ; //[m_nb_dcache]
+    bool                                * dreq_cached ; //[m_nb_dcache]
+    uint32_t                            * dreq_num_cpu; //[m_nb_dcache]
+
+    const uint32_t m_num_cache_LSB;
+    const uint32_t m_num_cache_MSB;
+          addr_40  m_num_cache_LSB_mask;
+          addr_40  m_num_cache_mask;
+
+protected:
+    SC_HAS_PROCESS(VciCcXCacheWrapperV4_CMP);
+
+public:
+
+    VciCcXCacheWrapperV4_CMP(
+                       sc_module_name insname,
+                       int proc_id,
+                       const soclib::common::MappingTable &mtp,
+                       const soclib::common::MappingTable &mtc,
+                       const soclib::common::IntTab &initiator_index_rw,
+                       const soclib::common::IntTab &initiator_index_c,
+                       const soclib::common::IntTab &target_index,
+                       size_t nb_cpu,
+                       size_t nb_dcache,
+                       size_t icache_ways,
+                       size_t icache_sets,
+                       size_t icache_words,
+                       size_t dcache_ways,
+                       size_t dcache_sets,
+                       size_t dcache_words,
+                       size_t wbuf_nwords,
+                       size_t wbuf_nlines,
+                       size_t wbuf_timeout,
+                       write_policy_t write_policy=WRITE_THROUGH
+                         );
+
+    ~VciCcXCacheWrapperV4_CMP();
+
+  void print_trace(size_t mode = 0);
+  void print_cpi();
+  void print_stats(bool print_wbuf=true, bool print_fsm=true);
+
+  void stop_simulation (uint32_t);
+  void log_transaction ( bool generate_file_icache
+                        ,bool generate_file_dcache
+                        ,bool generate_file_cmd
+                        ,bool generate_file_tgt
+                        ,bool generate_file_cleanup);
+
+  void vhdl_testbench (bool generate_file_mwbuf);
+
+private:
+
+    void transition();
+    void genMoore();
+
+    uint32_t get_num_cache     (addr_40 & addr);
+    uint32_t get_num_cache_only(addr_40   addr);
+    void     set_num_cache     (addr_40 & addr, uint32_t num_cache);
+    addr_40  set_num_cache_only(addr_40   addr, uint32_t num_cache);
+
+    soclib_static_assert((int)iss_t::SC_ATOMIC     == (int)vci_param::STORE_COND_ATOMIC);
+    soclib_static_assert((int)iss_t::SC_NOT_ATOMIC == (int)vci_param::STORE_COND_NOT_ATOMIC);
+};
+
+}}
+
+#endif /* SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_V4_CMP_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Index: /trunk/modules/vci_cc_xcache_wrapper_v4_cmp/caba/source/src/vci_cc_xcache_wrapper_v4_cmp.cpp
===================================================================
--- /trunk/modules/vci_cc_xcache_wrapper_v4_cmp/caba/source/src/vci_cc_xcache_wrapper_v4_cmp.cpp	(revision 152)
+++ /trunk/modules/vci_cc_xcache_wrapper_v4_cmp/caba/source/src/vci_cc_xcache_wrapper_v4_cmp.cpp	(revision 152)
@@ -0,0 +1,4763 @@
+// FIXME : data_64 ?
+
+/* -*- c++ -*-
+ *
+ * SOCLIB_LGPL_HEADER_BEGIN
+ * 
+ * This file is part of SoCLib, GNU LGPLv2.1.
+ * 
+ * SoCLib is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 of the License.
+ * 
+ * SoCLib is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SoCLib; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ * 
+ * SOCLIB_LGPL_HEADER_END
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu nipo
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+// History
+// - 25/04/2008
+//   The existing vci_xcache component has been extended to include 
+//   a VCI target port to support a directory based coherence protocol.
+//   Two types of packets can be send by the L2 cache to the L1 cache
+//   * INVALIDATE packets : length = 1
+//   * UPDATE packets : length = n + 2   
+//   The CLEANUP packets are sent by the L1 cache to the L2 cache, 
+//   to signal a replaced cache line.
+// - 12/08/2008
+//   The vci_cc_xcache_wrapper component instanciates directly the processsor 
+//   iss, in order to supress the processor/cache interface.
+//   According to the VCI advanced specification, this component uses one 
+//   word VCI CMD packets for MISS transactions, and accept one word VCI RSP
+//   packets for Write burst  transactions.
+//   The write buffer has been modified to use the WriteBuffer object. 
+//   A VCI write burst is constructed when two conditions are satisfied :
+//   The processor make strictly successive write requests, and they are
+//   in the same cache line. The write buffer performs re-ordering, to
+//   respect the contiguous addresses VCI constraint. In case of several
+//   WRITE_WORD requests in the same word, only the last request is conserved.
+//   In case of several WRITE_HALF or WRITE_WORD requests in the same word,
+//   the requests are merged in the same word. In case of uncached write
+//   requests, each request is transmited as a single VCI transaction.
+//   Both the data & instruction caches can be flushed in one single cycle.
+///////////////////////////////////////////////////////////////////////////////
+
+#include <iomanip>
+#include "arithmetics.h"
+#include "size.h"
+#include "../include/vci_cc_xcache_wrapper_v4_cmp.h"
+
+// =====[ DEBUG ]====================================
+
+#define ASSERT_VERBOSE
+#define ASSERT_NCYCLES m_cpt_total_cycles
+
+#include "debug.h"
+
+#if CC_XCACHE_WRAPPER_DEBUG
+# define PRINTF(msg...) PRINTF_COND(m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN,msg)
+#else
+# define PRINTF(msg...)
+#endif
+
+// =====[ FIFO_RSP ]=================================
+
+#if   (CC_XCACHE_WRAPPER_FIFO_RSP==1)
+# define CACHE_MISS_BUF_ALLOC             do {                  \
+    r_icache_miss_buf = new std::queue<data_t> [m_nb_icache];   \
+    r_dcache_miss_buf = new std::queue<data_t> [m_nb_dcache];   \
+  } while (0)
+# define CACHE_MISS_BUF_DEALLOC           do {  \
+    delete [] r_icache_miss_buf;                \
+    delete [] r_dcache_miss_buf;                \
+  } while (0)
+# define CACHE_MISS_BUF_RESET(c)          do {          \
+    for (uint32_t x=0; x<m_nb_##c##cache; ++x) {        \
+      while (r_##c##cache_miss_buf[x].size()>0) {       \
+        r_##c##cache_miss_buf[x].pop();                 \
+      }                                                 \
+    }                                                   \
+  } while (0)
+# define CACHE_MISS_BUF_REQ_INIT(c,x)      
+# define CACHE_MISS_BUF_RSP_VAL(c,x,n)    (r_##c##cache_miss_buf[x].size()>0)
+# define CACHE_MISS_BUF_RSP_ACK(c,x)      (r_##c##cache_miss_buf[x].size()<2)
+# define CACHE_MISS_BUF_RSP_DATA(c,x,n)   r_##c##cache_miss_buf[x].front()
+# define CACHE_MISS_BUF_RSP_POP(c,x)      do {  \
+    r_##c##cache_miss_buf[x].pop();             \
+  } while (0)
+# define CACHE_MISS_BUF_RSP_PUSH(c,x,n,d) do {  \
+    r_##c##cache_miss_buf[x].push(d);           \
+  } while (0)
+# define CACHE_MISS_BUF_RSP_PRINT(c)      do {                          \
+    for (uint32_t x=0; x<m_nb_##c##cache; ++x) {                        \
+      PRINTF("    * cache_miss_buf - size : %d\n",r_##c##cache_miss_buf[x].size()); \
+    }                                                                   \
+  } while (0)
+#elif (CC_XCACHE_WRAPPER_FIFO_RSP==2)
+# define CACHE_MISS_BUF_ALLOC             
+# define CACHE_MISS_BUF_DEALLOC           
+# define CACHE_MISS_BUF_RESET(c)          do {  \
+    while (r_##c##cache_miss_buf.size()>0) {    \
+      r_##c##cache_miss_buf.pop();              \
+    }                                           \
+  } while (0)
+# define CACHE_MISS_BUF_REQ_INIT(c,x)      
+# define CACHE_MISS_BUF_RSP_VAL(c,x,n)    ((r_##c##cache_miss_buf.size()>0) and (r_##c##cache_miss_buf.front().num_cache==x))
+# define CACHE_MISS_BUF_RSP_ACK(c,x)      (r_##c##cache_miss_buf.size()<2)
+# define CACHE_MISS_BUF_RSP_DATA(c,x,n)   r_##c##cache_miss_buf.front().data
+# define CACHE_MISS_BUF_RSP_POP(c,x)      do {  \
+    r_##c##cache_miss_buf.pop();                \
+  } while (0)
+# define CACHE_MISS_BUF_RSP_PUSH(c,x,n,d) do {  \
+    miss_buf_t miss_buf;                        \
+    miss_buf.data = d;                          \
+    miss_buf.num_cache = x;                     \
+    r_##c##cache_miss_buf.push(miss_buf);       \
+  } 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_nb_icache];             \
+    r_icache_miss_buf = new data_t * [m_nb_icache];             \
+    for (uint32_t x=0; x<m_nb_icache;++x) {                     \
+      r_icache_miss_val [x] = new bool   [m_icache_words];      \
+      r_icache_miss_buf [x] = new data_t [m_icache_words];      \
+    }                                                           \
+    r_dcache_miss_val = new bool   * [m_nb_dcache];             \
+    r_dcache_miss_buf = new data_t * [m_nb_dcache];             \
+    for (uint32_t x=0; x<m_nb_dcache;++x) {                     \
+      r_dcache_miss_val [x] = new bool   [m_dcache_words];      \
+      r_dcache_miss_buf [x] = new data_t [m_dcache_words];      \
+    }                                                           \
+  } while (0)
+# define CACHE_MISS_BUF_DEALLOC           do {  \
+    for (uint32_t x=0; x<m_nb_icache;++x) {     \
+      delete [] r_icache_miss_val[x];           \
+      delete [] r_icache_miss_buf[x];           \
+    }                                           \
+    delete [] r_icache_miss_val;                \
+    delete [] r_icache_miss_buf;                \
+    for (uint32_t x=0; x<m_nb_dcache;++x) {     \
+      delete [] r_dcache_miss_val[x];           \
+      delete [] r_dcache_miss_buf[x];           \
+    }                                           \
+    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,x)     do {          \
+    for (uint32_t i=0; i<m_##c##cache_words;++i)        \
+      r_##c##cache_miss_val[x][i] = false;              \
+  } while (0)
+# define CACHE_MISS_BUF_RSP_VAL(c,x,n)    r_##c##cache_miss_val[x][n]
+# define CACHE_MISS_BUF_RSP_ACK(c,x)      true
+# define CACHE_MISS_BUF_RSP_DATA(c,x,n)   r_##c##cache_miss_buf[x][n]
+# define CACHE_MISS_BUF_RSP_POP(c,x)         
+# define CACHE_MISS_BUF_RSP_PUSH(c,x,n,d) do {  \
+    r_##c##cache_miss_val[x][n] = true;         \
+    r_##c##cache_miss_buf[x][n] = d;            \
+  } while (0)
+# define CACHE_MISS_BUF_RSP_PRINT(c)      do {                          \
+    for (uint32_t x=0; x<m_nb_##c##cache;++x)                           \
+      for (uint32_t i=0; i<m_##c##cache_words;++i)                      \
+        PRINTF("%d %x |",r_##c##cache_miss_val[x][i],r_##c##cache_miss_buf[x][i]); PRINTF("\n"); \
+  } while (0)
+#endif
+
+// =====[ MULTI_CACHE ]==============================
+
+#if (CC_XCACHE_WRAPPER_MULTI_CACHE==1)
+# define get_num_icache(     addr,num_cpu)   get_num_cache     (addr)          
+# define get_num_icache_only(addr,num_cpu)   get_num_cache_only(addr)          
+# define set_num_icache(     addr,num_cache) set_num_cache     (addr,num_cache)
+# define set_num_icache_only(addr,num_cache) set_num_cache_only(addr,num_cache)
+# define get_num_dcache(     addr)           get_num_cache     (addr)          
+# define get_num_dcache_only(addr)           get_num_cache_only(addr)          
+# define set_num_dcache(     addr,num_cache) set_num_cache     (addr,num_cache)
+# define set_num_dcache_only(addr,num_cache) set_num_cache_only(addr,num_cache)
+#elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2)
+# define get_num_icache(     addr,num_cpu)   num_cpu
+# define get_num_icache_only(addr,num_cpu)   num_cpu
+# define set_num_icache(     addr,num_cache) do  {} while (0)
+# define set_num_icache_only(addr,num_cache) addr
+# define get_num_dcache(     addr)           get_num_cache     (addr)          
+# define get_num_dcache_only(addr)           get_num_cache_only(addr)          
+# define set_num_dcache(     addr,num_cache) set_num_cache     (addr,num_cache)
+# define set_num_dcache_only(addr,num_cache) set_num_cache_only(addr,num_cache)
+#else
+#error "Invalid value to CC_XCACHE_WRAPPER_MULTI_CACHE"
+#endif
+
+namespace soclib { 
+  namespace caba {
+    namespace {
+
+      const char *dcache_fsm_state_str[] = {
+        "DCACHE_IDLE",
+        "DCACHE_WRITE_UPDT",
+        "DCACHE_MISS_VICTIM",
+        "DCACHE_MISS_WAIT",
+        "DCACHE_MISS_UPDT",
+        "DCACHE_UNC_WAIT",
+        "DCACHE_SC_WAIT",
+        "DCACHE_INVAL",
+        "DCACHE_SYNC",
+        "DCACHE_ERROR",
+        "DCACHE_CC_CHECK",
+        "DCACHE_CC_INVAL",
+        "DCACHE_CC_UPDT",
+        "DCACHE_CC_CLEANUP",
+      };
+      const char *icache_fsm_state_str[] = {
+        "ICACHE_IDLE",
+        "ICACHE_MISS_VICTIM",
+        "ICACHE_MISS_WAIT",
+        "ICACHE_MISS_UPDT",
+        "ICACHE_UNC_WAIT",
+        "ICACHE_ERROR",
+        "ICACHE_CC_CLEANUP",
+        "ICACHE_CC_CHECK",
+        "ICACHE_CC_INVAL",
+        "ICACHE_CC_UPDT",
+      };
+      const char *cmd_fsm_state_str[] = {
+        "CMD_IDLE",
+        "CMD_INS_MISS",
+        "CMD_INS_UNC",
+        "CMD_DATA_MISS",
+        "CMD_DATA_UNC",
+        "CMD_DATA_WRITE",
+        "CMD_DATA_SC",
+      };
+      const char *rsp_fsm_state_str[] = {
+        "RSP_IDLE",
+        "RSP_INS_MISS",
+        "RSP_INS_UNC",
+        "RSP_DATA_MISS",
+        "RSP_DATA_UNC",
+        "RSP_DATA_WRITE",
+        "RSP_DATA_SC",
+      };
+      const char *tgt_fsm_state_str[] = {
+        "TGT_IDLE",
+        "TGT_UPDT_WORD",
+        "TGT_UPDT_DATA",
+        "TGT_REQ_BROADCAST",
+        "TGT_REQ_ICACHE",
+        "TGT_REQ_DCACHE",
+        "TGT_RSP_BROADCAST",
+        "TGT_RSP_ICACHE",
+        "TGT_RSP_DCACHE",
+      };
+
+      const char *cleanup_fsm_state_str[] = {
+        "CLEANUP_IDLE",
+        "CLEANUP_REQ",
+        "CLEANUP_RSP_DCACHE",
+        "CLEANUP_RSP_ICACHE",
+      };
+    }
+
+    typedef long long unsigned int blob_t;
+
+#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXCacheWrapperV4_CMP<vci_param, iss_t>
+
+    using soclib::common::uint32_log2;
+
+    /////////////////////////////////
+    tmpl(/**/)::VciCcXCacheWrapperV4_CMP(
+                                     /////////////////////////////////
+                                     sc_module_name name,
+                                     int proc_id,
+                                     const soclib::common::MappingTable &mtp,
+                                     const soclib::common::MappingTable &mtc,
+                                     const soclib::common::IntTab &initiator_index_rw,
+                                     const soclib::common::IntTab &initiator_index_c,
+                                     const soclib::common::IntTab &target_index,
+                                     size_t nb_cpu,
+                                     size_t nb_dcache,
+                                     size_t icache_ways,
+                                     size_t icache_sets,
+                                     size_t icache_words,
+                                     size_t dcache_ways,
+                                     size_t dcache_sets,
+                                     size_t dcache_words,
+                                     size_t wbuf_nwords,
+                                     size_t wbuf_nlines,
+                                     size_t wbuf_timeout,
+                                     write_policy_t write_policy
+                                     )
+               : 
+               soclib::caba::BaseModule(name),
+
+               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"),
+
+               m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()),
+               m_segment(mtc.getSegment(target_index)),
+               m_srcid_rw(mtp.indexForId(initiator_index_rw)),
+               m_srcid_c(mtc.indexForId(initiator_index_c)),
+
+               m_nb_cpu(nb_cpu),
+#if   (CC_XCACHE_WRAPPER_MULTI_CACHE==1)
+               m_nb_icache(nb_dcache),
+#elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2)
+               m_nb_icache(m_nb_cpu),
+#endif
+               m_nb_dcache(nb_dcache),
+               m_nb_cache((m_nb_dcache>m_nb_icache)?m_nb_dcache:m_nb_icache),
+               m_dcache_ways(dcache_ways),
+               m_dcache_words(dcache_words),
+               m_dcache_words_shift(uint32_log2(dcache_words)+uint32_log2(sizeof(data_t))),
+               m_dcache_yzmask((~0)<<m_dcache_words_shift),
+               m_icache_ways(icache_ways),
+               m_icache_words(icache_words),
+               m_icache_words_shift(uint32_log2(icache_words)+uint32_log2(sizeof(data_t))),
+               m_icache_yzmask((~0)<<m_icache_words_shift),
+               m_write_policy(write_policy),
+               m_cache_words((dcache_words)?dcache_words:icache_words),
+
+               r_cpu_prior("r_cpu_prior"),
+
+               r_vci_cmd_fsm("r_vci_cmd_fsm"),
+               r_vci_cmd_min("r_vci_cmd_min"),
+               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_cmd_num_cache("r_vci_cmd_num_cache"),
+
+               r_vci_rsp_fsm("r_vci_rsp_fsm"),
+               r_vci_rsp_cpt("r_vci_rsp_cpt"),
+               //s_vci_rsp_ack("s_vci_rsp_ack"),
+               r_vci_rsp_num_cache("r_vci_rsp_num_cache"),
+
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+               r_cache_word("r_cache_word"),
+#endif
+
+               r_vci_tgt_fsm("r_vci_tgt_fsm"),
+               r_tgt_iaddr("r_tgt_iaddr"),
+               r_tgt_daddr("r_tgt_daddr"),
+               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_num_cache("r_tgt_num_cache"),
+
+               r_cleanup_fsm("r_cleanup_fsm"),
+               r_cleanup_num_cache("r_cleanup_num_cache"),
+               r_cleanup_icache("r_cleanup_icache"),
+
+               m_num_cache_LSB(uint32_log2(icache_words) + uint32_log2(sizeof(data_t))),
+               m_num_cache_MSB(uint32_log2(nb_dcache) + m_num_cache_LSB)
+    {
+      // Size of word is 32 bits
+      ASSERT((icache_words*vci_param::B) < (1<<vci_param::K),
+             "Need more PLEN bits.");
+
+      ASSERT((vci_param::T > 2) and ((1<<(vci_param::T-1)) >= (wbuf_nlines/m_nb_dcache)),
+             "Need more TRDID bits.");
+
+      ASSERT(uint32_log2(nb_dcache) <= (1<<vci_param::P),
+             "Need more PKTID bits.");
+                
+      ASSERT(IS_POW_OF_2(m_nb_dcache),
+             "nb_dcache must be a power of 2.");
+
+      ASSERT(IS_POW_OF_2(m_nb_cpu) and (m_nb_cpu <= m_nb_dcache) and (m_nb_cpu > 0),
+             "nb cpu must be a multiple of nb cache.");
+
+      ASSERT(IS_POW_OF_2(m_icache_ways) and (m_nb_icache <= m_icache_ways),
+             "nb icache ways must be a multiple of nb cache.");
+
+      ASSERT(IS_POW_OF_2(m_dcache_ways) and (m_nb_dcache <= m_dcache_ways),
+             "nb dcache ways must be a multiple of nb cache.");
+
+      ASSERT(icache_words == dcache_words,
+             "icache_words must be equal at dcache_words.");
+
+      ASSERT(IS_POW_OF_2(wbuf_nlines) and (m_nb_dcache <= wbuf_nlines),
+             "wbuf_nlines must be a multiple of nb cache.");
+
+      // FIXME : s'adapter à la taille des requêtes XTN_READ/XTN_WRITE
+      ASSERT((m_nb_dcache == 1) or (dcache_words >= 16),
+             "When multi cache is activated, need 4 bits (16 word) to the cache set .");
+
+      if (m_nb_cpu > 1)
+        ASSERT(CC_XCACHE_MULTI_CPU!=0,
+               "Macro CC_XCACHE_MULTI_CPU in wbuf must be set at 1.");
+
+      p_irq = new sc_in<bool> * [m_nb_cpu];
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        p_irq [num_cpu] = new sc_in<bool> [iss_t::n_irq];
+
+      m_iss = new iss_t * [m_nb_cpu];
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        {
+          std::ostringstream iss_name("");
+          iss_name << this->name() << "_" << num_cpu;
+
+          m_iss[num_cpu] = new iss_t (iss_name.str().c_str(), proc_id+num_cpu);
+        }
+                
+      CACHE_MISS_BUF_ALLOC;
+
+      r_icache_lock          = new sc_signal<uint32_t>[m_nb_icache];
+      r_dcache_lock          = new sc_signal<uint32_t>[m_nb_dcache];
+      r_dcache_sync          = new sc_signal<bool>    [m_nb_dcache];
+
+      r_icache_fsm           = new sc_signal<int>     [m_nb_icache];
+      r_icache_fsm_save      = new sc_signal<int>     [m_nb_icache];
+      r_icache_addr_save     = new sc_signal<addr_40> [m_nb_icache];
+      r_icache_miss_req      = new sc_signal<bool>    [m_nb_icache];
+      r_icache_miss_way      = new sc_signal<size_t>  [m_nb_icache];
+      r_icache_miss_set      = new sc_signal<size_t>  [m_nb_icache];
+      r_icache_unc_req       = new sc_signal<bool>    [m_nb_icache];
+      r_icache_cleanup_req   = new sc_signal<bool>    [m_nb_icache];
+      r_icache_cleanup_line  = new sc_signal<addr_40> [m_nb_icache];
+      r_icache_inval_rsp     = new sc_signal<bool>    [m_nb_icache];
+      r_icache_update_addr   = new sc_signal<size_t>  [m_nb_icache];
+      r_icache_buf_unc_valid = new sc_signal<bool>    [m_nb_icache];
+
+      r_dcache_fsm           = new sc_signal<int>     [m_nb_dcache];
+      r_dcache_fsm_save      = new sc_signal<int>     [m_nb_dcache];
+      r_dcache_addr_save     = new sc_signal<addr_40> [m_nb_dcache];
+      r_dcache_wdata_save    = new sc_signal<data_t>  [m_nb_dcache];
+      r_dcache_rdata_save    = new sc_signal<data_t>  [m_nb_dcache];
+      r_dcache_type_save     = new sc_signal<int>     [m_nb_dcache];
+      r_dcache_be_save       = new sc_signal<be_t>    [m_nb_dcache];
+      r_dcache_cached_save   = new sc_signal<bool>    [m_nb_dcache];
+      r_dcache_num_cpu_save  = new sc_signal<uint32_t>[m_nb_dcache];
+      r_dcache_cleanup_req   = new sc_signal<bool>    [m_nb_dcache];
+      r_dcache_cleanup_line  = new sc_signal<addr_40> [m_nb_dcache];
+      r_dcache_miss_req      = new sc_signal<bool>    [m_nb_dcache];
+      r_dcache_miss_way      = new sc_signal<size_t>  [m_nb_dcache];
+      r_dcache_miss_set      = new sc_signal<size_t>  [m_nb_dcache];
+      r_dcache_unc_req       = new sc_signal<bool>    [m_nb_dcache];
+      r_dcache_sc_req        = new sc_signal<bool>    [m_nb_dcache];
+      r_dcache_inval_rsp     = new sc_signal<bool>    [m_nb_dcache];
+      r_dcache_update_addr   = new sc_signal<size_t>  [m_nb_dcache];
+      r_dcache_previous_unc  = new sc_signal<bool>    [m_nb_dcache];
+
+      r_dcache_ll_data       = new sc_signal<data_64>  * [m_nb_dcache];
+      r_dcache_ll_addr       = new sc_signal<addr_40>  * [m_nb_dcache];
+      r_dcache_ll_valid      = new sc_signal<bool>     * [m_nb_dcache];
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        {
+          r_dcache_ll_data    [num_cache] = new sc_signal<data_64>  [m_nb_cpu];
+          r_dcache_ll_addr    [num_cache] = new sc_signal<addr_40>  [m_nb_cpu];
+          r_dcache_ll_valid   [num_cache] = new sc_signal<bool>     [m_nb_cpu];
+        }
+
+      r_tgt_icache_req       = new sc_signal<bool>    [m_nb_icache];
+      r_tgt_icache_rsp       = new sc_signal<bool>    [m_nb_icache];
+      r_tgt_dcache_req       = new sc_signal<bool>    [m_nb_dcache];
+      r_tgt_dcache_rsp       = new sc_signal<bool>    [m_nb_dcache];
+
+      r_tgt_buf              = new data_t             [m_cache_words];
+      r_tgt_be               = new be_t               [m_cache_words];
+
+      r_vci_rsp_ins_error    = new sc_signal<bool>    [m_nb_icache];
+      r_vci_rsp_data_error   = new sc_signal<bool>    [m_nb_dcache];
+
+      ireq                   = new typename iss_t::InstructionRequest  [m_nb_icache];
+      irsp                   = new typename iss_t::InstructionResponse [m_nb_icache];
+      ireq_cached            = new bool                                [m_nb_icache];
+      ireq_num_cpu           = new uint32_t                            [m_nb_dcache];
+
+      dreq                   = new typename iss_t::DataRequest         [m_nb_dcache];
+      drsp                   = new typename iss_t::DataResponse        [m_nb_dcache];
+      dreq_cached            = new bool                                [m_nb_dcache];
+      dreq_num_cpu           = new uint32_t                            [m_nb_dcache];
+
+      m_cpt_icache_access         = new uint32_t [m_nb_icache];
+      m_cpt_dcache_access         = new uint32_t [m_nb_dcache];
+      m_cpt_icache_miss_victim_wait = new uint32_t [m_nb_icache];
+      m_cpt_dcache_miss_victim_wait = new uint32_t [m_nb_dcache];
+
+#if CC_XCACHE_WRAPPER_STORE_AFTER_STORE
+      m_cpt_dcache_store_after_store    = new uint32_t [m_nb_dcache];
+#endif
+#if CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS
+      m_cpt_dcache_hit_after_miss_read  = new uint32_t [m_nb_dcache];
+      m_cpt_dcache_hit_after_miss_write = new uint32_t [m_nb_dcache];
+#endif
+               
+      m_cpt_fsm_dcache  = new uint32_t * [m_nb_dcache];
+      m_cpt_fsm_icache  = new uint32_t * [m_nb_icache];
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        m_cpt_fsm_dcache[num_cache]  = new uint32_t [soclib::common::size(dcache_fsm_state_str )];
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        m_cpt_fsm_icache[num_cache]  = new uint32_t [soclib::common::size(icache_fsm_state_str )];
+      m_cpt_fsm_cmd     = new uint32_t [soclib::common::size(cmd_fsm_state_str    )];
+      m_cpt_fsm_rsp     = new uint32_t [soclib::common::size(rsp_fsm_state_str    )];
+      m_cpt_fsm_tgt     = new uint32_t [soclib::common::size(tgt_fsm_state_str    )];
+      m_cpt_fsm_cleanup = new uint32_t [soclib::common::size(cleanup_fsm_state_str)];
+
+      m_cpt_frz_cycles  = new uint32_t [m_nb_cpu];
+      // r_icache_fsm("r_icache_fsm"),
+      // r_icache_fsm_save("r_icache_fsm_save"),
+      // 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_icache_buf_unc_valid("r_icache_buf_unc_valid"),
+
+      // r_dcache_fsm("r_dcache_fsm"),
+      // r_dcache_fsm_save("r_dcache_fsm_save"),
+      // r_dcache_addr_save("r_dcache_addr_save"),
+      // r_dcache_wdata_save("r_dcache_wdata_save"),
+      // r_dcache_rdata_save("r_dcache_rdata_save"),
+      // r_dcache_type_save("r_dcache_type_save"),
+      // r_dcache_be_save("r_dcache_be_save"),
+      // r_dcache_cached_save("r_dcache_cached_save"),
+      // r_dcache_cleanup_req("r_dcache_cleanup_req"),
+      // 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_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_tgt_icache_req("r_tgt_icache_req"),
+      // r_tgt_icache_rsp("r_tgt_icache_rsp"),
+
+      // r_tgt_dcache_req("r_tgt_dcache_req"),
+      // r_tgt_dcache_rsp("r_tgt_dcache_rsp"),
+
+      // r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
+      // r_vci_rsp_data_error("r_vci_rsp_data_error"),
+
+      size_t _icache_ways  = icache_ways /m_nb_icache;
+      size_t _icache_sets  = icache_sets ;
+      size_t _dcache_ways  = dcache_ways /m_nb_dcache;
+      size_t _dcache_sets  = dcache_sets ;
+      size_t _icache_words = icache_words;
+      size_t _dcache_words = dcache_words;
+
+      size_t _wbuf_nwords  = wbuf_nwords ;
+      size_t _wbuf_nlines  = wbuf_nlines /m_nb_dcache;
+      size_t _wbuf_timeout = wbuf_timeout;
+
+
+#if CC_XCACHE_WRAPPER_VERBOSE
+      std::cout << "<VciCcXCacheWrapperV4_CMP> Parameters :" << std::endl;
+      std::cout << "  * nb_cpu             : " << nb_cpu << std::endl;
+      std::cout << "  * nb_cache           : " << m_nb_icache << " icache(s), " << m_nb_dcache << " dcache(s)" << std::endl;
+      std::cout << "  * icache (total)     : " <<  icache_ways << " way(s), " <<  icache_sets << " set(s), " <<  icache_words << " word(s)" << std::endl;
+      std::cout << "  * icache (per cache) : " << _icache_ways << " way(s), " << _icache_sets << " set(s), " << _icache_words << " word(s)" << std::endl;
+      std::cout << "  * dcache (total)     : " <<  dcache_ways << " way(s), " <<  dcache_sets << " set(s), " <<  dcache_words << " word(s)" << std::endl;
+      std::cout << "  * dcache (per cache) : " << _dcache_ways << " way(s), " << _dcache_sets << " set(s), " << _dcache_words << " word(s)" << std::endl;
+      std::cout << "  * wbuf   (total)     : " <<  wbuf_nlines << " line(s), " <<  wbuf_nwords << " word(s), timeout : " <<  wbuf_timeout << std::endl;
+      std::cout << "  * wbuf   (per cache) : " << _wbuf_nlines << " line(s), " << _wbuf_nwords << " word(s), timeout : " << _wbuf_timeout << std::endl;
+#endif
+
+      r_icache = new GenericCache<vci_addr_t>  * [m_nb_icache];
+      r_dcache = new GenericCache<vci_addr_t>  * [m_nb_dcache];
+      r_wbuf   = new MultiWriteBuffer<addr_40> * [m_nb_dcache];
+
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        {
+          r_icache [num_cache] = new GenericCache<vci_addr_t>  ("icache", _icache_ways, _icache_sets, _icache_words);
+        }
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        {
+          r_dcache [num_cache] = new GenericCache<vci_addr_t>  ("dcache", _dcache_ways, _dcache_sets, _dcache_words);
+          r_wbuf   [num_cache] = new MultiWriteBuffer<addr_40> ("r_wbuf", _wbuf_nwords, _wbuf_nlines, _wbuf_timeout, _dcache_words);
+        }
+
+      m_num_cache_LSB_mask = 0;
+      for (uint32_t i=0; i<m_num_cache_LSB; ++i)
+        {
+          m_num_cache_LSB_mask <<= 1;
+          m_num_cache_LSB_mask  |= 1;
+        }
+      m_num_cache_mask = 0;
+      for (uint32_t i=0; i<(m_num_cache_MSB-m_num_cache_LSB); ++i)
+        {
+          m_num_cache_mask <<= 1;
+          m_num_cache_mask  |= 1;
+        }
+
+      SC_METHOD(transition);
+      dont_initialize();
+      sensitive << p_clk.pos();
+
+      SC_METHOD(genMoore);
+      dont_initialize();
+      sensitive << p_clk.neg();
+
+      typename iss_t::CacheInfo cache_info;
+      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.dcache_line_size = dcache_words*sizeof(data_t);
+      cache_info.dcache_assoc     = dcache_ways;
+      cache_info.dcache_n_lines   = dcache_sets;
+
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        m_iss[num_cpu]->setCacheInfo(cache_info);
+                
+#if CC_XCACHE_WRAPPER_STOP_SIMULATION
+      m_stop_simulation               = false;
+      m_stop_simulation_nb_frz_cycles = new uint32_t [m_nb_cpu];
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        m_stop_simulation_nb_frz_cycles [num_cpu] = 0;
+#endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+      generate_log_transaction_file_icache  = true;
+      generate_log_transaction_file_dcache  = true;
+      generate_log_transaction_file_cmd     = true;
+      generate_log_transaction_file_tgt     = true;
+      generate_log_transaction_file_cleanup = true;
+
+      log_transaction_file_icache = new std::ofstream [m_nb_cpu];
+      log_transaction_file_dcache = new std::ofstream [m_nb_cpu];
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        {
+          {
+            std::ostringstream filename("");
+            filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_icache-" << proc_id << "_" << num_cpu << ".log";
+            log_transaction_file_icache[num_cpu].open(filename.str().c_str() ,std::ios::out | std::ios::trunc);
+          }
+          {
+            std::ostringstream filename("");
+            filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_dcache-" << proc_id << "_" << num_cpu << ".log";
+            log_transaction_file_dcache[num_cpu].open(filename.str().c_str() ,std::ios::out | std::ios::trunc);
+          }
+        }
+
+      {
+        std::ostringstream filename("");
+        filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_cmd-" << proc_id << ".log";
+        log_transaction_file_cmd.open(filename.str().c_str() ,std::ios::out | std::ios::trunc);
+      }
+      {
+        std::ostringstream filename("");
+        filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_tgt-" << proc_id << ".log";
+        log_transaction_file_tgt.open(filename.str().c_str() ,std::ios::out | std::ios::trunc);
+      }
+      {
+        std::ostringstream filename("");
+        filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_cleanup-" << proc_id << ".log";
+        log_transaction_file_cleanup.open(filename.str().c_str() ,std::ios::out | std::ios::trunc);
+      }
+#endif
+
+#if MWBUF_VHDL_TESTBENCH
+      simulation_started = false;
+
+      vhdl_testbench_mwbuf = new std::ofstream [m_nb_dcache];
+      for (uint32_t num_dcache=0; num_dcache<m_nb_dcache; ++num_dcache)
+        {
+          std::ostringstream filename("");
+          filename << "VHDL_testbench_mwbuf-" << proc_id << "_" << num_dcache << ".txt";
+          vhdl_testbench_mwbuf[num_dcache].open(filename.str().c_str() ,std::ios::out | std::ios::trunc);
+
+          vhdl_testbench_mwbuf[num_dcache] 
+            << _wbuf_nlines  << " "        // nb_lines      
+            << _wbuf_nwords  << " "        // nb_words      
+            << _wbuf_timeout << " "        // timeout       
+            << m_nb_cpu      << " "        // nb_cpu        
+            << 32            << " "        // size_data     
+            << 40            << " "        // size_addr     
+            << _dcache_words << std::endl; // cache_nb_words
+        }
+
+#endif
+    } // end constructor
+
+    ///////////////////////////////////
+    tmpl(/**/)::~VciCcXCacheWrapperV4_CMP()
+               ///////////////////////////////////
+    {
+#if MWBUF_VHDL_TESTBENCH
+      for (uint32_t num_dcache=0; num_dcache<m_nb_dcache; ++num_dcache)
+        vhdl_testbench_mwbuf[num_dcache].close();
+      delete [] vhdl_testbench_mwbuf;
+#endif
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        {
+          log_transaction_file_dcache[num_cpu].close();
+          log_transaction_file_icache[num_cpu].close();
+        }
+      delete [] log_transaction_file_dcache;
+      delete [] log_transaction_file_icache;
+
+      log_transaction_file_cmd    .close();
+      log_transaction_file_tgt    .close();
+      log_transaction_file_cleanup.close();
+#endif
+
+      delete [] m_stop_simulation_nb_frz_cycles;
+
+
+      delete [] r_icache_lock         ;
+      delete [] r_dcache_lock         ;
+      delete [] r_dcache_sync         ;
+
+      delete [] r_icache_fsm          ;
+      delete [] r_icache_fsm_save     ;
+      delete [] r_icache_addr_save    ;
+      delete [] r_icache_miss_req     ;
+      delete [] r_icache_miss_way     ;
+      delete [] r_icache_miss_set     ;
+      delete [] r_icache_unc_req      ;
+      delete [] r_icache_cleanup_req  ;
+      delete [] r_icache_cleanup_line ;
+      delete [] r_icache_inval_rsp    ;
+      delete [] r_icache_update_addr  ;
+      delete [] r_icache_buf_unc_valid;
+
+      delete [] r_dcache_fsm          ;
+      delete [] r_dcache_fsm_save     ;
+      delete [] r_dcache_addr_save    ;
+      delete [] r_dcache_wdata_save   ;
+      delete [] r_dcache_rdata_save   ;
+      delete [] r_dcache_type_save    ;
+      delete [] r_dcache_be_save      ;
+      delete [] r_dcache_cached_save  ;
+      delete [] r_dcache_cleanup_req  ;
+      delete [] r_dcache_cleanup_line ;
+      delete [] r_dcache_miss_req     ;
+      delete [] r_dcache_miss_way     ;
+      delete [] r_dcache_miss_set     ;
+      delete [] r_dcache_unc_req      ;
+      delete [] r_dcache_sc_req       ;
+      delete [] r_dcache_inval_rsp    ;
+      delete [] r_dcache_update_addr  ;
+      delete [] r_dcache_previous_unc ;
+
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        {
+          delete [] r_dcache_ll_data    [num_cache];
+          delete [] r_dcache_ll_addr    [num_cache];
+          delete [] r_dcache_ll_valid   [num_cache];
+        }
+      delete [] r_dcache_num_cpu_save ;
+      delete [] r_dcache_ll_data      ;
+      delete [] r_dcache_ll_addr      ;
+      delete [] r_dcache_ll_valid     ;
+
+      delete [] r_tgt_icache_req      ;
+      delete [] r_tgt_icache_rsp      ;
+      delete [] r_tgt_dcache_req      ;
+      delete [] r_tgt_dcache_rsp      ;
+
+      delete [] r_tgt_be ;
+      delete [] r_tgt_buf;
+
+      delete [] r_vci_rsp_ins_error   ;
+      delete [] r_vci_rsp_data_error  ;
+
+      delete [] ireq           ;
+      delete [] irsp           ;
+      delete [] ireq_cached    ;
+      delete [] ireq_num_cpu   ;
+      delete [] dreq           ;
+      delete [] drsp           ;
+      delete [] dreq_cached    ;
+      delete [] dreq_num_cpu   ;
+
+      delete [] m_cpt_frz_cycles;
+
+      delete [] m_cpt_icache_access   ;
+      delete [] m_cpt_dcache_access   ;
+      delete [] m_cpt_icache_miss_victim_wait;
+      delete [] m_cpt_dcache_miss_victim_wait;
+#if CC_XCACHE_WRAPPER_STORE_AFTER_STORE
+      delete [] m_cpt_dcache_store_after_store;
+#endif
+#if CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS
+      delete [] m_cpt_dcache_hit_after_miss_read;
+      delete [] m_cpt_dcache_hit_after_miss_write;
+#endif
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        delete [] m_cpt_fsm_dcache [num_cache];
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        delete [] m_cpt_fsm_icache [num_cache];
+        
+      delete [] m_cpt_fsm_dcache ;
+      delete [] m_cpt_fsm_icache ;
+      delete [] m_cpt_fsm_cmd    ;
+      delete [] m_cpt_fsm_rsp    ;
+      delete [] m_cpt_fsm_tgt    ;
+      delete [] m_cpt_fsm_cleanup;
+
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        {
+          delete r_icache [num_cache];
+        }
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        {
+          delete r_wbuf   [num_cache];
+          delete r_dcache [num_cache];
+        }
+      delete [] r_wbuf;
+      delete [] r_icache;
+      delete [] r_dcache;
+
+
+      CACHE_MISS_BUF_DEALLOC;
+
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        {
+          delete    m_iss [num_cpu];
+          delete [] p_irq [num_cpu];
+        }
+      delete [] m_iss;
+      delete [] p_irq;
+    }
+
+    ////////////////////////
+    tmpl(void)::print_cpi()
+               ////////////////////////
+    {
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        std::cout << "CPU " << m_srcid_rw << " : CPI = " 
+                  << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles[num_cpu]) << std::endl ;
+    }
+    ////////////////////////
+    tmpl(void)::print_stats(bool print_wbuf, bool print_fsm)
+               ////////////////////////
+    {
+      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;
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        {
+          float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles[num_cpu]);
+
+          std::cout << "- CPI                            : [" << num_cpu << "] "<< (float)m_cpt_total_cycles/run_cycles << std::endl ;
+          std::cout << "- IPC                            : [" << num_cpu << "] "<< (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;
+
+      uint32_t m_cpt_icache_access_all = 0;
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        m_cpt_icache_access_all += m_cpt_icache_access [num_cache];
+
+      std::cout << "- ICACHE ACCESS                  : " << m_cpt_icache_access_all << std::endl;
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        std::cout << "  + [" << num_cache << "] : " << m_cpt_icache_access [num_cache] << " (" << (float)m_cpt_icache_access [num_cache]*100.0/(float)m_cpt_icache_access_all << "%)" << std::endl;
+
+      uint32_t m_cpt_dcache_access_all = 0;
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        m_cpt_dcache_access_all += m_cpt_dcache_access [num_cache];
+
+      std::cout << "- DCACHE ACCESS                  : " << m_cpt_dcache_access_all << std::endl;
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        {
+          std::cout << "  + [" << num_cache << "] : " << m_cpt_dcache_access [num_cache] << " (" << (float)m_cpt_dcache_access [num_cache]*100.0/(float)m_cpt_dcache_access_all << "%)";
+
+#if CC_XCACHE_WRAPPER_STORE_AFTER_STORE
+          std::cout << " - store after store : " << m_cpt_dcache_store_after_store [num_cache];
+#endif
+#if CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS
+          std::cout << " - Hit after Miss : Read " << m_cpt_dcache_hit_after_miss_read [num_cache] << ", Write " << m_cpt_dcache_hit_after_miss_write [num_cache];
+#endif
+          std::cout << std::endl;
+        }
+
+      uint32_t m_cpt_icache_miss_victim_wait_all = 0;
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        m_cpt_icache_miss_victim_wait_all += m_cpt_icache_miss_victim_wait [num_cache];
+      std::cout << "- ICACHE MISS VICTIM WAIT        : " << m_cpt_icache_miss_victim_wait_all << std::endl;
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        std::cout << "  + [" << num_cache << "] : " << m_cpt_icache_miss_victim_wait [num_cache] << std::endl;
+
+      uint32_t m_cpt_dcache_miss_victim_wait_all = 0;
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        m_cpt_dcache_miss_victim_wait_all += m_cpt_dcache_miss_victim_wait [num_cache];
+      std::cout << "- DCACHE MISS VICTIM WAIT        : " << m_cpt_dcache_miss_victim_wait_all << std::endl;
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        std::cout << "  + [" << num_cache << "] : " << m_cpt_dcache_miss_victim_wait [num_cache] << std::endl;
+
+      if (print_fsm)
+        {
+          std::cout << "- DCACHE FSM" << std::endl;
+          for (uint32_t i=0; i<soclib::common::size(dcache_fsm_state_str ); ++i)
+            {
+              std::cout << "  + "  << dcache_fsm_state_str[i] << " :\t ";
+              for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+                std::cout << m_cpt_fsm_dcache [num_cache][i] << ", ";
+              std::cout << std::endl; 
+            }
+          std::cout << "- ICACHE FSM" << std::endl;
+          for (uint32_t i=0; i<soclib::common::size(icache_fsm_state_str ); ++i)
+            {
+              std::cout << "  + "  << icache_fsm_state_str[i] << " :\t ";
+              for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+                std::cout << m_cpt_fsm_icache [num_cache][i] << ", ";
+              std::cout << std::endl; 
+            }
+          std::cout << "- CMD FSM" << std::endl;
+          for (uint32_t i=0; i<soclib::common::size(cmd_fsm_state_str ); ++i)
+            std::cout << "  + " << cmd_fsm_state_str[i] << " :\t " << m_cpt_fsm_cmd [i] << std::endl;
+          std::cout << "- RSP FSM" << std::endl;
+          for (uint32_t i=0; i<soclib::common::size(rsp_fsm_state_str ); ++i)
+            std::cout << "  + " << rsp_fsm_state_str[i] << " :\t " << m_cpt_fsm_rsp [i] << std::endl;
+          std::cout << "- TGT FSM" << std::endl;
+          for (uint32_t i=0; i<soclib::common::size(tgt_fsm_state_str ); ++i)
+            std::cout << "  + "  << tgt_fsm_state_str[i] << " :\t " << m_cpt_fsm_tgt [i] << std::endl;
+          std::cout << "- CLEANUP FSM" << std::endl;
+          for (uint32_t i=0; i<soclib::common::size(cleanup_fsm_state_str ); ++i)
+            std::cout << "  + "  << cleanup_fsm_state_str[i] << " :\t " << m_cpt_fsm_cleanup [i] << std::endl;
+        }
+
+      std::cout << "* : accepted or not by the cache" << std::endl ;
+
+      if (print_wbuf)
+        for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+          r_wbuf[num_cache]->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;
+
+      std::cout << std::dec << "Proc \"" << name() << "\"" << std::endl;
+
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        {
+          m_iss[num_cpu]->getRequests( ireq, dreq );
+          std::cout << ireq << std::endl;
+          std::cout << dreq << std::endl;
+        }
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        std::cout << "  " << icache_fsm_state_str[r_icache_fsm[num_cache]] << std::endl;
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        std::cout << "  " << dcache_fsm_state_str[r_dcache_fsm[num_cache]] << std::endl;
+            
+      std::cout << "  " << 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)
+        {
+          for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+            r_wbuf[num_cache]->printTrace((mode>>1)&1);
+        }
+      if(mode & 0x4)
+        {
+          std::cout << "  Data cache" << std::endl;
+          for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+            r_dcache[num_cache]->printTrace();
+        }
+      if(mode & 0x8)
+        {
+          std::cout << "  Instruction cache" << std::endl;
+          for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+            r_icache[num_cache]->printTrace();
+        }
+    }
+
+    //////////////////////////
+    tmpl(void)::transition()
+               //////////////////////////
+    {
+      if ( not p_resetn.read() ) {
+
+        r_cpu_prior = 0;
+
+        for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+          m_iss[num_cpu]->reset();
+
+        // FSM states
+        for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+          {
+            r_icache_fsm [num_cache] = ICACHE_IDLE;
+
+            r_icache_lock[num_cache] = m_nb_cpu;
+          }
+        for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+          {
+            r_dcache_fsm [num_cache] = DCACHE_IDLE;
+
+            r_dcache_lock[num_cache] = m_nb_cpu;
+            r_dcache_sync[num_cache] = false;
+          }
+
+        r_vci_cmd_fsm = CMD_IDLE;
+        r_vci_rsp_fsm = RSP_IDLE;
+        r_vci_tgt_fsm = TGT_IDLE;
+        r_cleanup_fsm = CLEANUP_IDLE;
+
+        for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+          {
+            // write buffer & caches
+            r_icache[num_cache]->reset();
+
+            // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI  FSMs
+            r_icache_miss_req    [num_cache] = false;
+            r_icache_unc_req     [num_cache] = false;
+            r_icache_cleanup_req [num_cache] = false;
+
+            // internal messages in DCACHE et ICACHE FSMs
+            r_icache_inval_rsp   [num_cache] = false;
+
+            // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs
+            r_icache_buf_unc_valid [num_cache] = false;
+
+            // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
+            r_tgt_icache_req     [num_cache] = false;
+            r_tgt_icache_rsp     [num_cache] = false;
+
+            r_vci_rsp_ins_error  [num_cache] = false;
+          }// end for num_cache
+
+        for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+          {
+            // write buffer & caches
+            r_wbuf  [num_cache]->reset();
+            r_dcache[num_cache]->reset();
+
+            // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI  FSMs
+            r_dcache_miss_req    [num_cache] = false;
+            r_dcache_unc_req     [num_cache] = false;
+            r_dcache_sc_req      [num_cache] = false;
+            r_dcache_cleanup_req [num_cache] = false;
+            r_dcache_previous_unc[num_cache] = false;
+
+            // internal messages in DCACHE et ICACHE FSMs
+            r_dcache_inval_rsp   [num_cache] = false;
+
+            // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs
+            for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+              r_dcache_ll_valid      [num_cache][num_cpu] = false;
+
+            // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
+            r_tgt_dcache_req     [num_cache] = false;
+            r_tgt_dcache_rsp     [num_cache] = false;
+
+            r_vci_rsp_data_error [num_cache] = false;
+          }// end for num_cache
+
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+        r_cache_word         = 0;
+#endif
+
+        r_vci_cmd_dcache_prior = 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_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_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;
+
+        for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+          m_cpt_frz_cycles [num_cpu]  = 0;
+        m_cpt_total_cycles = 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;
+        m_cost_data_miss_frz = 0;
+        m_cost_unc_read_frz = 0;
+        m_cost_ins_miss_frz = 0;
+
+        m_cpt_imiss_transaction = 0;
+        m_cpt_dmiss_transaction = 0;
+        m_cpt_unc_transaction = 0;
+        m_cpt_data_write_transaction = 0;
+
+        m_cost_imiss_transaction = 0;
+        m_cost_dmiss_transaction = 0;
+        m_cost_unc_transaction = 0;
+        m_cost_write_transaction = 0;
+        m_length_write_transaction = 0;
+
+        for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+          {
+            m_cpt_icache_access           [num_cache] = 0;
+            m_cpt_icache_miss_victim_wait [num_cache] = 0;
+
+            for (uint32_t i=0; i<soclib::common::size(icache_fsm_state_str ); ++i)
+              m_cpt_fsm_icache  [num_cache][i] = 0;
+          }
+        for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+          {
+            m_cpt_dcache_access               [num_cache] = 0;
+            m_cpt_dcache_miss_victim_wait     [num_cache] = 0;
+
+#if CC_XCACHE_WRAPPER_STORE_AFTER_STORE
+            m_cpt_dcache_store_after_store    [num_cache] = 0;
+#endif
+#if CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS
+            m_cpt_dcache_hit_after_miss_read  [num_cache] = 0;
+            m_cpt_dcache_hit_after_miss_write [num_cache] = 0;
+#endif
+            for (uint32_t i=0; i<soclib::common::size(dcache_fsm_state_str ); ++i)
+              m_cpt_fsm_dcache  [num_cache][i] = 0;
+          }
+
+        for (uint32_t i=0; i<soclib::common::size(cmd_fsm_state_str    ); ++i)
+          m_cpt_fsm_cmd     [i] = 0;
+        for (uint32_t i=0; i<soclib::common::size(rsp_fsm_state_str    ); ++i)
+          m_cpt_fsm_rsp     [i] = 0;
+        for (uint32_t i=0; i<soclib::common::size(tgt_fsm_state_str    ); ++i)
+          m_cpt_fsm_tgt     [i] = 0;
+        for (uint32_t i=0; i<soclib::common::size(cleanup_fsm_state_str); ++i)
+          m_cpt_fsm_cleanup [i] = 0;
+
+        return;
+      }
+
+#if MWBUF_VHDL_TESTBENCH
+      simulation_started = true;
+
+      vhdl_tb_t vhdl_mwbuf_test_empty            [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_empty            [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_flush            [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_write_val        [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_write_ack        [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_write_ack        [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_write_addr       [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_write_data       [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_write_be         [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_write_cached     [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_write_cpu_id     [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_sent_val         [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_sent_val         [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_sent_ack         [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_sent_word_min    [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_sent_word_min    [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_sent_word_max    [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_sent_word_max    [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_sent_word        [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_sent_addr        [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_sent_addr        [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_sent_data        [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_sent_data        [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_sent_be          [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_sent_be          [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_sent_index       [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_sent_index       [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_raw_test         [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_raw_addr         [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_raw_miss         [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_raw_miss         [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_completed_val    [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_completed_index  [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_completed_cached [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_completed_cached [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_test_completed_cpu_id [m_nb_dcache];
+      vhdl_tb_t vhdl_mwbuf_port_completed_cpu_id [m_nb_dcache];
+
+      for (uint32_t num_dcache=0; num_dcache<m_nb_dcache; ++num_dcache)
+        {
+          vhdl_mwbuf_test_empty            [num_dcache] = 0;
+          vhdl_mwbuf_port_empty            [num_dcache] = 0;
+          vhdl_mwbuf_port_flush            [num_dcache] = 0;
+          vhdl_mwbuf_port_write_val        [num_dcache] = 0;
+          vhdl_mwbuf_test_write_ack        [num_dcache] = 0;
+          vhdl_mwbuf_port_write_ack        [num_dcache] = 0;
+          vhdl_mwbuf_port_write_addr       [num_dcache] = 0;
+          vhdl_mwbuf_port_write_data       [num_dcache] = 0;
+          vhdl_mwbuf_port_write_be         [num_dcache] = 0;
+          vhdl_mwbuf_port_write_cached     [num_dcache] = 0;
+          vhdl_mwbuf_port_write_cpu_id     [num_dcache] = 0;
+          vhdl_mwbuf_test_sent_val         [num_dcache] = 0;
+          vhdl_mwbuf_port_sent_val         [num_dcache] = 0;
+          vhdl_mwbuf_port_sent_ack         [num_dcache] = 0;
+          vhdl_mwbuf_test_sent_word_min    [num_dcache] = 0;
+          vhdl_mwbuf_port_sent_word_min    [num_dcache] = 0;
+          vhdl_mwbuf_test_sent_word_max    [num_dcache] = 0;
+          vhdl_mwbuf_port_sent_word_max    [num_dcache] = 0;
+          vhdl_mwbuf_port_sent_word        [num_dcache] = 0;
+          vhdl_mwbuf_test_sent_addr        [num_dcache] = 0;
+          vhdl_mwbuf_port_sent_addr        [num_dcache] = 0;
+          vhdl_mwbuf_test_sent_data        [num_dcache] = 0;
+          vhdl_mwbuf_port_sent_data        [num_dcache] = 0;
+          vhdl_mwbuf_test_sent_be          [num_dcache] = 0;
+          vhdl_mwbuf_port_sent_be          [num_dcache] = 0;
+          vhdl_mwbuf_test_sent_index       [num_dcache] = 0;
+          vhdl_mwbuf_port_sent_index       [num_dcache] = 0;
+          vhdl_mwbuf_port_raw_test         [num_dcache] = 0;
+          vhdl_mwbuf_port_raw_addr         [num_dcache] = 0;
+          vhdl_mwbuf_test_raw_miss         [num_dcache] = 0;
+          vhdl_mwbuf_port_raw_miss         [num_dcache] = 0;
+          vhdl_mwbuf_port_completed_val    [num_dcache] = 0;
+          vhdl_mwbuf_port_completed_index  [num_dcache] = 0;
+          vhdl_mwbuf_test_completed_cached [num_dcache] = 0;
+          vhdl_mwbuf_port_completed_cached [num_dcache] = 0;
+          vhdl_mwbuf_test_completed_cpu_id [num_dcache] = 0;
+          vhdl_mwbuf_port_completed_cpu_id [num_dcache] = 0;
+        }
+#endif
+
+      // printf("%d\n",(uint32_t)m_cpt_total_cycles);
+
+      PRINTF("--------------------------------------------\n");
+      PRINTF("  * CC_XCACHE_WRAPPER \"%s\" Transition - Time = %d\n",name().c_str(),(uint32_t)m_cpt_total_cycles);
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        PRINTF("    * fsm dcache              = [%.2d] %s - (%.2d) %llx (%llx)\n",num_cache,dcache_fsm_state_str[r_dcache_fsm[num_cache]],r_dcache_lock[num_cache].read(),(blob_t)r_dcache_addr_save[num_cache].read(),(blob_t)set_num_dcache_only(r_dcache_addr_save[num_cache].read(),num_cache));
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        PRINTF("    * fsm icache              = [%.2d] %s - (%.2d) %llx (%llx)\n",num_cache,icache_fsm_state_str[r_icache_fsm[num_cache]],r_icache_lock[num_cache].read(),(blob_t)r_icache_addr_save[num_cache].read(),(blob_t)set_num_icache_only(r_icache_addr_save[num_cache].read(),num_cache));
+      PRINTF("    * fsm cmd                 = (%.2d) %s\n",r_vci_cmd_num_cache.read(), cmd_fsm_state_str[r_vci_cmd_fsm]);
+      PRINTF("    * fsm rsp                 = (%.2d) %s\n",r_vci_rsp_num_cache.read(), rsp_fsm_state_str[r_vci_rsp_fsm]);
+      PRINTF("    * fsm tgt                 = (%.2d) %s - i %llx d %llx\n",r_tgt_num_cache.read(), tgt_fsm_state_str[r_vci_tgt_fsm],(blob_t)r_tgt_iaddr.read(),(blob_t)r_tgt_daddr.read());
+    //PRINTF("    * fsm tgt                 =      %s - %llx\n",tgt_fsm_state_str[r_vci_tgt_fsm],(blob_t)r_tgt_addr.read());
+      PRINTF("    * fsm cleanup             = (%.2d) %s\n",r_cleanup_num_cache.read(), cleanup_fsm_state_str[r_cleanup_fsm]);
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        {
+          for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+            PRINTF("    * ll info                 : [%.2d][%.2d] %d %llx (%llx) %llx\n"
+                   ,num_cache
+                   ,num_cpu
+                   ,          r_dcache_ll_valid [num_cache][num_cpu].read()
+                   ,(blob_t)r_dcache_ll_addr  [num_cache][num_cpu].read()
+                   ,(blob_t)set_num_dcache_only(r_dcache_ll_addr [num_cache][num_cpu].read(),num_cache)
+                   ,(blob_t)r_dcache_ll_data [num_cache][num_cpu].read());
+
+          PRINTF("    * dcache_previous_unc     : [%.2d] %d\n",num_cache,r_dcache_previous_unc[num_cache].read());
+
+#if CC_XCACHE_WRAPPER_DEBUG
+          if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
+            r_wbuf[num_cache]->printTrace(1);
+#endif
+
+          // VHDL debug
+// #if MWBUF_VHDL_TESTBENCH
+//           printf("\nMWBUF[%d] - Time = %d\n\n",num_cache,(uint32_t)m_cpt_total_cycles);
+//           r_wbuf[num_cache]->printTrace(1);
+// #endif
+
+        }
+      // CACHE_MISS_BUF_RSP_PRINT(i);
+      // CACHE_MISS_BUF_RSP_PRINT(d);
+
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        m_cpt_fsm_dcache  [num_cache][r_dcache_fsm[num_cache]] ++;
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        m_cpt_fsm_icache  [num_cache][r_icache_fsm[num_cache]] ++;
+      m_cpt_fsm_cmd     [r_vci_cmd_fsm] ++;
+      m_cpt_fsm_rsp     [r_vci_rsp_fsm] ++;
+      m_cpt_fsm_tgt     [r_vci_tgt_fsm] ++;
+      m_cpt_fsm_cleanup [r_cleanup_fsm] ++;
+
+      m_cpt_total_cycles++;
+
+      /////////////////////////////////////////////////////////////////////
+      // The TGT_FSM controls the following ressources:
+      // - r_vci_tgt_fsm
+      // - r_tgt_buf[nwords]
+      // - r_tgt_be[nwords]
+      // - r_tgt_update
+      // - r_tgt_word
+      // - r_tgt_addr
+      // - r_tgt_srcid
+      // - r_tgt_trdid
+      // - r_tgt_pktid
+      // All VCI commands must be CMD_WRITE.
+      // If the VCI address offset is null, the command is an invalidate 
+      // request. It is an update request otherwise.
+      // The VCI_TGT FSM stores the external request arguments in the
+      // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 
+      // & r_tgt_dcache_req flip-flops to signal the external request to 
+      // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
+      // of the update or invalidate request in the RSP state.
+      // -  for an invalidate request the VCI packet length is 1 word.
+      // The WDATA field contains the line index (i.e. the Z & Y fields).
+      // -  for an update request the VCI packet length is (n+2) words.
+      // The WDATA field of the first VCI word contains the line number.
+      // The WDATA field of the second VCI word contains the word index.
+      // The WDATA field of the n following words contains the values.
+      // -  for both invalidate & update requests, the VCI response
+      // is one single word.
+      // In case of errors in the VCI command packet, the simulation
+      // is stopped with an error message.
+      /////////////////////////////////////////////////////////////////////
+
+      switch(r_vci_tgt_fsm) {
+
+      case TGT_IDLE:
+        if ( p_vci_tgt.cmdval.read() ) 
+          {
+            PRINTF("    * <TGT> Request\n");
+
+            addr_40 address = p_vci_tgt.address.read();
+
+            if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) 
+              {
+                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "coherence request is not a write" << std::endl;
+                std::cout << "address = " << 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) 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 << "address = " << std::hex << address << std::dec << std::endl;
+                std::cout << "srcid   = " << p_vci_tgt.srcid.read() << std::endl;
+                exit(0);
+              }
+
+            addr_40 tgt_addr  = ((((addr_40)p_vci_tgt.be.read() & 0x3) << 32) | ((addr_40) p_vci_tgt.wdata.read())) << (addr_40)m_dcache_words_shift;
+            // * m_dcache_words * 4;
+
+            addr_40 tgt_iaddr = tgt_addr;
+            addr_40 tgt_daddr = tgt_addr;
+
+            PRINTF("    * <TGT> srcid            : %d\n",(uint32_t)p_vci_tgt.srcid.read());
+            PRINTF("    * <TGT> trdid            : %d\n",(uint32_t)p_vci_tgt.trdid.read());
+            PRINTF("    * <TGT> pktid            : %d\n",(uint32_t)p_vci_tgt.pktid.read());
+            PRINTF("    * <TGT> address (before) : %llx\n",(blob_t)tgt_iaddr);
+
+            r_tgt_srcid     = p_vci_tgt.srcid.read();
+            r_tgt_trdid     = p_vci_tgt.trdid.read();
+            r_tgt_pktid     = p_vci_tgt.pktid.read();
+            // r_tgt_plen      = p_vci_tgt.plen.read();
+                    
+            // BROADCAST
+            if ( (address&0x3) == 0x3 )   // broadcast invalidate for data or instruction type
+              {
+                if ( not p_vci_tgt.eop.read() ) 
+                  {
+                    std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                    std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
+                    exit(0);
+                  }
+                r_tgt_update = false; 
+                // r_tgt_brdcast= true;
+                r_vci_tgt_fsm = TGT_REQ_BROADCAST;
+                uint32_t tgt_num_cache;
+                tgt_num_cache = get_num_icache(tgt_iaddr,0); // none effect (else CC_XCACHE_WRAPPER_MULTI_CACHE==1)
+                tgt_num_cache = get_num_dcache(tgt_daddr);
+                r_tgt_num_cache = tgt_num_cache;
+
+                PRINTF("    * <TGT> REQ_BROADCAST\n");
+                PRINTF("    * <TGT> num_cache (data) : %d\n",tgt_num_cache);
+
+                m_cpt_cc_inval_broadcast++ ;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                if (generate_log_transaction_file_tgt)
+                  {
+                    log_transaction_file_tgt
+                      << "[" << m_cpt_total_cycles << "] "
+                      << "BROADCAST  "
+                      << std::hex
+                      << " L " << std::setw(10) << (blob_t)tgt_addr
+                      << std::dec
+                      << " - " << tgt_num_cache
+                      << std::endl;
+                  }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+              }
+            else                    // multi-update or multi-invalidate for data type
+              { 
+                uint32_t cell = address - m_segment.baseAddress(); // addr_40
+                // r_tgt_brdcast = false;
+
+                if (cell == 0) 
+                  {                                       // invalidate data
+                    if ( not p_vci_tgt.eop.read() ) 
+                      {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                        exit(0);
+                      }
+                    r_tgt_update = false; 
+                    r_vci_tgt_fsm = TGT_REQ_DCACHE;
+                    uint32_t tgt_num_cache = get_num_dcache(tgt_daddr); // static partionnement
+                    r_tgt_num_cache = tgt_num_cache;
+                            
+                    PRINTF("    * <TGT> REQ_DCACHE\n");
+                    PRINTF("    * <TGT> num_cache        : %d\n",tgt_num_cache);
+
+                    m_cpt_cc_inval_dcache++ ;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                    if (generate_log_transaction_file_tgt)
+                      {
+                        log_transaction_file_tgt
+                          << "[" << m_cpt_total_cycles << "] "
+                          << "INVAL DATA "
+                          << std::hex
+                          << " L " << std::setw(10) << (blob_t)tgt_addr
+                          << std::dec 
+                          << " - " << tgt_num_cache
+                          << std::endl;
+                      }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+                  } 
+                else if (cell == 4)                     // invalidate instruction
+                  {                         
+                    if ( not p_vci_tgt.eop.read() ) 
+                      {
+                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                        exit(0);
+                      }
+                    r_tgt_update = false; 
+                    r_vci_tgt_fsm = TGT_REQ_ICACHE;
+                    uint32_t tgt_num_cpu   = p_vci_tgt.pktid.read();
+                    uint32_t tgt_num_cache = get_num_icache(tgt_iaddr,tgt_num_cpu);
+                    r_tgt_num_cache = tgt_num_cache;
+                            
+                    PRINTF("    * <TGT> REQ_ICACHE\n");
+                    PRINTF("    * <TGT> num_cache        : %d\n",tgt_num_cache);
+
+                    m_cpt_cc_inval_icache++ ;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                    if (generate_log_transaction_file_tgt)
+                      {
+                        log_transaction_file_tgt
+                          << "[" << m_cpt_total_cycles << "] "
+                          << "INVAL INS  "
+                          << std::hex
+                          << " L " << std::setw(10) << (blob_t)tgt_addr
+                          << std::dec
+                          << " - " << tgt_num_cache
+                          << std::endl;
+                      }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+                  } 
+                else if ( (cell == 8) or (cell==12) )    // update data or instruction
+                  {                                
+                    if ( p_vci_tgt.eop.read() ) 
+                      {
+                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                        exit(0);
+                      }
+                    if(cell == 8)
+                      {
+                        m_cpt_cc_update_dcache++;
+                        r_tgt_update_data = true;
+
+                        uint32_t tgt_num_cache = get_num_dcache(tgt_daddr);
+                        r_tgt_num_cache = tgt_num_cache;
+                                
+                        PRINTF("    * <TGT> UPDT_WORD DATA\n");
+                        PRINTF("    * <TGT> num_cache        : %d\n",tgt_num_cache);
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                        if (generate_log_transaction_file_tgt)
+                          {
+                            log_transaction_file_tgt
+                              << "[" << m_cpt_total_cycles << "] "
+                              << "UPT DATA   "
+                              << std::hex
+                              << " L " << std::setw(10) << (blob_t)tgt_addr
+                              << std::dec
+                              << " - " << tgt_num_cache
+                              << std::endl;
+                          }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                      }
+                    else
+                      {
+                        m_cpt_cc_update_icache++;
+                        r_tgt_update_data = false;
+
+                        uint32_t tgt_num_cpu   = p_vci_tgt.pktid.read();
+                        uint32_t tgt_num_cache = get_num_icache(tgt_iaddr,tgt_num_cpu);
+                        r_tgt_num_cache = tgt_num_cache;
+                                
+                        PRINTF("    * <TGT> UPDT_WORD INSTRUCTION\n");
+                        PRINTF("    * <TGT> num_cache        : %d\n",tgt_num_cache);
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                        if (generate_log_transaction_file_tgt)
+                          {
+                            log_transaction_file_tgt
+                              << "[" << m_cpt_total_cycles << "] "
+                              << "UPT INS    "
+                              << std::hex
+                              << " L " << std::setw(10) << (blob_t)tgt_addr
+                              << std::dec
+                              << " - " << tgt_num_cache
+                              << std::endl;
+                          }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                      }
+                    r_tgt_update = true; 
+                    r_vci_tgt_fsm = TGT_UPDT_WORD;
+                  } 
+
+              } // end if address
+                    
+            r_tgt_iaddr      = tgt_iaddr;
+            r_tgt_daddr      = tgt_daddr;
+            PRINTF("    * <TGT> address (after)  : i %llx, d %llx\n",(blob_t)tgt_iaddr,(blob_t)tgt_daddr);
+
+          } // end if cmdval
+        break;
+
+      case TGT_UPDT_WORD:
+        if (p_vci_tgt.cmdval.read()) 
+          {
+            if ( p_vci_tgt.eop.read() ) 
+              {
+                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                exit(0);
+              }
+            for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_be[i] = 0;
+            r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
+#ifdef COHERENCE_DEBUG
+            std::cout << "PROC " << m_srcid_rw << " update, line : " << std::hex << r_tgt_daddr.read() << " word : " << p_vci_tgt.wdata.read() << std::dec << std::endl;
+#endif
+            r_vci_tgt_fsm = TGT_UPDT_DATA;
+          }
+        break;
+
+      case TGT_UPDT_DATA:
+        if (p_vci_tgt.cmdval.read()) 
+          {
+            size_t word = r_tgt_word.read();
+            if ( word >= m_cache_words ) 
+              {
+                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
+                exit(0);
+              }
+#ifdef COHERENCE_DEBUG
+            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();
+
+            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;
+              } else {
+                r_vci_tgt_fsm = TGT_REQ_ICACHE;
+              }
+            }
+          }
+        break;
+
+      case TGT_REQ_BROADCAST:
+        {
+          bool tgt_icache_req;
+
+#if   (CC_XCACHE_WRAPPER_MULTI_CACHE==1)
+          tgt_icache_req = r_tgt_icache_req[r_tgt_num_cache].read();
+#elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2)
+          tgt_icache_req = false;
+          for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+            tgt_icache_req |= r_tgt_icache_req[num_cache].read();
+#endif
+          if (not tgt_icache_req and not r_tgt_dcache_req[r_tgt_num_cache].read()) 
+            {
+              r_vci_tgt_fsm = TGT_RSP_BROADCAST; 
+
+#if   (CC_XCACHE_WRAPPER_MULTI_CACHE==1)
+              r_tgt_icache_req[r_tgt_num_cache] = true;
+#elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2)
+              for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+                r_tgt_icache_req[      num_cache] = true;
+#endif
+
+              r_tgt_dcache_req[r_tgt_num_cache] = true;
+            }
+        }
+        break;
+        ////////////////////
+      case TGT_REQ_ICACHE:
+        {
+          // Request treated by the icache
+          if ( not r_tgt_icache_req[r_tgt_num_cache].read() ) 
+            {
+              r_vci_tgt_fsm = TGT_RSP_ICACHE; 
+              r_tgt_icache_req[r_tgt_num_cache] = true;
+            }
+          break;
+        }
+
+      case TGT_REQ_DCACHE:
+        {
+          // Request treated by the dcache
+
+          if ( not r_tgt_dcache_req[r_tgt_num_cache].read() ) 
+            {
+              r_vci_tgt_fsm = TGT_RSP_DCACHE; 
+              r_tgt_dcache_req[r_tgt_num_cache] = true;
+            }
+          break;
+        }
+      case TGT_RSP_BROADCAST:
+        {
+          PRINTF("      * <TGT> dcache[%d] : %d - %d\n",(uint32_t)r_tgt_num_cache, (uint32_t)r_tgt_dcache_req[r_tgt_num_cache].read(),(uint32_t)r_tgt_dcache_rsp[r_tgt_num_cache].read());
+          for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+            PRINTF("      * <TGT> icache[%d] : %d - %d\n",(uint32_t)num_cache, (uint32_t)r_tgt_icache_req[num_cache].read(),(uint32_t)r_tgt_icache_rsp[num_cache].read());
+
+          bool tgt_icache_req;
+                    
+#if   (CC_XCACHE_WRAPPER_MULTI_CACHE==1)
+          tgt_icache_req = r_tgt_icache_req[r_tgt_num_cache].read();
+#elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2)
+          tgt_icache_req = false;
+          for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+            tgt_icache_req |= r_tgt_icache_req[num_cache].read();
+#endif
+          if (not tgt_icache_req and not r_tgt_dcache_req[r_tgt_num_cache].read()) 
+            {
+              bool     tgt_icache_rsp;
+              uint32_t tgt_icache_rsp_num_cache;
+                        
+#if   (CC_XCACHE_WRAPPER_MULTI_CACHE==1)
+              tgt_icache_rsp_num_cache = r_tgt_num_cache;
+              tgt_icache_rsp = r_tgt_icache_rsp[r_tgt_num_cache].read();
+#elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2)
+              tgt_icache_rsp_num_cache = 0;
+              for (;tgt_icache_rsp_num_cache<m_nb_icache; ++tgt_icache_rsp_num_cache)
+                {
+                  PRINTF("      * <TGT> icache[%d] : %d\n",(uint32_t)tgt_icache_rsp_num_cache, (uint32_t)r_tgt_icache_rsp[tgt_icache_rsp_num_cache].read());
+                            
+                  if (r_tgt_icache_rsp[tgt_icache_rsp_num_cache].read())
+                    break;
+                }
+
+              tgt_icache_rsp = (tgt_icache_rsp_num_cache<m_nb_icache);
+#endif
+
+              PRINTF("      * <TGT> icache_rsp [%d] : %d\n",tgt_icache_rsp_num_cache,(uint32_t) tgt_icache_rsp);
+              PRINTF("      * <TGT> dcache_rsp [%d] : %d\n",(uint32_t)r_tgt_num_cache,(uint32_t) r_tgt_dcache_rsp[r_tgt_num_cache]);
+
+              if (tgt_icache_rsp or r_tgt_dcache_rsp[r_tgt_num_cache])
+                {
+                  // Have send one response
+                  if ( p_vci_tgt.rspack.read())
+                    {
+                      // reset dcache if activated
+                      if (r_tgt_dcache_rsp[r_tgt_num_cache])
+                        r_tgt_dcache_rsp[r_tgt_num_cache] = false;
+                      else
+                        // reset one icache
+                        r_tgt_icache_rsp[tgt_icache_rsp_num_cache] = false;
+                    }
+                }
+
+              // // one response
+              // if ( not r_tgt_icache_rsp[r_tgt_num_cache] or not r_tgt_dcache_rsp[r_tgt_num_cache] )
+              // {
+              //     if ( p_vci_tgt.rspack.read() )
+              //     {
+              //         r_vci_tgt_fsm = TGT_IDLE; 
+              //         r_tgt_icache_rsp[r_tgt_num_cache] = false;
+              //         r_tgt_dcache_rsp[r_tgt_num_cache] = false;
+              //     }
+              // }
+                        
+              // // if data and instruction have the inval line, need two responses  
+              // if ( r_tgt_icache_rsp[r_tgt_num_cache] and r_tgt_dcache_rsp[r_tgt_num_cache] )
+              // {
+              //     if ( p_vci_tgt.rspack.read() )
+              //     {
+              //         r_tgt_icache_rsp[r_tgt_num_cache] = false; // only reset one for respond the second time 
+              //     }
+              // }
+
+              PRINTF("      * <TGT> icache_rsp    : %d\n",(uint32_t) r_tgt_icache_rsp[r_tgt_num_cache]);
+              PRINTF("      * <TGT> dcache_rsp[%d] : %d\n",(uint32_t)r_tgt_num_cache,(uint32_t)r_tgt_dcache_rsp[r_tgt_num_cache].read());
+              // if there is no need for a response
+              if (not tgt_icache_rsp and not r_tgt_dcache_rsp[r_tgt_num_cache] )
+                {
+                  r_vci_tgt_fsm = TGT_IDLE;
+                }
+                        
+            }
+          break;
+        }
+        ////////////////////
+      case TGT_RSP_ICACHE:
+        {
+          bool transaction_rsp = (p_vci_tgt.rspack.read() or not r_tgt_icache_rsp[r_tgt_num_cache].read()) and not r_tgt_icache_req[r_tgt_num_cache].read();
+
+          PRINTF("      * <TGT> RSP_ICACHE : transaction : %d ((%d or not %d) and not %d)\n",transaction_rsp
+                 ,(int)p_vci_tgt.rspack.read()
+                 ,(int)r_tgt_icache_rsp[r_tgt_num_cache].read()
+                 ,(int)r_tgt_icache_req[r_tgt_num_cache].read()
+                 );
+
+          if (transaction_rsp) 
+            {
+              r_vci_tgt_fsm = TGT_IDLE;
+              r_tgt_icache_rsp[r_tgt_num_cache] = false; 
+            }
+          break;
+        }
+
+      case TGT_RSP_DCACHE:
+        {
+          bool transaction_rsp = (p_vci_tgt.rspack.read() or not r_tgt_dcache_rsp[r_tgt_num_cache].read()) and not r_tgt_dcache_req[r_tgt_num_cache].read();
+
+          PRINTF("      * <TGT> RSP_DCACHE : transaction : %d\n",transaction_rsp);
+
+          if (transaction_rsp) 
+            {
+              r_vci_tgt_fsm = TGT_IDLE;
+              r_tgt_dcache_rsp[r_tgt_num_cache] = false; 
+            }
+          break;
+        }
+      } // end switch TGT_FSM
+
+        /////////////////////////////////////////////////////////////////////
+        // Interface between CPU and CACHE FSM
+        ///////////////////////////////////////////////////////////////////////
+
+      uint32_t ireq_num_cache [m_nb_cpu];
+      uint32_t dreq_num_cache [m_nb_cpu];
+      bool     have_sync = false;
+
+      {
+        typename iss_t::InstructionRequest _ireq = ISS_IREQ_INITIALIZER;
+        typename iss_t::DataRequest        _dreq = ISS_DREQ_INITIALIZER;
+
+        for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+          {
+            ireq [num_cache] = _ireq;
+            //irsp [num_cache] = _irsp;
+          }
+        for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+          {
+            dreq [num_cache] = _dreq;
+            //drsp [num_cache] = _drsp;
+                
+            have_sync |= r_dcache_sync [num_cache];
+          }
+      }
+
+      for (uint32_t _num_cpu=0; _num_cpu<m_nb_cpu; ++_num_cpu)
+        {
+          // round robin priority
+          uint32_t num_cpu = (r_cpu_prior+_num_cpu)%m_nb_cpu;
+
+          typename iss_t::InstructionRequest _ireq = ISS_IREQ_INITIALIZER;
+          typename iss_t::DataRequest        _dreq = ISS_DREQ_INITIALIZER;
+            
+          m_iss[num_cpu]->getRequests(_ireq, _dreq);
+
+          addr_40  addr;
+          uint32_t num_cache;
+
+          addr      = (addr_40)_ireq.addr;
+          num_cache = get_num_icache(addr,num_cpu);
+
+          bool icache_req_valid = ((not ireq[num_cache].valid and               // no previous request in this cycle
+                                    (r_icache_lock [num_cache] == m_nb_cpu)) or // no previous request in previous cycle
+                                   (r_icache_lock [num_cache] == num_cpu));     // previous request in previous cycle by this cpu
+
+          if (icache_req_valid)
+            {
+              bool valid = _ireq.valid;
+
+              if (valid)
+                {
+                  PRINTF("    * <CPU2CACHE> ICACHE :    Transaction between cpu %d and cache %d (lock)\n",num_cpu,num_cache);
+                  ireq_num_cache [num_cpu  ] = num_cache;
+                  r_icache_lock [num_cache] = num_cpu;
+                }
+              else
+                {
+                  PRINTF("    * <CPU2CACHE> ICACHE : No Transaction between cpu %d and cache %d : invalid\n",num_cpu,num_cache);
+                  ireq_num_cache [num_cpu] = m_nb_icache;
+                }
+
+              ireq_cached    [num_cache] = m_cacheability_table[(vci_addr_t)_ireq.addr];
+              ireq_num_cpu   [num_cache] = num_cpu;
+              ireq           [num_cache] = _ireq;
+              ireq           [num_cache].addr = addr;
+            }
+          else
+            {
+              PRINTF("    * <CPU2CACHE> ICACHE : No transaction (cpu %d)\n",num_cpu);
+
+              ireq_num_cache [num_cpu] = m_nb_icache;
+            }
+
+          addr      = (addr_40)_dreq.addr;
+          num_cache = get_num_dcache(addr);
+            
+
+          bool dcache_no_lock      = (r_dcache_lock [num_cache] == m_nb_cpu);
+          bool dcache_lock_owner   = (r_dcache_lock [num_cache] == num_cpu);
+#if CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS
+          bool dcache_lock_no_owner= not dcache_no_lock and not dcache_lock_owner;
+          bool dcache_wait         = ((r_dcache_fsm[num_cache] == DCACHE_MISS_WAIT)//  or
+                                      // (r_dcache_fsm[num_cache] == DCACHE_UNC_WAIT) or
+                                      // (r_dcache_fsm[num_cache] == DCACHE_SC_WAIT)
+                                      );
+
+          bool dcache_req_valid = ((not dreq[num_cache].valid and               // no previous request in this cycle
+                                    not have_sync and                           // no sync instruction
+                                    (dcache_no_lock or
+                                     (dcache_lock_no_owner and dcache_wait))) or // no previous request in previous cycle
+                                   (dcache_lock_owner and not dcache_wait));     // previous request in previous cycle by this cpu
+#else
+          bool dcache_req_valid = ((not dreq[num_cache].valid and // no previous request in this cycle
+                                    not have_sync and             // no sync instruction
+                                    dcache_no_lock) or            // no previous request in previous cycle
+                                   dcache_lock_owner);            // previous request in previous cycle by this cpu
+#endif
+
+          // test if already used
+          if (dcache_req_valid)
+            {
+              bool valid = _dreq.valid;
+
+              if (valid)
+                {
+                  PRINTF("    * <CPU2CACHE> DCACHE :    Transaction between cpu %d and cache %d (lock)\n",num_cpu,num_cache);
+                  dreq_num_cache [num_cpu  ] = num_cache;
+
+#if CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS
+                  if (not dcache_lock_no_owner)
+#endif
+                    r_dcache_lock [num_cache] = num_cpu;
+                }
+              else
+                {
+                  PRINTF("    * <CPU2CACHE> DCACHE : No Transaction between cpu %d and cache %d : invalid\n",num_cpu,num_cache);
+                  dreq_num_cache [num_cpu] = m_nb_dcache;
+                }
+
+              dreq_cached    [num_cache] = m_cacheability_table[(vci_addr_t)_dreq.addr];
+              dreq_num_cpu   [num_cache] = num_cpu;
+              dreq           [num_cache] = _dreq;
+              dreq           [num_cache].addr = addr;
+            }
+          else
+            {
+              PRINTF("    * <CPU2CACHE> DCACHE : No transaction (cpu %d)\n",num_cpu);
+
+              dreq_num_cache [num_cpu] = m_nb_dcache;
+            }
+
+
+#if CC_XCACHE_WRAPPER_DEBUG
+          if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
+            {
+              std::cout << "    * <CPU2CACHE> Instruction Request   : " << ireq_num_cache[num_cpu] << " - " << _ireq << std::endl
+                        << "    * <CPU2CACHE> Data        Request   : " << dreq_num_cache[num_cpu] << " - " << _dreq << std::endl;
+            }
+#endif
+        }
+
+      // round robin priority
+      r_cpu_prior = (r_cpu_prior+1)%m_nb_cpu;
+
+      /////////////////////////////////////////////////////////////////////
+      // The ICACHE FSM controls the following ressources:
+      // - r_icache_fsm
+      // - r_icache_fsm_save
+      // - r_icache instruction cache access
+      // - r_icache_addr_save
+      // - r_icache_miss_req set
+      // - 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
+      // - ireq & irsp structures for communication with the processor
+      //
+      // 1/ External requests (update or invalidate) have highest priority.
+      //    They are taken into account in the IDLE and WAIT states.
+      //    As external hit should be extremly rare on the ICACHE,
+      //    all external requests are handled as invalidate...
+      //    In case of external request the ICACHE FSM goes to the CC_CHECK
+      //    state to test the external hit, and returns in the
+      //    pre-empted state after completion.
+      // 2/ Processor requests are taken into account only in the IDLE state.
+      //    In case of MISS, or in case of uncached instruction, the FSM 
+      //    writes the missing address line in the  r_icache_addr_save register 
+      //    and sets the r_icache_miss_req or the r_icache_unc_req flip-flops.
+      //    These request flip-flops are reset by the VCI_RSP FSM
+      //    when the VCI transaction is completed and the r_icache_buf_unc_valid
+      //    is set in case of uncached access.
+      //    In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 
+      //    flip-flop. It is reset by the ICACHE FSM.
+      ///////////////////////////////////////////////////////////////////////
+        
+      for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+        {
+          typename iss_t::InstructionRequest  _ireq = ireq [num_cache];
+          typename iss_t::InstructionResponse _irsp = ISS_IRSP_INITIALIZER;
+
+          switch(r_icache_fsm[num_cache]) {
+            /////////////////
+          case ICACHE_IDLE:
+            {
+              if ( r_tgt_icache_req[num_cache] ) {   // external request
+                // if ( _ireq.valid ) m_cost_ins_miss_frz++;
+                r_icache_fsm     [num_cache] = ICACHE_CC_CHECK;
+                r_icache_fsm_save[num_cache] = r_icache_fsm[num_cache];
+                break;
+              } 
+              if ( _ireq.valid ) {
+                data_t   icache_ins         = 0;
+                bool     icache_hit         = false;
+                bool     icache_cached      = ireq_cached  [num_cache];
+                // uint32_t icache_num_cpu     = ireq_num_cpu [num_cache];
+                bool     icache_cleanup_hit = r_icache_cleanup_req[num_cache] and (((addr_40)_ireq.addr >> (addr_40)m_icache_words_shift) == r_icache_cleanup_line[num_cache].read());
+
+                // icache_hit & icache_ins evaluation
+                if ( icache_cached ) {
+                  icache_hit = r_icache[num_cache]->read((vci_addr_t) _ireq.addr, &icache_ins);
+                } else {
+                  // if uncache, again in the icache_miss_buf
+                  icache_hit = (r_icache_buf_unc_valid[num_cache] and ((addr_40) _ireq.addr == (addr_40)r_icache_addr_save[num_cache]));
+                  icache_ins = CACHE_MISS_BUF_RSP_DATA(i,num_cache,0);
+
+                  if (icache_hit)
+                    CACHE_MISS_BUF_RSP_POP(i,num_cache);
+                }
+
+                PRINTF("    * <ICACHE [%d]> hit %d - cached %d - cleanup_hit %d\n",num_cache, icache_hit, icache_cached, icache_cleanup_hit);
+
+                if (icache_hit and icache_cleanup_hit)
+                  {
+                    PRINTF("    * <ICACHE [%d]> Warning : icache hit and icache_cleanup_hit\n",num_cache);
+                    icache_hit = false;
+                  }
+                else
+                  {
+                    if ( not icache_hit and not icache_cleanup_hit) 
+                      {
+                              
+                        m_cpt_ins_miss++;
+                        m_cost_ins_miss_frz++;
+                                
+                        r_icache_addr_save[num_cache] = (addr_40) _ireq.addr;
+
+                        if ( icache_cached )
+                          {
+                            // to prevent deadlock, miss victim don't be block
+                            if (not r_icache_cleanup_req[num_cache])
+                              {
+                                CACHE_MISS_BUF_REQ_INIT(i,num_cache);
+                                r_icache_fsm     [num_cache] = ICACHE_MISS_VICTIM;
+                                r_icache_miss_req[num_cache] = true;
+                              }
+                            else
+                              m_cpt_icache_miss_victim_wait [num_cache] ++;
+                          }
+                        else
+                          {
+                            CACHE_MISS_BUF_REQ_INIT(i,num_cache);
+                            r_icache_addr_save[num_cache] = (addr_40) _ireq.addr;
+
+                            r_icache_fsm    [num_cache] = ICACHE_UNC_WAIT;
+                            r_icache_unc_req[num_cache] = true;
+                          }
+                      }
+                    else
+                      {
+                        //     icache_hit and not icache_cleanup_hit
+                        // not icache_hit and     icache_cleanup_hit
+
+                        // request accepted, inval the buf unc
+
+                        r_icache_buf_unc_valid[num_cache] = false;
+                      }
+                    m_cpt_icache_dir_read += m_icache_ways;
+                    m_cpt_icache_data_read += m_icache_ways;
+                  }
+
+                _irsp.valid          = icache_hit;
+                _irsp.instruction    = icache_ins;
+              }
+              break;
+            }
+            //////////////////////
+          case ICACHE_MISS_VICTIM:
+            {
+              // if (not r_icache_cleanup_req[num_cache])
+              {
+                size_t     way;
+                size_t     set;
+                vci_addr_t addr = (vci_addr_t) r_icache_addr_save[num_cache].read();
+                vci_addr_t victim;
+                        
+                r_icache_cleanup_req [num_cache] = r_icache[num_cache]->victim_select(addr, &victim, &way, &set );
+                r_icache_cleanup_line[num_cache] = (addr_40) victim;
+                r_icache_miss_way    [num_cache] = way;
+                r_icache_miss_set    [num_cache] = set;
+                        
+                r_icache_fsm         [num_cache] = ICACHE_MISS_WAIT;
+              }
+              break;
+            }
+            //////////////////////
+          case ICACHE_MISS_WAIT:
+            {
+              m_cost_ins_miss_frz++;
+              if ( r_tgt_icache_req[num_cache] ) {   // external request
+                r_icache_fsm      [num_cache] = ICACHE_CC_CHECK;
+                r_icache_fsm_save [num_cache] = r_icache_fsm[num_cache].read();
+                break;
+              }
+
+              bool val = CACHE_MISS_BUF_RSP_VAL(i,num_cache,0);
+
+              PRINTF("    * <ICACHE [%d]> val                  : %d\n",num_cache,val);
+
+              if (val)
+                {
+                  PRINTF("    * <ICACHE [%d]> r_icache_inval_rsp   : %d\n",num_cache,(int) r_icache_inval_rsp  [num_cache]);
+                  PRINTF("    * <ICACHE [%d]> r_vci_rsp_ins_error  : %d\n",num_cache,(int) r_vci_rsp_ins_error [num_cache]);
+                  PRINTF("    * <ICACHE [%d]> r_icache_cleanup_req : %d\n",num_cache,(int) r_icache_cleanup_req[num_cache]);
+
+                  // Miss read response and no invalidation
+                  if ( r_vci_rsp_ins_error [num_cache]) {
+                    r_icache_fsm[num_cache] = ICACHE_ERROR;
+                  } else {
+                    r_icache_update_addr[num_cache] = 0;
+                    r_icache_fsm        [num_cache] = ICACHE_MISS_UPDT;
+                  }
+                }
+              break;
+            }
+            /////////////////////
+          case ICACHE_UNC_WAIT:
+            {
+              m_cost_ins_miss_frz++;
+              if ( r_tgt_icache_req[num_cache] ) {   // external request
+                r_icache_fsm     [num_cache] = ICACHE_CC_CHECK;
+                r_icache_fsm_save[num_cache] = r_icache_fsm[num_cache].read();
+                break;
+              }
+
+              bool ok = CACHE_MISS_BUF_RSP_VAL(i,num_cache,0);
+
+              PRINTF("    * <ICACHE [%d]> ok                   : %d\n",num_cache,ok);
+              PRINTF("    * <ICACHE [%d]> error                : %d\n",num_cache,(uint32_t)r_vci_rsp_ins_error [num_cache]);
+
+              if (ok)
+                {
+                  if ( r_vci_rsp_ins_error [num_cache]) {
+                    r_icache_fsm[num_cache] = ICACHE_ERROR;
+                  } else {
+                    r_icache_fsm [num_cache] = ICACHE_IDLE;
+                    r_icache_buf_unc_valid[num_cache] = true;
+                  }
+                }
+              break;
+            }
+            //////////////////
+          case ICACHE_ERROR:
+            {
+              if ( (addr_40)_ireq.addr == (addr_40)r_icache_addr_save[num_cache] ) {
+                _irsp.error          = true;
+                _irsp.valid          = true;
+              }
+              r_icache_fsm        [num_cache] = ICACHE_IDLE;
+              r_vci_rsp_ins_error [num_cache] = false;
+              break;
+            }
+            //////////////////////
+          case ICACHE_MISS_UPDT: 
+            {
+              size_t     word =              r_icache_update_addr[num_cache].read();
+              vci_addr_t addr = (vci_addr_t) r_icache_addr_save  [num_cache].read();
+              size_t     way  = r_icache_miss_way[num_cache].read();
+              size_t     set  = r_icache_miss_set[num_cache].read();
+
+              bool val = CACHE_MISS_BUF_RSP_VAL(i,num_cache,word);
+
+              if (val)
+                {
+                  PRINTF("    * <ICACHE [%d]> rsp_val            : %d/%d\n",num_cache,(int)r_icache_update_addr[num_cache],(int)m_icache_words);
+                  PRINTF("    * <ICACHE [%d]> r_icache_inval_rsp : %d\n"   ,num_cache,(int)r_icache_inval_rsp[num_cache]);
+                  PRINTF("    * <ICACHE [%d]> ins                : %x\n"   ,num_cache,(int)CACHE_MISS_BUF_RSP_DATA(i,num_cache,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[num_cache])
+                    r_icache[num_cache]->write(way, set, word, CACHE_MISS_BUF_RSP_DATA(i,num_cache,word));
+
+                  CACHE_MISS_BUF_RSP_POP(i,num_cache);
+
+                  r_icache_update_addr[num_cache] = ++word;
+                            
+                  // if last word, finish the update
+                  if (word >= m_icache_words)
+                    {
+                      // in all case (inval_rsp or not), update the victim tag
+                      r_icache[num_cache]->victim_update_tag(addr, way, set);
+
+                      // Last word : if previous invalid_rsp, can cleanup, else update the TAG
+                      if (r_icache_inval_rsp[num_cache])
+                        {
+                          r_icache_inval_rsp[num_cache] = false;
+                          r_icache_fsm      [num_cache] = ICACHE_CC_CLEANUP;
+                        }
+                      else
+                        {
+                          r_icache_fsm [num_cache] = ICACHE_IDLE;
+                        }
+                    }
+                }
+
+              break;
+            }
+            ////////////////////
+          case ICACHE_CC_CLEANUP:
+            {
+              // cleanup
+              if(not r_icache_cleanup_req[num_cache]){
+                r_icache_cleanup_req [num_cache] = true;
+                r_icache_cleanup_line[num_cache] = r_icache_addr_save[num_cache].read() >> m_icache_words_shift;
+                r_icache_fsm         [num_cache] = ICACHE_IDLE;
+
+                m_cpt_icache_dir_read += m_icache_ways;
+                r_icache[num_cache]->inval((addr_40)r_icache_addr_save[num_cache]);
+              }
+              break;
+            }
+            /////////////////////
+          case ICACHE_CC_CHECK:   // read directory in case of invalidate or update request
+            {
+
+              m_cpt_icache_dir_read  += m_icache_ways;
+              m_cpt_icache_data_read += m_icache_ways;
+              addr_40 ad = r_tgt_iaddr;
+              data_t  icache_rdata = 0;
+
+              PRINTF("    * <ICACHE [%d]> CC_CHECK\n",num_cache);
+
+              if((r_icache_fsm_save[num_cache] == ICACHE_MISS_WAIT) and 
+                 ((r_icache_addr_save[num_cache].read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) {
+                PRINTF("    * <ICACHE [%d]> have request, need inval rsp\n",num_cache);
+
+                r_icache_inval_rsp[num_cache] = true;
+                r_tgt_icache_req  [num_cache] = false;
+                if(r_tgt_update){    // Also send a cleanup and answer
+                  PRINTF("    * <ICACHE [%d]> send a cleanup and answer\n",num_cache);
+                  r_tgt_icache_rsp[num_cache] = true;
+                } else {            // Also send a cleanup but don't answer
+                  PRINTF("    * <ICACHE [%d]> send a cleanup and but don't answer\n",num_cache);
+                  r_tgt_icache_rsp[num_cache] = false;
+                }
+                r_icache_fsm[num_cache] = r_icache_fsm_save[num_cache];
+              } else {
+                bool    icache_hit   = r_icache[num_cache]->read(ad, &icache_rdata);
+
+                PRINTF("    * <ICACHE [%d]> have no request, hit cache : %d\n",num_cache,icache_hit);
+
+                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[num_cache]->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[num_cache] = 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[num_cache] = ICACHE_CC_UPDT;
+                    // complete the line buffer in case of update
+                    for(size_t i=0; i<m_icache_words; i++){
+                      data_t rdata = 0;
+                      r_icache[num_cache]->read(ad + i*4,&rdata);
+                      data_t mask = vci_param::be2mask(r_tgt_be[i]);
+                      r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata);
+                    }
+#endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                  } else if ( icache_hit and not r_tgt_update) {
+                  r_icache_fsm[num_cache] = ICACHE_CC_INVAL;
+                } else { // instruction not found (can happen)
+                  r_tgt_icache_req[num_cache] = false;
+                  if(r_tgt_update){
+                    r_tgt_icache_rsp[num_cache] = true;
+                  } else {
+                    r_tgt_icache_rsp[num_cache] = false;
+                  }
+                  r_icache_fsm[num_cache] = r_icache_fsm_save[num_cache];
+                }
+              }
+              break;
+            }
+            /////////////////////
+          case ICACHE_CC_INVAL:  
+            {                       
+              addr_40 ad  = r_tgt_iaddr;
+              // if ( _ireq.valid ) m_cost_ins_miss_frz++;
+              m_cpt_icache_dir_read += m_icache_ways;
+              r_tgt_icache_rsp[num_cache] = true;
+              r_icache[num_cache]->inval(ad);
+              r_tgt_icache_req[num_cache] = false;
+              r_icache_fsm    [num_cache] = r_icache_fsm_save[num_cache];
+              break;
+            }    
+            /////////////////////
+          case ICACHE_CC_UPDT:
+            {                       
+              addr_40 ad = r_tgt_iaddr.read();
+              m_cpt_icache_dir_write++;
+              m_cpt_icache_data_write++;
+
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+              uint32_t word  = r_cache_word;
+
+              if(r_tgt_be[word])
+                r_icache[num_cache]->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[num_cache] = false;
+                  r_tgt_icache_rsp[num_cache] = true;
+                  r_icache_fsm    [num_cache] = r_icache_fsm_save[num_cache].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++){
+                if(r_tgt_be[i]) r_icache[num_cache]->write( ad + i*4, buf[i]);
+              }
+              r_tgt_icache_req [num_cache] = false;
+              r_tgt_icache_rsp [num_cache] = true;
+              r_icache_fsm     [num_cache] = r_icache_fsm_save[num_cache].read();
+#endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+
+              break;
+            }    
+
+          }// end switch r_icache_fsm
+
+          irsp [num_cache] = _irsp;
+          if (_ireq.valid and _irsp.valid)
+            {
+              PRINTF("    * <CPU2CACHE> Transaction between cpu %d and Icache %d (unlock)\n",r_icache_lock [num_cache].read(),num_cache);
+
+              r_icache_lock       [num_cache] = m_nb_cpu;
+              m_cpt_icache_access [num_cache] ++;
+            }
+
+        }// end for num_cache
+
+      //////////////////////////////////////////////////////////////////////://///////////
+      // The DCACHE FSM controls the following ressources:
+      // - r_dcache_fsm
+      // - r_dcache_fsm_save
+      // - r_dcache (data cache access)
+      // - r_dcache_addr_save
+      // - r_dcache_wdata_save
+      // - r_dcache_rdata_save
+      // - r_dcache_type_save
+      // - r_dcache_be_save
+      // - r_dcache_cached_save
+      // - r_dcache_miss_req set
+      // - r_dcache_unc_req set
+      // - r_dcache_cleanup_req set
+      // - r_vci_rsp_data_error reset
+      // - r_tgt_dcache_req reset
+      // - r_wbuf write
+      // - dreq & drsp structures for communication with the processor
+      //
+      // 1/ EXTERNAL REQUEST : 
+      //    There is an external request when the tgt_dcache req flip-flop is set,
+      //    requesting a line invalidation or a line update. 
+      //    External requests are taken into account in the states  IDLE, WRITE_REQ,  
+      //    UNC_WAIT, MISS_WAIT, and have the highest priority :
+      //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
+      //    goes to the CC_CHECK state to execute the requested action, and returns to the
+      //    pre-empted state.
+      //  2/ PROCESSOR REQUEST : 
+      //   In order to support VCI write burst, the processor requests are taken into account
+      //   in the WRITE_REQ state as well as in the IDLE state.
+      //   - In the IDLE state, the processor request cannot be satisfied if
+      //   there is a cached read miss, or an uncached read.
+      //   - In the WRITE_REQ state, the request cannot be satisfied if
+      //   there is a cached read miss, or an uncached read,
+      //   or when the write buffer is full.
+      //   - In all other states, the processor request is not satisfied.
+      //
+      //   The cache access takes into account the cacheability_table.
+      //   In case of processor request, there is five conditions to exit the IDLE state:
+      //   - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal), 
+      //     then to the MISS_UPDT state, and finally to the IDLE state.
+      //   - UNCACHED READ  => to the UNC_WAIT state (waiting the r_miss_ok signal), 
+      //     and to the IDLE state.
+      //   - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state.
+      //   - WRITE MISS => directly to the WRITE_REQ state to access the write buffer.
+      //   - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state.
+      //
+      // Error handling :  Read Bus Errors are synchronous events, but
+      // Write Bus Errors are asynchronous events (processor is not frozen).
+      // - If a Read Bus Error is detected, the VCI_RSP FSM sets the
+      //   r_vci_rsp_data_error flip-flop, and the synchronous error is signaled
+      //   by the DCACHE FSM.
+      // - If a Write Bus Error is detected, the VCI_RSP FSM  signals
+      //   the asynchronous error using the setWriteBerr() method.
+      ///////////////////////////////////////////////////////////////////////////////////
+
+      for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+        {
+          typename iss_t::DataRequest  _dreq = dreq [num_cache];
+          typename iss_t::DataResponse _drsp = ISS_DRSP_INITIALIZER;
+
+          switch ( r_dcache_fsm[num_cache]) {
+
+            /////////////////
+          case DCACHE_IDLE:
+            {
+              if ( r_tgt_dcache_req[num_cache]) {   // external request
+                r_dcache_fsm     [num_cache] = DCACHE_CC_CHECK;
+                r_dcache_fsm_save[num_cache] = r_dcache_fsm[num_cache];
+                break;
+              } 
+
+              if ( _dreq.valid ) {
+                PRINTF("    * <DCACHE [%d]> Have dreq\n",num_cache);
+
+                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      = dreq_cached  [num_cache];
+                uint32_t    dcache_num_cpu     = dreq_num_cpu [num_cache];
+                bool        dcache_hit         = r_dcache[num_cache]->read((vci_addr_t) _dreq.addr, &dcache_rdata);
+                bool        dcache_cleanup_hit = r_dcache_cleanup_req[num_cache] and (((addr_40)_dreq.addr >> (addr_40)m_dcache_words_shift) == r_dcache_cleanup_line[num_cache].read());
+
+                PRINTF("    * <DCACHE [%d]> hit %d - cached %d - cleanup_hit %d\n",num_cache,dcache_hit, dcache_cached, dcache_cleanup_hit);
+                        
+                m_cpt_dcache_data_read += m_dcache_ways;
+                m_cpt_dcache_dir_read  += m_dcache_ways;
+
+                switch( _dreq.type ) {
+                case iss_t::DATA_READ:
+                case iss_t::DATA_LL:
+                  {
+                    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 [num_cache] = 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 [%d]> ll_valid = true\n",num_cache);
+
+                            r_dcache_ll_valid  [num_cache][dcache_num_cpu] = true;
+                            r_dcache_ll_data   [num_cache][dcache_num_cpu] = dcache_rdata;
+                            r_dcache_ll_addr   [num_cache][dcache_num_cpu] = (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[num_cache]->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)
+                          {
+                                                
+                            // Miss : send signal at the CMD_FSM (via r_dcache_miss_req or r_dcache_unc_req)
+                            if ( dcache_cached ) {
+                              // to prevent deadlock, miss victim don't be block
+                              if (not r_dcache_cleanup_req[num_cache].read())
+                                {
+                                  CACHE_MISS_BUF_REQ_INIT(d,num_cache);
+                                                        
+                                  m_cpt_data_read_miss++;
+                                  m_cost_data_miss_frz++;
+                                  r_dcache_miss_req [num_cache] = true;
+                                  r_dcache_fsm [num_cache] = DCACHE_MISS_VICTIM;
+                                }
+                              else
+                                m_cpt_icache_miss_victim_wait [num_cache] ++;
+                            } else {
+                              if (not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access
+                                {
+                                  CACHE_MISS_BUF_REQ_INIT(d,num_cache);
+
+                                  r_dcache_previous_unc[num_cache] = true;
+                                                        
+                                  m_cpt_data_read_uncached++;
+                                  m_cost_unc_read_frz++;
+                                  r_dcache_unc_req[num_cache] = true;
+                                  r_dcache_fsm    [num_cache] = DCACHE_UNC_WAIT;
+                                }
+                            }
+                          }
+                      }
+                  }
+                  break;
+                case iss_t::DATA_SC:
+                  {
+                    PRINTF("    * <DCACHE [%d]> DATA_SC - ll_valid = %d, num_cpu = %d\n",num_cache,r_dcache_ll_valid[num_cache][dcache_num_cpu].read(),dcache_num_cpu);
+
+                    if (not r_dcache_previous_unc[num_cache].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[num_cache][dcache_num_cpu].read() and 
+                            (r_dcache_ll_addr [num_cache][dcache_num_cpu].read() == (vci_addr_t)_dreq.addr)){
+                          PRINTF("    * <DCACHE [%d]> have previous load linked\n",num_cache);
+                                        
+                          r_dcache_previous_unc[num_cache] = true;
+                          r_dcache_sc_req      [num_cache] = true;
+
+                          CACHE_MISS_BUF_REQ_INIT(d,num_cache);
+
+                          r_dcache_fsm         [num_cache] = DCACHE_SC_WAIT;
+                        } else {
+                          PRINTF("    * <DCACHE [%d]> don't have previous load linked\n",num_cache);
+                                        
+                          _drsp.valid = true;
+                          _drsp.rdata = 1; // SC rsp NOK
+                          r_dcache_ll_valid[num_cache][dcache_num_cpu] = false;
+                        }
+                      }
+
+                    break;
+                  }
+                case iss_t::XTN_READ:
+                case iss_t::XTN_WRITE:
+                  {
+                    bool valid = false;
+                    // only DCACHE INVALIDATE and SYNC request are supported
+                    switch (_dreq.addr>>2)
+                      {
+                      case iss_t::XTN_DCACHE_INVAL : 
+                        {
+                          valid = true;
+                          r_dcache_fsm[num_cache] = 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
+
+                          bool empty=true;
+                          for (uint32_t i=0; i<m_nb_dcache; ++i)
+                            empty &= r_wbuf[i]->empty();
+
+                          if (empty)
+                            {
+                              valid = true;
+                              r_dcache_fsm [num_cache] = DCACHE_IDLE;
+                            }
+                          else
+                            {
+                              valid = false;
+                              r_dcache_fsm [num_cache] = DCACHE_SYNC;
+                              r_dcache_sync[num_cache] = true;
+                            }
+                          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 [num_cache] = DCACHE_IDLE;
+                        }
+                      }//end switch (_dreq.addr>>2)
+
+                    _drsp.valid = valid;
+                    _drsp.rdata = 0;
+                    break;
+                  }
+                case iss_t::DATA_WRITE:
+
+                  PRINTF("    * <DCACHE [%d]> r_dcache_previous_unc : %d\n",num_cache,r_dcache_previous_unc[num_cache].read());
+
+                  if (dcache_cached or not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access
+                    {
+                      bool valid;
+                      addr_40 addr = _dreq.addr;
+                      set_num_dcache(addr,num_cache);
+
+                      // FIXME : 
+                      //  * dans le wbuf, ne pas mettre l'adresse au complet (economie de surface)
+                      //  * pour cela, virer le set_num_dcache !
+                      valid = r_wbuf[num_cache]->write(addr, _dreq.be, _dreq.wdata, dcache_cached, dcache_num_cpu);
+
+#if MWBUF_VHDL_TESTBENCH
+                      vhdl_mwbuf_port_write_val        [num_cache] = (vhdl_tb_t)1;
+                      vhdl_mwbuf_test_write_ack        [num_cache] = (vhdl_tb_t)1;
+                      vhdl_mwbuf_port_write_ack        [num_cache] = (vhdl_tb_t)valid;
+                      vhdl_mwbuf_port_write_addr       [num_cache] = (vhdl_tb_t)addr;
+                      vhdl_mwbuf_port_write_data       [num_cache] = (vhdl_tb_t)_dreq.wdata;
+                      vhdl_mwbuf_port_write_be         [num_cache] = (vhdl_tb_t)_dreq.be;
+                      vhdl_mwbuf_port_write_cached     [num_cache] = (vhdl_tb_t)dcache_cached;
+                      vhdl_mwbuf_port_write_cpu_id     [num_cache] = (vhdl_tb_t)dcache_num_cpu;
+#endif
+
+
+                      PRINTF("    * <DCACHE [%d]> r_wbuf valid          : %d\n",num_cache,valid);
+
+                      if (valid)
+                        {
+                          m_cpt_data_write++;
+                                        
+                          if (not dcache_cached)
+                            {
+                              r_dcache_previous_unc[num_cache] = true;
+                              m_cpt_data_write_uncached++;
+                            }
+                          else if (not dcache_hit)
+                            m_cpt_data_write_miss++;
+                                        
+                          if (dcache_hit) {
+                            // update data cache
+                            r_dcache_fsm[num_cache] = DCACHE_WRITE_UPDT;
+                          } else {
+                            // write accepted
+                            r_dcache_fsm [num_cache] = DCACHE_IDLE;
+                          }
+                        }
+
+                      _drsp.valid = valid;
+                      _drsp.rdata = 0;
+                    }
+                  break;
+                } // end switch _dreq.type
+
+                r_dcache_addr_save   [num_cache] = (addr_40) _dreq.addr;
+                r_dcache_type_save   [num_cache] = _dreq.type;
+                r_dcache_wdata_save  [num_cache] = _dreq.wdata;
+                r_dcache_be_save     [num_cache] = _dreq.be;
+                r_dcache_rdata_save  [num_cache] = dcache_rdata;
+                r_dcache_cached_save [num_cache] = dcache_cached;
+                r_dcache_num_cpu_save[num_cache] = dcache_num_cpu;
+    
+              } else {    // end if _dreq.valid
+                r_dcache_fsm [num_cache] = DCACHE_IDLE;
+              }
+                    
+              break;
+            }
+            ///////////////////////
+          case DCACHE_WRITE_UPDT:
+            {
+              m_cpt_dcache_data_write++;
+              data_t     mask  = vci_param::be2mask(r_dcache_be_save[num_cache]);
+              data_t     wdata = (mask & r_dcache_wdata_save[num_cache]) | (~mask & r_dcache_rdata_save[num_cache]);
+              vci_addr_t ad    = r_dcache_addr_save[num_cache].read();
+              r_dcache[num_cache]->write(ad, wdata);
+
+              int dcache_fsm_next = DCACHE_IDLE; // default
+
+#if CC_XCACHE_WRAPPER_STORE_AFTER_STORE
+              // Test if write after write
+
+              if (_dreq.valid and (_dreq.type == iss_t::DATA_WRITE))
+                {
+                  PRINTF("    * <DCACHE [%d]> Have dreq (Write after Write)\n",num_cache);
+
+                  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      = dreq_cached  [num_cache];
+                  uint32_t    dcache_num_cpu     = dreq_num_cpu [num_cache];
+                  bool        dcache_hit         = r_dcache[num_cache]->read((vci_addr_t) _dreq.addr, &dcache_rdata);
+
+                  m_cpt_dcache_data_read += m_dcache_ways;
+                  m_cpt_dcache_dir_read  += m_dcache_ways;
+
+                  PRINTF("    * <DCACHE [%d]> r_dcache_previous_unc : %d\n",num_cache,r_dcache_previous_unc[num_cache].read());
+                        
+                  if (dcache_cached or not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access
+                    {
+                      bool valid;
+                      addr_40 addr = _dreq.addr;
+                      set_num_dcache(addr,num_cache);
+                                
+                      // FIXME : 
+                      //  * dans le wbuf, ne pas mettre l'adresse au complet (economie de surface)
+                      //  * pour cela, virer le set_num_dcache !
+                      valid = r_wbuf[num_cache]->write(addr, _dreq.be, _dreq.wdata, dcache_cached, dcache_num_cpu);
+
+#if MWBUF_VHDL_TESTBENCH
+                      vhdl_mwbuf_port_write_val        [num_cache] = (vhdl_tb_t)1;
+                      vhdl_mwbuf_test_write_ack        [num_cache] = (vhdl_tb_t)1;
+                      vhdl_mwbuf_port_write_ack        [num_cache] = (vhdl_tb_t)valid;
+                      vhdl_mwbuf_port_write_addr       [num_cache] = (vhdl_tb_t)addr;
+                      vhdl_mwbuf_port_write_data       [num_cache] = (vhdl_tb_t)_dreq.wdata;
+                      vhdl_mwbuf_port_write_be         [num_cache] = (vhdl_tb_t)_dreq.be;
+                      vhdl_mwbuf_port_write_cached     [num_cache] = (vhdl_tb_t)dcache_cached;
+                      vhdl_mwbuf_port_write_cpu_id     [num_cache] = (vhdl_tb_t)dcache_num_cpu;
+#endif
+
+                      PRINTF("    * <DCACHE [%d]> r_wbuf valid          : %d\n",num_cache,valid);
+
+                      if (valid)
+                        {
+                          m_cpt_dcache_store_after_store [num_cache] ++;
+                                        
+                          m_cpt_data_write++;
+                                        
+                          if (not dcache_cached)
+                            {
+                              r_dcache_previous_unc[num_cache] = true;
+                              m_cpt_data_write_uncached++;
+                            }
+                          else if (not dcache_hit)
+                            m_cpt_data_write_miss++;
+                                        
+                          if (dcache_hit) {
+                            // update data cache
+                            dcache_fsm_next = DCACHE_WRITE_UPDT;
+                          } else {
+                            // write accepted
+                            dcache_fsm_next = DCACHE_IDLE;
+                          }
+                        }
+                                
+                      _drsp.valid = valid;
+                      _drsp.rdata = 0;
+                    }
+
+                  r_dcache_addr_save   [num_cache] = (addr_40) _dreq.addr;
+                  // r_dcache_type_save   [num_cache] = _dreq.type;
+                  r_dcache_wdata_save  [num_cache] = _dreq.wdata;
+                  r_dcache_be_save     [num_cache] = _dreq.be;
+                  r_dcache_rdata_save  [num_cache] = dcache_rdata;
+                  // r_dcache_cached_save [num_cache] = dcache_cached;
+                  // r_dcache_num_cpu_save[num_cache] = dcache_num_cpu;
+                }
+#endif
+
+              r_dcache_fsm [num_cache] = dcache_fsm_next; // default
+
+              break;
+            }
+            //////////////////////
+          case DCACHE_MISS_VICTIM:
+            {
+              // if (not r_dcache_cleanup_req[num_cache].read())
+              {
+                size_t     way;
+                size_t     set;
+                vci_addr_t addr = (vci_addr_t) r_dcache_addr_save[num_cache].read();
+                vci_addr_t victim;
+                bool       victim_val = r_dcache[num_cache]->victim_select(addr, &victim, &way, &set );
+                         
+                r_dcache_cleanup_req  [num_cache] = victim_val;
+                r_dcache_cleanup_line [num_cache] = (addr_40) victim;
+                r_dcache_miss_way     [num_cache] = way;
+                r_dcache_miss_set     [num_cache] = set;
+                 
+                PRINTF("    * <DCACHE [%d]> MISS_VICTIM : Victim %d - %llx (way %d, set %d)\n",num_cache,victim_val, (blob_t)victim, (int)way, (int)set);
+        
+                r_dcache_fsm          [num_cache] = DCACHE_MISS_WAIT;
+              }
+                    
+              break;
+            }
+            //////////////////////
+          case DCACHE_MISS_WAIT:
+            {
+#if CC_XCACHE_WRAPPER_MULTI_CACHE_HIT_AFTER_MISS
+              data_t   dcache_rdata   = 0;
+              bool     dcache_hit     = r_dcache[num_cache]->read((vci_addr_t) _dreq.addr, &dcache_rdata);
+              // bool     dcache_cached  = dreq_cached  [num_cache];
+              // uint32_t dcache_num_cpu = dreq_num_cpu [num_cache];
+
+              m_cpt_dcache_data_read += m_dcache_ways;
+              m_cpt_dcache_dir_read  += m_dcache_ways;
+                  
+              if (_dreq.valid)
+                switch (_dreq.type)
+                  {
+                  case iss_t::DATA_READ : // accept only hit dcache load
+                    {
+                      m_cpt_data_read++; // new dcache read
+                          
+                      if (dcache_hit) // no special test for uncached read, because it's always miss
+                        {
+                          m_cpt_dcache_hit_after_miss_read [num_cache] ++;
+                              
+                          // address is in the cache : return the word
+                          _drsp.valid = true;
+                          _drsp.rdata = dcache_rdata; // return read data (cf dcache_hit)
+                        }
+                      break;
+                    }
+                    // case iss_t::DATA_WRITE : // accept only cached write and miss in dcache (else need update dcache)
+                    //   {
+                    //     if (dcache_cached and not dcache_hit)
+                    //       {
+                    //         bool valid;
+                    //         addr_40 addr = _dreq.addr;
+                    //         set_num_dcache(addr,num_cache);
+                              
+                    //         // FIXME : 
+                    //         //  * dans le wbuf, ne pas mettre l'adresse au complet (economie de surface)
+                    //         //  * pour cela, virer le set_num_dcache !
+                    //         valid = r_wbuf[num_cache]->write(addr, _dreq.be, _dreq.wdata, dcache_cached, dcache_num_cpu);
+                    //         PRINTF("    * <DCACHE [%d]> r_wbuf valid          : %d\n",num_cache,valid);
+                              
+                    //         if (valid)
+                    //           {
+                    //             m_cpt_dcache_hit_after_miss_write [num_cache] ++;
+
+                    //             m_cpt_data_write++;
+                    //             m_cpt_data_write_miss++;
+                    //           }
+                              
+                    //         _drsp.valid = valid;
+                    //         _drsp.rdata = 0;
+                    //       }
+                    //     break;
+                    //   }
+                  default :
+                    {
+                      break;
+                    }
+                  }
+#endif
+
+              // if ( _dreq.valid ) m_cost_data_miss_frz++;
+              if ( r_tgt_dcache_req[num_cache].read() ) {   // external request
+                r_dcache_fsm      [num_cache] = DCACHE_CC_CHECK;
+                r_dcache_fsm_save [num_cache] = r_dcache_fsm[num_cache];
+                break;
+              }
+
+              bool val = CACHE_MISS_BUF_RSP_VAL(d,num_cache,0);
+              if (val)
+                {
+                  // Miss read response and no invalidation
+                  if (r_vci_rsp_data_error[num_cache])
+                    {
+                      r_dcache_fsm [num_cache] = DCACHE_ERROR;
+                    } 
+                  else 
+                    {
+                      r_dcache_update_addr[num_cache] = 0;
+                      r_dcache_fsm        [num_cache] = DCACHE_MISS_UPDT;
+                    }
+                }
+              break;
+            }
+            //////////////////////
+          case DCACHE_MISS_UPDT:
+            {
+              size_t     word = r_dcache_update_addr[num_cache].read();
+              vci_addr_t addr = (vci_addr_t) r_dcache_addr_save[num_cache].read();
+              size_t     way  = r_dcache_miss_way[num_cache].read();
+              size_t     set  = r_dcache_miss_set[num_cache].read();
+                    
+              PRINTF("    * <DCACHE [%d]> MISS_UPDT : Victim way %d, set %d\n",num_cache, (int)way, (int)set);
+
+              if (CACHE_MISS_BUF_RSP_VAL(d,num_cache,word))
+                {
+                  // m_cpt_dcache_dir_write++;
+                  // if ( _dreq.valid ) m_cost_data_miss_frz++;
+
+                  // if need invalid rsp, don't modify the cache, but pop the buf_rsp
+                  // (power save)
+                  if (not r_dcache_inval_rsp[num_cache])
+                    {
+                      r_dcache[num_cache]->write(way, set, word, CACHE_MISS_BUF_RSP_DATA(d,num_cache,word));
+                      m_cpt_dcache_data_write++;
+                    }
+
+                  CACHE_MISS_BUF_RSP_POP(d,num_cache);
+                  r_dcache_update_addr[num_cache] = ++word;
+                            
+                  // if last word, finish the update
+                  if (word >= m_dcache_words)
+                    {
+                      // in all case (inval_rsp or not), update the victim tag
+                      // because victim is already cleanup
+                      r_dcache[num_cache]->victim_update_tag(addr, way, set);
+
+                      // Last word : if previous invalid_rsp, can cleanup, else update the TAG
+                      if (r_dcache_inval_rsp[num_cache])
+                        {
+                          r_dcache_inval_rsp[num_cache] = false;
+                          r_dcache_fsm      [num_cache] = DCACHE_CC_CLEANUP;
+                        }
+                      else
+                        {
+                          r_dcache_fsm [num_cache] = DCACHE_IDLE;
+                        }
+                    }
+                }
+                
+              break;
+            }
+            ////////////////////
+          case DCACHE_UNC_WAIT:
+            {
+              // if ( _dreq.valid ) m_cost_unc_read_frz++;
+              if ( r_tgt_dcache_req[num_cache] ) {   // external request
+                r_dcache_fsm     [num_cache] = DCACHE_CC_CHECK;
+                r_dcache_fsm_save[num_cache] = r_dcache_fsm[num_cache];
+                break;
+              } 
+
+              bool ok = CACHE_MISS_BUF_RSP_VAL(d,num_cache,0);
+
+              if (ok) {
+                if (r_vci_rsp_data_error[num_cache]) {
+                  r_dcache_fsm[num_cache] = DCACHE_ERROR;
+                } else {
+                  data_t rdata = CACHE_MISS_BUF_RSP_DATA(d,num_cache,0);
+                  CACHE_MISS_BUF_RSP_POP(d,num_cache);
+
+                  if(_dreq.type == iss_t::DATA_LL){
+                    PRINTF("    * <DCACHE [%d]> ll_valid = true\n",num_cache);
+
+                    r_dcache_ll_valid  [num_cache][r_dcache_num_cpu_save[num_cache]] = true;
+                    r_dcache_ll_data   [num_cache][r_dcache_num_cpu_save[num_cache]] = rdata;
+                    r_dcache_ll_addr   [num_cache][r_dcache_num_cpu_save[num_cache]] = (vci_addr_t) _dreq.addr;
+                  }
+                  r_dcache_fsm [num_cache] = DCACHE_IDLE;
+
+                  _drsp.valid = true;
+                  _drsp.rdata = rdata;
+                }
+              }
+              break;
+            }
+            ////////////////////
+          case DCACHE_SC_WAIT:
+            {
+              // if ( _dreq.valid ) m_cost_unc_read_frz++;
+              if ( r_tgt_dcache_req[num_cache] ) {   // external request
+                r_dcache_fsm      [num_cache] = DCACHE_CC_CHECK;
+                r_dcache_fsm_save [num_cache] = r_dcache_fsm [num_cache];
+                break;
+              } 
+
+              bool ok = CACHE_MISS_BUF_RSP_VAL(d,num_cache,0);
+
+              if (ok) {
+                if (r_vci_rsp_data_error[num_cache]) {
+                  r_dcache_fsm [num_cache] = DCACHE_ERROR;
+                } else {
+                  r_dcache_fsm [num_cache] = DCACHE_IDLE;
+
+                  _drsp.valid = true;
+                  _drsp.rdata = CACHE_MISS_BUF_RSP_DATA(d,num_cache,0);
+                  CACHE_MISS_BUF_RSP_POP(d,num_cache);
+                  r_dcache_ll_valid [num_cache][r_dcache_num_cpu_save[num_cache]] = false;
+                }
+              }
+              break;
+            }
+
+            //////////////////
+          case DCACHE_ERROR:
+            {
+              r_dcache_fsm        [num_cache] = DCACHE_IDLE;
+
+              r_vci_rsp_data_error[num_cache] = false;
+              _drsp.error = true;
+              _drsp.valid = true;
+              break;
+            }
+            /////////////////    
+          case DCACHE_INVAL:
+            {
+              if ( r_tgt_dcache_req[num_cache].read() ) {   // external request
+                r_dcache_fsm      [num_cache] = DCACHE_CC_CHECK;
+                r_dcache_fsm_save [num_cache] = r_dcache_fsm [num_cache];
+                break;
+              }
+              if( not r_dcache_cleanup_req [num_cache].read() ){
+                m_cpt_dcache_dir_read += m_dcache_ways;
+                vci_addr_t  ad  = r_dcache_addr_save [num_cache].read();
+                r_dcache_cleanup_req  [num_cache] = r_dcache[num_cache]->inval(ad);
+                r_dcache_cleanup_line [num_cache] = r_dcache_addr_save [num_cache].read() >> m_dcache_words_shift;
+
+                r_dcache_fsm          [num_cache] = DCACHE_IDLE;
+              }
+              break;
+            }
+          case DCACHE_SYNC :
+            {
+              if ( r_tgt_dcache_req[num_cache] ) {   // external request
+                r_dcache_fsm     [num_cache] = DCACHE_CC_CHECK;
+                r_dcache_fsm_save[num_cache] = r_dcache_fsm[num_cache];
+                break;
+              } 
+
+              bool empty=true;
+              for (uint32_t i=0; i<m_nb_dcache; ++i)
+                empty &= r_wbuf[i]->empty();
+                    
+              if (empty)
+                {
+                  _drsp.valid = true; // end, can accept the sync request
+                  r_dcache_fsm [num_cache] = DCACHE_IDLE;
+                  r_dcache_sync[num_cache] = false;
+                }
+              break;
+            }
+            /////////////////////
+          case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
+            {
+              addr_40  ad          = r_tgt_daddr;
+              data_t  dcache_rdata = 0;
+
+              PRINTF("    * <DCACHE [%d]> CC_CHECK\n",num_cache);
+
+              // 
+              if((r_dcache_fsm_save[num_cache] == DCACHE_MISS_WAIT) and 
+                 ((r_dcache_addr_save[num_cache].read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) {
+                PRINTF("    * <DCACHE [%d]> have request, need inval rsp\n",num_cache);
+
+                r_dcache_inval_rsp[num_cache] = true;
+                r_tgt_dcache_req  [num_cache] = false;
+                if(r_tgt_update){    // Also send a cleanup and answer
+                  PRINTF("    * <DCACHE [%d]> send a cleanup and answer\n",num_cache);
+                  r_tgt_dcache_rsp[num_cache]     = true;
+                } else {            // Also send a cleanup but don't answer
+                  PRINTF("    * <DCACHE [%d]> send a cleanup and but don't answer\n",num_cache);
+                  r_tgt_dcache_rsp[num_cache]     = false;
+                }
+                r_dcache_fsm[num_cache] = r_dcache_fsm_save[num_cache];
+              } else {
+                bool    dcache_hit   = r_dcache[num_cache]->read(ad, &dcache_rdata);
+
+                PRINTF("    * <DCACHE [%d]> have no request, hit cache : %d, update : %d\n",num_cache,dcache_hit,(uint32_t)r_tgt_update);
+
+                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 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[num_cache]->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[num_cache] = 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++){
+                      data_t rdata = 0;
+                      r_dcache[num_cache]->read(ad + i*4,&rdata);
+                      data_t mask = vci_param::be2mask(r_tgt_be[i]);
+                      r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata);
+                    }
+                    r_dcache_fsm[num_cache] = DCACHE_CC_UPDT;
+#endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                  } else if ( dcache_hit and not r_tgt_update ) {
+                  r_dcache_fsm[num_cache] = DCACHE_CC_INVAL;
+                } else {
+                  if(r_tgt_update){
+                    r_tgt_dcache_rsp[num_cache] = true;
+                  } else {
+                    r_tgt_dcache_rsp[num_cache] = false;
+                  }
+                  r_tgt_dcache_req[num_cache] = false;
+                  r_dcache_fsm    [num_cache] = r_dcache_fsm_save[num_cache];
+                }
+              }
+              break;
+            }
+            ///////////////////
+          case DCACHE_CC_UPDT:    // update directory and data cache        
+            {
+              addr_40 ad = r_tgt_daddr;
+
+              m_cpt_dcache_dir_write++;
+              m_cpt_dcache_data_write++;
+
+# ifdef COHERENCE_DEBUG
+              std::cout << "PROC " << m_srcid_rw << " DCACHE_CC_UPDT, update : " << std::endl;
+# endif
+
+#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+              uint32_t word  = r_cache_word;
+                    
+              if(r_tgt_be[word])
+                r_dcache[num_cache]->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[num_cache]->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[num_cache] = false;
+                  r_tgt_dcache_rsp[num_cache] = true;
+                  r_dcache_fsm    [num_cache] = r_dcache_fsm_save[num_cache];
+                  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[num_cache]->write( ad + i*4, buf[i]);
+# ifdef COHERENCE_DEBUG
+                  std::cout << " address " << std::hex << ad+i*4 << " data " << std::dec << buf[i] << std::endl;
+                  data_t rdata = 0xAAAAAAAA;
+                  r_dcache[num_cache]->read(ad + i*4,&rdata);
+                  std::cout << "data written " << rdata << std::endl; 
+# endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
+                }
+              }
+              r_tgt_dcache_req[num_cache] = false;
+              r_tgt_dcache_rsp[num_cache] = true;
+              r_dcache_fsm    [num_cache] = r_dcache_fsm_save[num_cache];
+#endif
+              break;
+            }
+            /////////////////////
+          case DCACHE_CC_INVAL:   // invalidate a cache line
+            {
+              addr_40  ad      = r_tgt_daddr;
+              r_tgt_dcache_rsp[num_cache] = true;
+              r_dcache        [num_cache]->inval(ad);
+              r_tgt_dcache_req[num_cache] = false;
+              r_dcache_fsm    [num_cache] = r_dcache_fsm_save[num_cache];
+              break;
+            }
+            ///////////////////
+          case DCACHE_CC_CLEANUP:   
+            {
+              // cleanup
+              if(not r_dcache_cleanup_req[num_cache]){
+                r_dcache_cleanup_req  [num_cache] = true;
+                r_dcache_cleanup_line [num_cache] = r_dcache_addr_save[num_cache].read() >> m_dcache_words_shift;
+                r_dcache_fsm          [num_cache] = DCACHE_IDLE;
+
+                m_cpt_dcache_dir_read += m_dcache_ways;
+                r_dcache[num_cache]->inval((addr_40)r_dcache_addr_save[num_cache]);
+              }
+              break;
+            }    
+
+          } // end switch r_dcache_fsm
+        
+          ////////// 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
+
+          r_wbuf[num_cache]->update (have_sync);
+
+#if MWBUF_VHDL_TESTBENCH
+          vhdl_mwbuf_port_flush [num_cache] = (vhdl_tb_t)have_sync;
+#endif
+
+          drsp [num_cache] = _drsp;
+          if (_dreq.valid and _drsp.valid)
+            {
+              PRINTF("    * <CPU2CACHE> Transaction between cpu %d and Dcache %d (unlock)\n",r_dcache_lock [num_cache].read(),num_cache);
+
+              r_dcache_lock       [num_cache] = m_nb_cpu;
+              m_cpt_dcache_access [num_cache] ++;
+            }
+
+        }// end for num_cache
+
+      /////////// execute one iss cycle /////////////////////////////////////////////
+
+      for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+        {
+          // Test if the resquest is accepted
+          typename iss_t::InstructionResponse _irsp = ISS_IRSP_INITIALIZER;
+          typename iss_t::DataResponse        _drsp = ISS_DRSP_INITIALIZER;
+
+          if (ireq_num_cache[num_cpu]<m_nb_icache)
+            _irsp = irsp[ireq_num_cache[num_cpu]];
+          if (dreq_num_cache[num_cpu]<m_nb_dcache)
+            _drsp = drsp[dreq_num_cache[num_cpu]];
+
+#if CC_XCACHE_WRAPPER_STOP_SIMULATION  or CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+          typename iss_t::InstructionRequest  _ireq = ISS_IREQ_INITIALIZER;
+          typename iss_t::DataRequest         _dreq = ISS_DREQ_INITIALIZER;
+
+          if (ireq_num_cache[num_cpu]<m_nb_icache)
+            _ireq = ireq[ireq_num_cache[num_cpu]];
+          if (dreq_num_cache[num_cpu]<m_nb_dcache)
+            _dreq = dreq[dreq_num_cache[num_cpu]];
+#endif
+
+#if CC_XCACHE_WRAPPER_DEBUG
+          if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
+            {
+
+              std::cout << "    * CPU                    : " << num_cpu << std::endl
+                        << "      * Instruction Cache    : " << ireq_num_cache[num_cpu] << ", valid : " << (ireq_num_cache[num_cpu]<m_nb_icache) << std::endl
+                        << "      * Instruction Request  : " << _ireq << std::endl
+                        << "      * Instruction Response : " << _irsp << std::endl
+                        << "      * Data        Cache    : " << dreq_num_cache[num_cpu] << ", valid : " << (dreq_num_cache[num_cpu]<m_nb_dcache) << std::endl
+                        << "      * Data        Request  : " << _dreq << std::endl
+                        << "      * Data        Response : " << _drsp << std::endl;
+            }
+#endif
+
+          if ((_ireq.valid and not _irsp.valid) or 
+              (_dreq.valid and not _drsp.valid))
+            {
+              m_cpt_frz_cycles [num_cpu]++;
+#if CC_XCACHE_WRAPPER_STOP_SIMULATION
+              m_stop_simulation_nb_frz_cycles [num_cpu]++;
+                
+              if (m_stop_simulation and (m_stop_simulation_nb_frz_cycles [num_cpu]>= m_stop_simulation_nb_frz_cycles_max))
+                {
+                  std::cout << std::dec << "CC_XCACHE_WRAPPER \"" << name() << "\" (" << num_cpu << ") : cycle " << m_cpt_total_cycles << ", the cpu is frozen since " << m_stop_simulation_nb_frz_cycles [num_cpu]<< " cycles." << std::endl;
+                  ASSERT(false,"CPU : anormal activity"); // exit
+                }
+            }
+          else
+            {
+              m_stop_simulation_nb_frz_cycles [num_cpu] = 0; // reinit counter
+#endif //CC_XCACHE_WRAPPER_STOP_SIMULATION
+            }
+            
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+          if (generate_log_transaction_file_icache and _ireq.valid and _irsp.valid)
+            {
+              log_transaction_file_icache [num_cpu]
+                << "[" << m_cpt_total_cycles << "]"
+                << std::hex
+                << " @ "     << std::setw(8) << (uint32_t)_ireq.addr
+                << " ("      << std::setw(8) << (uint32_t)set_num_icache_only(_ireq.addr,ireq_num_cache[num_cpu]) 
+                << " - L "     << std::setw(8) <<((uint32_t)set_num_icache_only(_ireq.addr,ireq_num_cache[num_cpu])&m_icache_yzmask) << ")"
+                << " I "     << std::setw(8) << (uint32_t)_irsp.instruction
+                << " error "                 << (uint32_t)_irsp.error
+                << std::dec
+                << std::endl;
+            }
+
+          if (generate_log_transaction_file_dcache and _dreq.valid and _drsp.valid)
+            {
+              log_transaction_file_dcache [num_cpu]
+                << "[" << m_cpt_total_cycles << "]"
+                << std::hex
+                << " @ "     << std::setw(8) << (uint32_t)_dreq.addr
+                << " ("      << std::setw(8) << (uint32_t)set_num_dcache_only(_dreq.addr,dreq_num_cache[num_cpu])
+                << " - L "   << std::setw(8) <<((uint32_t)set_num_dcache_only(_dreq.addr,dreq_num_cache[num_cpu])&m_dcache_yzmask) << ")"
+                << " 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_transaction_file_dcache [num_cpu] << xtn_str(_dreq.addr>>2);
+                switch (_dreq.addr>>2)
+                  {
+                  case iss_t::XTN_DCACHE_INVAL : log_transaction_file_dcache [num_cpu]<< " INVAL"; break;
+                  case iss_t::XTN_SYNC         : log_transaction_file_dcache [num_cpu]<< " SYNC"; break;
+                  default                      : log_transaction_file_dcache [num_cpu]<< " invalid"; break;
+                  }
+                
+              log_transaction_file_dcache [num_cpu]<< std::endl;
+            }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+            
+          {
+            uint32_t it = 0;
+            for (size_t i=0; i<(size_t)iss_t::n_irq; i++) 
+              if(p_irq[num_cpu][i].read()) it |= (1<<i);
+                
+            m_iss[num_cpu]->executeNCycles(1, _irsp, _drsp, it);
+          }
+        }//end num_cpu
+
+      ////////////////////////////////////////////////////////////////////////////
+      // 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:
+        {
+          uint32_t num_cache          = 0;
+          bool     cleanup_dcache_req = false;
+          bool     cleanup_icache_req = false;
+
+          // dcache is prior
+          for (uint32_t i=0; i<m_nb_dcache; ++i)
+            {
+              PRINTF("      * <CLEANUP> dcache_cleanup_req : [%d] %d\n",i,(int)r_dcache_cleanup_req[i]);
+              cleanup_dcache_req |= r_dcache_cleanup_req[i];
+              if (cleanup_dcache_req)
+                {
+                  PRINTF("      * <CLEANUP> ... find\n");
+                  num_cache=i;
+                  break;
+                }
+            }
+ 
+          if (not cleanup_dcache_req)
+            for (uint32_t i=0; i<m_nb_icache; ++i)
+              {
+                PRINTF("      * <CLEANUP> icache_cleanup_req : [%d] %d\n",i,(int)r_icache_cleanup_req[i]);
+
+                cleanup_icache_req |= r_icache_cleanup_req[i];
+                if (cleanup_icache_req)
+                  {
+                    PRINTF("      * <CLEANUP> ... find\n");
+                    num_cache=i;
+                    break;
+                  }
+              }
+
+          PRINTF("      * <CLEANUP> cleanup_icache_req : %d\n",cleanup_icache_req);
+          PRINTF("      * <CLEANUP> cleanup_dcache_req : %d\n",cleanup_dcache_req);
+          PRINTF("      * <CLEANUP> num_cache          : %d\n",num_cache);
+
+          if (cleanup_icache_req or cleanup_dcache_req)
+            {
+              r_cleanup_fsm       = CLEANUP_REQ;
+              r_cleanup_icache    = cleanup_icache_req;
+              r_cleanup_num_cache = num_cache;
+
+              PRINTF("      * <CLEANUP> address            : %llx\n",((cleanup_icache_req)?((blob_t)set_num_icache_only(r_icache_cleanup_line[num_cache].read()<<m_icache_words_shift,num_cache)):((blob_t)set_num_dcache_only(r_dcache_cleanup_line[num_cache].read()<<m_dcache_words_shift,num_cache))));
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              if (generate_log_transaction_file_cleanup)
+                {
+                  log_transaction_file_cleanup
+                    << "[" << m_cpt_total_cycles << "] "
+                    << ((cleanup_icache_req)?("icache "):("dcache "))
+                    << num_cache << " : "
+                    << std::hex
+                    << " L "     << std::setw(10) << ((cleanup_icache_req)?((blob_t)set_num_icache_only(r_icache_cleanup_line[num_cache].read()<<m_icache_words_shift,num_cache)):((blob_t)set_num_dcache_only(r_dcache_cleanup_line[num_cache].read()<<m_dcache_words_shift,num_cache)))
+                    // << " (" << std::setw(10) << addr << ")"
+                    << std::dec
+                    << std::endl;
+                }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+            }
+          break;
+        }
+      case CLEANUP_REQ:
+        {
+          if ( p_vci_ini_c.cmdack )
+            {
+              if (r_cleanup_icache)
+                r_cleanup_fsm = CLEANUP_RSP_ICACHE;
+              else
+                r_cleanup_fsm = CLEANUP_RSP_DCACHE;
+            }
+          break;
+        }
+      case CLEANUP_RSP_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));
+              PRINTF("      * <CLEANUP> rpktid : %d, r_cleanup_num_cache : %d\n",(uint32_t)p_vci_ini_c.rpktid.read(), (uint32_t)r_cleanup_num_cache);
+
+              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" );
+              ASSERT(p_vci_ini_c.rpktid.read() == (sc_dt::sc_uint<vci_param::P>)r_cleanup_num_cache,
+                     "invalid pktid in a cleanup response");
+
+              r_cleanup_fsm = CLEANUP_IDLE;
+              r_dcache_cleanup_req[r_cleanup_num_cache] = false;
+              // m_cpt_cc_cleanup_data++;
+            }
+          break;
+        }
+      case CLEANUP_RSP_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[r_cleanup_num_cache] = false;
+              // m_cpt_cc_cleanup_ins++;
+            }
+          break;
+        }
+      } // end switch r_cleanup_fsm    
+
+        ////////////////////////////////////////////////////////////////////////////
+        // The VCI_CMD FSM controls the following ressources:
+        // - r_vci_cmd_fsm
+        // - r_vci_cmd_min
+        // - r_vci_cmd_max
+        // - r_vci_cmd_cpt
+        // - 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 - 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.
+        //
+        // VCI formats:
+        // According to the VCI advanced specification, all read requests packets 
+        // (read Uncached, Miss data, Miss instruction) are one word packets.
+        // For write burst packets, all words must be in the same cache line,
+        // and addresses must be contiguous (the BE field is 0 in case of "holes").
+        //////////////////////////////////////////////////////////////////////////////
+
+      // reverse priority
+      r_vci_cmd_dcache_prior = not r_vci_cmd_dcache_prior;
+
+      size_t  wbuf_min   = 0;
+      size_t  wbuf_max   = 0;
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+      addr_40 wbuf_addr  = 0;
+      size_t  wbuf_index = 0;
+#endif
+
+      uint32_t dcache_write_num_cache = m_nb_dcache;
+
+      for (uint32_t i=0; i<m_nb_dcache; ++i)
+        {
+          bool find = false;
+          
+          size_t  _wbuf_min   = 0;
+          size_t  _wbuf_max   = 0;
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+          addr_40 _wbuf_addr  = 0;
+          size_t  _wbuf_index = 0;
+#endif
+          
+          if (
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              (r_wbuf[i]->rok_info(&_wbuf_min, &_wbuf_max, &_wbuf_addr, &_wbuf_index)) and
+#else
+              (r_wbuf[i]->rok     (&_wbuf_min, &_wbuf_max)) and
+#endif                      
+              (dcache_write_num_cache == m_nb_dcache))
+            {
+              find = true;
+              dcache_write_num_cache = i;
+              
+              PRINTF("      * <CMD> wbuf min, max            : %d, %d\n",(int)_wbuf_min,(int)_wbuf_max);
+              
+              wbuf_min   = _wbuf_min  ;
+              wbuf_max   = _wbuf_max  ;
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              wbuf_addr  = _wbuf_addr ;
+              wbuf_index = _wbuf_index;
+              
+              PRINTF("      * <CMD> wbuf index               : %d\n",(int)_wbuf_index);
+              PRINTF("      * <CMD> wbuf address             : %llx\n",(blob_t)_wbuf_addr);
+#endif
+            }
+          
+          PRINTF("      * <CMD> Test read after miss     : cache : %d, find : %d\n",dcache_write_num_cache, find);
+          
+#if MWBUF_VHDL_TESTBENCH
+          vhdl_mwbuf_test_sent_val         [dcache_write_num_cache] = (vhdl_tb_t)1;
+          vhdl_mwbuf_port_sent_val         [dcache_write_num_cache] = (vhdl_tb_t)find;
+          vhdl_mwbuf_test_sent_word_min    [dcache_write_num_cache] = (vhdl_tb_t)find;
+          vhdl_mwbuf_port_sent_word_min    [dcache_write_num_cache] = (vhdl_tb_t)wbuf_min;
+          vhdl_mwbuf_test_sent_word_max    [dcache_write_num_cache] = (vhdl_tb_t)find;
+          vhdl_mwbuf_port_sent_word_max    [dcache_write_num_cache] = (vhdl_tb_t)wbuf_max;
+#endif                
+        }
+
+      switch (r_vci_cmd_fsm) {
+
+      case CMD_IDLE:
+        {
+          // if (r_vci_rsp_fsm != RSP_IDLE) break;
+
+
+          // Requests :
+
+          // multi_write_buffer access is conditionnal with dcache_miss_req and icache_miss_req
+
+          bool     dcache_miss_req      = false;
+          bool     icache_miss_req      = false;
+          uint32_t dcache_miss_num_cache = 0;
+          uint32_t icache_miss_num_cache = 0;
+          addr_40  addr = 0;
+
+          bool     wbuf_imiss = false;
+          bool     wbuf_dmiss = false;
+      
+          {
+            for (; dcache_miss_num_cache<m_nb_dcache; ++dcache_miss_num_cache)
+              {
+                dcache_miss_req = r_dcache_miss_req[dcache_miss_num_cache];
+                if (dcache_miss_req)
+                  break;
+              }
+            for (; icache_miss_num_cache<m_nb_icache; ++icache_miss_num_cache)
+              {
+                icache_miss_req = r_icache_miss_req[icache_miss_num_cache];
+                if (icache_miss_req)
+                  break;
+              }
+
+            PRINTF("      * <CMD> icache_miss_req (before) : %d\n",icache_miss_req);
+            PRINTF("      * <CMD> dcache_miss_req (before) : %d\n",dcache_miss_req);
+
+#if   (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==1)
+            //  1) one access with static priority (dcache prior)
+            icache_miss_req &= not dcache_miss_req;
+#elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==2)
+            //  2) one access with static priority (icache prior)
+            dcache_miss_req &= not icache_miss_req;
+#elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==3)
+            //  3) one access with round robin priority
+            dcache_miss_req = ((dcache_miss_req and not icache_miss_req) or // only dcache
+                               (dcache_miss_req and r_vci_cmd_dcache_prior)); // dcache prior
+            icache_miss_req &= not dcache_miss_req;
+            // #elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==4)
+            //                     //  4) two access authorized
+            //                     dcache_miss_req =  r_dcache_miss_req[cache_miss_num_cache];
+            //                     icache_miss_req =  r_icache_miss_req[cache_miss_num_cache];
+#else
+#error "Invalid value to CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY"
+#endif
+
+            PRINTF("      * <CMD> icache_miss_req (after ) : %d\n",icache_miss_req);
+            PRINTF("      * <CMD> dcache_miss_req (after ) : %d\n",dcache_miss_req);
+
+            PRINTF("      * <CMD> icache_miss_num_cache    : %d\n",icache_miss_num_cache);
+            PRINTF("      * <CMD> dcache_miss_num_cache    : %d\n",dcache_miss_num_cache);
+
+            if (icache_miss_req or dcache_miss_req)
+              {
+                addr = (icache_miss_req)?r_icache_addr_save[icache_miss_num_cache].read():r_dcache_addr_save[dcache_miss_num_cache].read();
+
+                PRINTF("      * <CMD> addr                     : %llx\n",(blob_t)addr);
+
+                if (icache_miss_req)
+                  {
+                    // FIXME : 
+                    // si wbuf contient des addresses partionné, set_num_icache puis get_num_dcache
+                    // dcache_miss_num_cache = icache_miss_num_cache;
+                    set_num_icache(addr,icache_miss_num_cache);
+                    // get_num_dcache(addr,dcache_miss_num_cache);
+                  }
+                else
+                  set_num_dcache(addr,dcache_miss_num_cache);
+
+                PRINTF("      * <CMD> addr                     : %llx\n",(blob_t)addr);
+                
+                uint32_t num_cache = get_num_dcache_only(addr);
+
+                wbuf_imiss = (icache_miss_req)?r_wbuf[num_cache]->miss(addr):false;
+                wbuf_dmiss = (dcache_miss_req)?r_wbuf[num_cache]->miss(addr):false;
+
+#if MWBUF_VHDL_TESTBENCH
+                vhdl_mwbuf_port_raw_test [num_cache] = (vhdl_tb_t)1;
+                vhdl_mwbuf_port_raw_addr [num_cache] = (vhdl_tb_t)addr;
+                vhdl_mwbuf_test_raw_miss [num_cache] = (vhdl_tb_t)1;
+                vhdl_mwbuf_port_raw_miss [num_cache] = (dcache_miss_req)?(vhdl_tb_t)wbuf_dmiss:(vhdl_tb_t)wbuf_imiss;
+#endif                
+              }
+          }
+
+          uint32_t dcache_unc_num_cache = 0;
+          for (; dcache_unc_num_cache<m_nb_dcache; ++dcache_unc_num_cache)
+            if (r_dcache_unc_req[dcache_unc_num_cache])
+              break;
+          uint32_t icache_unc_num_cache = 0;
+          for (; icache_unc_num_cache<m_nb_icache; ++icache_unc_num_cache)
+            if (r_icache_unc_req[icache_unc_num_cache])
+              break;
+          uint32_t dcache_sc_num_cache = 0;
+          for (; dcache_sc_num_cache<m_nb_dcache; ++dcache_sc_num_cache)
+            if (r_dcache_sc_req[dcache_sc_num_cache])
+              break;
+
+          // 1 - Data Read
+          if (wbuf_dmiss)
+            // (dcache_miss_req and r_wbuf[dcache_miss_num_cache]->miss(addr))
+            { 
+              r_vci_cmd_fsm       = CMD_DATA_MISS;
+              r_vci_cmd_num_cache = dcache_miss_num_cache;
+              r_dcache_miss_req[dcache_miss_num_cache] = false;
+              m_cpt_dmiss_transaction++; 
+
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              if (generate_log_transaction_file_cmd)
+                {
+                  log_transaction_file_cmd
+                    << "[" << m_cpt_total_cycles << "] "
+                    << "CMD DATA MISS  "
+                    << "(" << dcache_miss_num_cache << ") "
+                    << std::hex
+                    << " @ " << std::setw(10) << (blob_t)addr
+                    << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_dcache_yzmask) << ")"
+                    << std::dec
+                    << std::endl;
+                }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+            } 
+
+          // 2 - Data Read Uncachable
+          else if (dcache_unc_num_cache < m_nb_dcache) // have r_dcache_unc_req
+            { 
+              r_vci_cmd_fsm       = CMD_DATA_UNC;
+              r_vci_cmd_num_cache = dcache_unc_num_cache;
+              r_dcache_unc_req[dcache_unc_num_cache] = false;
+              // m_cpt_data_unc_transaction++; 
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              if (generate_log_transaction_file_cmd)
+                {
+                  addr_40 addr = (addr_40) r_dcache_addr_save[dcache_unc_num_cache].read() & ~0x3;
+                  set_num_dcache(addr,dcache_unc_num_cache);
+                        
+                  log_transaction_file_cmd
+                    << "[" << m_cpt_total_cycles << "] "
+                    << "CMD DATA UNC   "
+                    << "(" << dcache_unc_num_cache << ") "
+                    << std::hex
+                    << " @ " << std::setw(10) << (blob_t)addr
+                    << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_dcache_yzmask) << ")"
+                    << std::dec
+                    << std::endl;
+                }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+            }
+
+          // 3 - Instruction Miss
+          else if (wbuf_imiss)
+            //else if (icache_miss_req and r_wbuf[icache_miss_num_cache]->miss(addr))
+            {
+              r_vci_cmd_fsm       = CMD_INS_MISS; 
+              r_vci_cmd_num_cache = icache_miss_num_cache;
+              r_icache_miss_req[icache_miss_num_cache] = false;
+              m_cpt_imiss_transaction++;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              if (generate_log_transaction_file_cmd)
+                {
+                  log_transaction_file_cmd
+                    << "[" << m_cpt_total_cycles << "] "
+                    << "CMD INS  MISS  "
+                    << "(" << icache_miss_num_cache << ") "
+                    << std::hex
+                    << " @ " << std::setw(10) << (blob_t)addr
+                    << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_icache_yzmask) << ")"
+                    << std::dec
+                    << std::endl;
+                }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+            } 
+
+          // 4 - Instruction Uncachable
+          else if (icache_unc_num_cache < m_nb_icache) // have r_icache_unc_req
+            { 
+              r_vci_cmd_fsm       = CMD_INS_UNC; 
+              r_vci_cmd_num_cache = icache_unc_num_cache;
+              r_icache_unc_req[icache_unc_num_cache] = false;
+              // m_cpt_ins_unc_transaction++;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              if (generate_log_transaction_file_cmd)
+                {
+                  addr_40 addr = (addr_40) r_icache_addr_save[icache_unc_num_cache].read() & ~0x3;
+                  set_num_dcache(addr,icache_unc_num_cache);
+                        
+                  log_transaction_file_cmd
+                    << "[" << m_cpt_total_cycles << "] "
+                    << "CMD INS  UNC   "
+                    << "(" << icache_unc_num_cache << ") "
+                    << std::hex
+                    << " @ " << std::setw(10) << (blob_t)addr
+                    << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_icache_yzmask) << ")"
+                    << std::dec
+                    << std::endl;
+                }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+            }
+
+          // 5 - Data Write
+          else if (dcache_write_num_cache < m_nb_dcache) // have r_wbuf.rok(&wbuf_min, &wbuf_max)
+            { 
+              r_vci_cmd_num_cache = dcache_write_num_cache;
+              r_vci_cmd_fsm       = CMD_DATA_WRITE;
+              r_vci_cmd_cpt       = wbuf_min;
+              r_vci_cmd_min       = wbuf_min;
+              r_vci_cmd_max       = wbuf_max;
+              m_cpt_data_write_transaction++; 
+              m_length_write_transaction += (wbuf_max-wbuf_min+1); 
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              if (generate_log_transaction_file_cmd)
+                {
+                  addr_40 addr = (addr_40) wbuf_addr&~0x3;
+                        
+                  log_transaction_file_cmd
+                    << "[" << m_cpt_total_cycles << "] "
+                    << "CMD DATA WRITE "
+                    << "(" << dcache_write_num_cache << ") "
+                    << std::hex
+                    << " @ " << std::setw(10) << (blob_t)addr
+                    << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_dcache_yzmask) << ")"
+                    << " [" << wbuf_min << ":" << wbuf_max << "]"
+                    << " {" << wbuf_index << "}"
+                    << std::dec
+                    << std::endl;
+                }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+            } 
+
+          // 6 - Data Store Conditionnal
+          else if (dcache_sc_num_cache < m_nb_dcache) // have r_dcache_sc_req
+            { 
+              r_vci_cmd_fsm       = CMD_DATA_SC;
+              r_vci_cmd_num_cache = dcache_sc_num_cache;
+              r_vci_cmd_cpt       = 0;
+              r_vci_cmd_min       = 0;
+              r_vci_cmd_max       = 1; 
+              m_cpt_unc_transaction++; 
+              r_dcache_sc_req[dcache_sc_num_cache] = false;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              if (generate_log_transaction_file_cmd)
+                {
+                  addr_40 addr = (addr_40) r_dcache_addr_save[dcache_sc_num_cache].read() & ~0x3;
+                  set_num_dcache(addr,dcache_sc_num_cache);
+                        
+                  log_transaction_file_cmd
+                    << "[" << m_cpt_total_cycles << "] "
+                    << "CMD DATA SC    "
+                    << "(" << dcache_sc_num_cache << ") "
+                    << std::hex
+                    << " @ " << std::setw(10) << (blob_t)addr
+                    << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_dcache_yzmask) << ")"
+                    << std::dec
+                    << std::endl;
+                }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+            }
+
+          break;
+        }
+      case CMD_DATA_WRITE:
+        if ( p_vci_ini_rw.cmdack.read() ) {
+
+#if MWBUF_VHDL_TESTBENCH
+              vhdl_mwbuf_port_sent_word        [r_vci_cmd_num_cache] = (vhdl_tb_t)r_vci_cmd_cpt;
+              vhdl_mwbuf_test_sent_addr        [r_vci_cmd_num_cache] = (vhdl_tb_t)1;
+              vhdl_mwbuf_port_sent_addr        [r_vci_cmd_num_cache] = (vhdl_tb_t)r_wbuf[r_vci_cmd_num_cache]->getAddress(r_vci_cmd_cpt);
+              vhdl_mwbuf_test_sent_data        [r_vci_cmd_num_cache] = (vhdl_tb_t)1;
+              vhdl_mwbuf_port_sent_data        [r_vci_cmd_num_cache] = (vhdl_tb_t)r_wbuf[r_vci_cmd_num_cache]->getData(r_vci_cmd_cpt);
+              vhdl_mwbuf_test_sent_be          [r_vci_cmd_num_cache] = (vhdl_tb_t)1;
+              vhdl_mwbuf_port_sent_be          [r_vci_cmd_num_cache] = (vhdl_tb_t)r_wbuf[r_vci_cmd_num_cache]->getBe(r_vci_cmd_cpt);
+              vhdl_mwbuf_test_sent_index       [r_vci_cmd_num_cache] = (vhdl_tb_t)1;
+              vhdl_mwbuf_port_sent_index       [r_vci_cmd_num_cache] = (vhdl_tb_t)r_wbuf[r_vci_cmd_num_cache]->getIndex();
+#endif
+
+          r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
+          if (r_vci_cmd_cpt == r_vci_cmd_max) {
+            r_vci_cmd_fsm = CMD_IDLE ;
+            r_wbuf[r_vci_cmd_num_cache]->sent() ;
+#if MWBUF_VHDL_TESTBENCH
+            vhdl_mwbuf_port_sent_ack [r_vci_cmd_num_cache] = (vhdl_tb_t)1;
+#endif
+          }
+        }
+        break;
+
+      case CMD_DATA_SC:
+        if ( p_vci_ini_rw.cmdack.read() ) {
+          r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
+          if (r_vci_cmd_cpt == r_vci_cmd_max) {
+            r_vci_cmd_fsm = CMD_IDLE ;
+          }
+        }
+        break;
+      case CMD_INS_MISS:
+      case CMD_INS_UNC:
+      case CMD_DATA_MISS:
+      case CMD_DATA_UNC:
+        if ( p_vci_ini_rw.cmdack.read() ) {
+          r_vci_cmd_fsm = CMD_IDLE;
+        }
+        break;
+
+      } // end  switch r_vci_cmd_fsm
+
+        //////////////////////////////////////////////////////////////////////////
+        // The VCI_RSP FSM controls the following ressources:
+        // - r_vci_rsp_fsm:
+        // - r_icache_miss_buf[m_icache_words]
+        // - r_dcache_miss_buf[m_dcache_words]
+        // - r_vci_rsp_data_error set
+        // - r_vci_rsp_ins_error set
+        // - r_vci_rsp_cpt
+        // In order to have only one active VCI transaction, this VCI_RSP_FSM 
+        // is synchronized with the VCI_CMD FSM, and both FSMs exit the
+        // IDLE state simultaneously.
+        // 
+        // VCI formats:
+        // This component accepts single word or multi-word response packets for
+        // write response packets. 
+        //
+        // Error handling:
+        // This FSM analyzes the VCI error code and signals directly the
+        // Write Bus Error. 
+        // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error 
+        // flip_flop and the error is signaled by the DCACHE FSM.  
+        // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 
+        // flip_flop and the error is signaled by the DCACHE FSM.  
+        // In case of Cleanup Error, the simulation stops with an error message...
+        //////////////////////////////////////////////////////////////////////////
+
+      switch (r_vci_rsp_fsm) {
+
+      case RSP_IDLE:
+
+        if( p_vci_ini_rw.rspval.read() )
+          {
+            PRINTF("      * <RSP> have rsp - trdid : %x - num_cache : %d\n",(uint32_t)p_vci_ini_rw.rtrdid.read(),(uint32_t)p_vci_ini_rw.rpktid.read());
+
+            ASSERT(p_vci_ini_rw.rpktid.read() <= (1<<vci_param::P),
+                   "invalid pktid in a cleanup response");
+
+            r_vci_rsp_cpt = 0;
+
+            if ((p_vci_ini_rw.rtrdid.read()>>(vci_param::T-1)) != 0 )
+              {
+                r_vci_rsp_fsm = RSP_DATA_WRITE;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                if (generate_log_transaction_file_cmd)
+                  {
+                    log_transaction_file_cmd
+                      << "[" << m_cpt_total_cycles << "] "
+                      << "RSP DATA WRITE "
+                      << "(" << p_vci_ini_rw.rpktid.read() << ") "
+                      << "{" << (p_vci_ini_rw.rtrdid.read() - (1<<(vci_param::T-1))) << "}"
+                      << std::endl;
+                  }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+              }
+            else
+              {
+                switch (p_vci_ini_rw.rtrdid.read())
+                  {
+                  case TYPE_INS_MISS     : 
+                    {
+                      r_vci_rsp_fsm = RSP_INS_MISS;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                      if (generate_log_transaction_file_cmd)
+                        {
+                          log_transaction_file_cmd
+                            << "[" << m_cpt_total_cycles << "] "
+                            << "RSP INS  MISS  "
+                            << "(" << p_vci_ini_rw.rpktid.read() << ") "
+                            << std::endl;
+                        }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+                      break;
+                    }
+                  case TYPE_INS_UNC      : 
+                    {
+                      r_vci_rsp_fsm = RSP_INS_UNC;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                      if (generate_log_transaction_file_cmd)
+                        {
+                          log_transaction_file_cmd
+                            << "[" << m_cpt_total_cycles << "] "
+                            << "RSP INS  UNC   "
+                            << "(" << p_vci_ini_rw.rpktid.read() << ") "
+                            << std::endl;
+                        }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+                      break;
+                    }
+                  case TYPE_DATA_MISS    : 
+                    {
+                      r_vci_rsp_fsm = RSP_DATA_MISS;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                      if (generate_log_transaction_file_cmd)
+                        {
+                          log_transaction_file_cmd
+                            << "[" << m_cpt_total_cycles << "] "
+                            << "RSP DATA MISS  "
+                            << "(" << p_vci_ini_rw.rpktid.read() << ") "
+                            << std::endl;
+                        }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+                      break;
+                    }
+                  case TYPE_DATA_UNC     : 
+                    {
+                      r_vci_rsp_fsm = RSP_DATA_UNC;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                      if (generate_log_transaction_file_cmd)
+                        {
+                          log_transaction_file_cmd
+                            << "[" << m_cpt_total_cycles << "] "
+                            << "RSP DATA UNC   "
+                            << "(" << p_vci_ini_rw.rpktid.read() << ") "
+                            << std::endl;
+                        }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+                      break;
+                    }
+                  case TYPE_DATA_SC      : 
+                    {
+                      r_vci_rsp_fsm = RSP_DATA_SC;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                      if (generate_log_transaction_file_cmd)
+                        {
+                          log_transaction_file_cmd
+                            << "[" << m_cpt_total_cycles << "] "
+                            << "RSP DATA SC    "
+                            << "(" << p_vci_ini_rw.rpktid.read() << ") "
+                            << std::endl;
+                        }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
+                      break;
+                    }
+                  default : 
+                    {
+                      ASSERT(false, "Unexpected response");
+                    }
+                  }
+              }
+
+            r_vci_rsp_num_cache = p_vci_ini_rw.rpktid.read();
+          }
+        break;
+
+      case RSP_INS_MISS:
+
+        m_cost_imiss_transaction++;
+        PRINTF("      * <RSP> rspval/ack : %d - %d\n",(uint32_t)p_vci_ini_rw.rspval.read(), (uint32_t)s_vci_rsp_ack);
+
+        if (p_vci_ini_rw.rspval.read() and s_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_num_cache,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[r_vci_rsp_num_cache].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[r_vci_rsp_num_cache] = true;
+          }
+        break;
+
+      case RSP_INS_UNC:
+
+        m_cost_imiss_transaction++;
+        if (p_vci_ini_rw.rspval.read() and s_vci_rsp_ack)
+          {
+            ASSERT(p_vci_ini_rw.reop.read(),
+                   "illegal VCI response packet for uncached instruction");
+
+            CACHE_MISS_BUF_RSP_PUSH(i,r_vci_rsp_num_cache,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[r_vci_rsp_num_cache] = true;
+          }
+        break;
+
+      case RSP_DATA_MISS:
+
+        m_cost_dmiss_transaction++;
+        if (p_vci_ini_rw.rspval.read() and s_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_num_cache,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[r_vci_rsp_num_cache].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[r_vci_rsp_num_cache] = 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;
+            uint32_t wbuf_index = p_vci_ini_rw.rtrdid.read() - (1<<(vci_param::T-1));
+            size_t cpu_id = r_wbuf[r_vci_rsp_num_cache]->getCpuId (wbuf_index);
+            bool   cached = r_wbuf[r_vci_rsp_num_cache]->completed(wbuf_index);
+            PRINTF("      * <RSP> cached : %d\n",cached);
+
+            if (not cached)
+              r_dcache_previous_unc[r_vci_rsp_num_cache] = false;
+
+            if ((p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL)
+              m_iss[cpu_id]->setWriteBerr();
+
+#if MWBUF_VHDL_TESTBENCH
+            vhdl_mwbuf_port_completed_val    [r_vci_rsp_num_cache] = (vhdl_tb_t)1;
+            vhdl_mwbuf_port_completed_index  [r_vci_rsp_num_cache] = (vhdl_tb_t)wbuf_index;
+            vhdl_mwbuf_test_completed_cached [r_vci_rsp_num_cache] = (vhdl_tb_t)1;
+            vhdl_mwbuf_port_completed_cached [r_vci_rsp_num_cache] = (vhdl_tb_t)cached;
+            vhdl_mwbuf_test_completed_cpu_id [r_vci_rsp_num_cache] = (vhdl_tb_t)1;
+            vhdl_mwbuf_port_completed_cpu_id [r_vci_rsp_num_cache] = (vhdl_tb_t)cpu_id;
+#endif
+          }
+        break;
+
+      case RSP_DATA_UNC:
+        m_cost_unc_transaction++;
+        if (p_vci_ini_rw.rspval.read() and s_vci_rsp_ack)
+          {
+            ASSERT(p_vci_ini_rw.reop.read(),
+                   "illegal VCI response packet for data read uncached");
+
+            CACHE_MISS_BUF_RSP_PUSH(d,r_vci_rsp_num_cache,0,(data_t)p_vci_ini_rw.rdata.read());
+
+            r_vci_rsp_fsm = RSP_IDLE;
+            r_dcache_previous_unc[r_vci_rsp_num_cache] = false;
+
+            if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error[r_vci_rsp_num_cache] = true;
+          }
+        break;
+
+      case RSP_DATA_SC:
+        m_cost_unc_transaction++;
+        if (p_vci_ini_rw.rspval.read() and s_vci_rsp_ack)
+          {
+            ASSERT(p_vci_ini_rw.reop.read(),
+                   "illegal VCI response packet for data SC");
+
+            CACHE_MISS_BUF_RSP_PUSH(d,r_vci_rsp_num_cache,0,(data_t)p_vci_ini_rw.rdata.read());
+
+            r_vci_rsp_fsm = RSP_IDLE;
+            r_dcache_previous_unc[r_vci_rsp_num_cache] = false;
+
+            if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error[r_vci_rsp_num_cache] = true;
+          }
+        break;
+
+      } // end switch r_vci_rsp_fsm
+
+
+#if MWBUF_VHDL_TESTBENCH
+      for (uint32_t num_dcache=0; num_dcache<m_nb_dcache; ++num_dcache)
+        {
+          vhdl_mwbuf_test_empty            [num_dcache] = (vhdl_tb_t)1;
+          vhdl_mwbuf_port_empty            [num_dcache] = (vhdl_tb_t)r_wbuf[num_dcache]->empty();
+
+          vhdl_testbench_mwbuf [num_dcache]
+            << std::hex
+            << vhdl_mwbuf_test_empty            [num_dcache] << " "
+            << vhdl_mwbuf_port_empty            [num_dcache] << " "
+            << vhdl_mwbuf_port_flush            [num_dcache] << " "
+            << vhdl_mwbuf_port_write_val        [num_dcache] << " "
+            << vhdl_mwbuf_test_write_ack        [num_dcache] << " "
+            << vhdl_mwbuf_port_write_ack        [num_dcache] << " "
+            << vhdl_mwbuf_port_write_addr       [num_dcache] << " "
+            << vhdl_mwbuf_port_write_data       [num_dcache] << " "
+            << vhdl_mwbuf_port_write_be         [num_dcache] << " "
+            << vhdl_mwbuf_port_write_cached     [num_dcache] << " "
+            << vhdl_mwbuf_port_write_cpu_id     [num_dcache] << " "
+            << vhdl_mwbuf_test_sent_val         [num_dcache] << " "
+            << vhdl_mwbuf_port_sent_val         [num_dcache] << " "
+            << vhdl_mwbuf_port_sent_ack         [num_dcache] << " "
+            << vhdl_mwbuf_test_sent_word_min    [num_dcache] << " "
+            << vhdl_mwbuf_port_sent_word_min    [num_dcache] << " "
+            << vhdl_mwbuf_test_sent_word_max    [num_dcache] << " "
+            << vhdl_mwbuf_port_sent_word_max    [num_dcache] << " "
+            << vhdl_mwbuf_port_sent_word        [num_dcache] << " "
+            << vhdl_mwbuf_test_sent_addr        [num_dcache] << " "
+            << vhdl_mwbuf_port_sent_addr        [num_dcache] << " "
+            << vhdl_mwbuf_test_sent_data        [num_dcache] << " "
+            << vhdl_mwbuf_port_sent_data        [num_dcache] << " "
+            << vhdl_mwbuf_test_sent_be          [num_dcache] << " "
+            << vhdl_mwbuf_port_sent_be          [num_dcache] << " "
+            << vhdl_mwbuf_test_sent_index       [num_dcache] << " "
+            << vhdl_mwbuf_port_sent_index       [num_dcache] << " "
+            << vhdl_mwbuf_port_raw_test         [num_dcache] << " "
+            << vhdl_mwbuf_port_raw_addr         [num_dcache] << " "
+            << vhdl_mwbuf_test_raw_miss         [num_dcache] << " "
+            << vhdl_mwbuf_port_raw_miss         [num_dcache] << " "
+            << vhdl_mwbuf_port_completed_val    [num_dcache] << " "
+            << vhdl_mwbuf_port_completed_index  [num_dcache] << " "
+            << vhdl_mwbuf_test_completed_cached [num_dcache] << " "
+            << vhdl_mwbuf_port_completed_cached [num_dcache] << " "
+            << vhdl_mwbuf_test_completed_cpu_id [num_dcache] << " "
+            << vhdl_mwbuf_port_completed_cpu_id [num_dcache]
+            << std::dec
+            << std::endl;
+        }
+#endif
+    } // end transition()
+
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(void)::genMoore()
+    //////////////////////////////////////////////////////////////////////////////////
+    {
+      PRINTF("--------------------------------------------\n");
+      PRINTF("  * CC_XCACHE_WRAPPER \"%s\" genMoore - Time = %d\n",name().c_str(),(uint32_t)m_cpt_total_cycles);
+
+      // VCI initiator response
+      switch ( r_cleanup_fsm.read() ) {
+      case CLEANUP_IDLE:
+        p_vci_ini_c.rspack  = 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_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_REQ:
+        {
+          addr_40 addr;
+          if (r_cleanup_icache)
+            {
+              addr = r_icache_cleanup_line[r_cleanup_num_cache].read()<<m_icache_words_shift;
+              set_num_icache(addr,r_cleanup_num_cache);
+
+              PRINTF("      * <CLEANUP> icache             : %llx\n",(blob_t)addr);
+            }
+          else
+            {
+              addr = r_dcache_cleanup_line[r_cleanup_num_cache].read()<<m_dcache_words_shift;
+              set_num_dcache(addr,r_cleanup_num_cache);
+
+              PRINTF("      * <CLEANUP> dcache             : %llx\n",(blob_t)addr);
+            }
+
+          p_vci_ini_c.rspack  = false;
+          p_vci_ini_c.cmdval  = true;
+          p_vci_ini_c.address = addr;
+          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.trdid   = (r_cleanup_icache)?TYPE_INS_CLEANUP:TYPE_DATA_CLEANUP;
+          p_vci_ini_c.pktid   = (sc_dt::sc_uint<vci_param::P>)r_cleanup_num_cache;
+          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_RSP_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_RSP_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
+
+      switch (r_vci_cmd_fsm.read() ) {
+      case CMD_IDLE:
+        {
+          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;
+
+          break;
+        }
+      case CMD_DATA_UNC:
+        {
+          p_vci_ini_rw.cmdval = true;
+
+          addr_40 addr = (addr_40) r_dcache_addr_save[r_vci_cmd_num_cache].read() & ~0x3;
+          set_num_dcache(addr,r_vci_cmd_num_cache);
+
+          PRINTF("      * <CMD> DATA_UNC   : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr));
+
+          p_vci_ini_rw.address = addr;
+          switch( r_dcache_type_save[r_vci_cmd_num_cache] ) {
+          case iss_t::DATA_READ:
+            p_vci_ini_rw.wdata = 0;
+            p_vci_ini_rw.be  = r_dcache_be_save[r_vci_cmd_num_cache].read();
+            p_vci_ini_rw.cmd = vci_param::CMD_READ;
+            break;
+          case iss_t::DATA_LL:
+            p_vci_ini_rw.wdata = 0;
+            p_vci_ini_rw.be  = 0xF;
+            p_vci_ini_rw.cmd = vci_param::CMD_LOCKED_READ;
+            break;
+          default:
+            ASSERT(false,"this should not happen");
+          }
+          p_vci_ini_rw.plen = 4;
+          p_vci_ini_rw.trdid  = TYPE_DATA_UNC;   // data cache uncached read
+          p_vci_ini_rw.pktid  = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache;
+          p_vci_ini_rw.srcid  = m_srcid_rw;
+          p_vci_ini_rw.cons   = false;
+          p_vci_ini_rw.wrap   = false;
+          p_vci_ini_rw.contig = true;
+          p_vci_ini_rw.clen   = 0;
+          p_vci_ini_rw.cfixed = false;
+          p_vci_ini_rw.eop    = true;
+
+          break;
+        }
+      case CMD_DATA_SC:
+        {
+          p_vci_ini_rw.cmdval = true;
+
+          addr_40 addr = (addr_40) r_dcache_addr_save[r_vci_cmd_num_cache].read() & ~0x3;
+          set_num_dcache(addr,r_vci_cmd_num_cache);
+
+          PRINTF("      * <CMD> DATA_SC    : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr));
+
+          p_vci_ini_rw.address = addr;
+          if(r_vci_cmd_max.read() == 3){
+            ASSERT(false, "Not handled yet");
+          } else { // r_vci_cmd_cpt == 1
+            switch(r_vci_cmd_cpt.read()){
+            case 0:
+              p_vci_ini_rw.wdata = (uint32_t)(r_dcache_ll_data[r_vci_cmd_num_cache][r_dcache_num_cpu_save[r_vci_cmd_num_cache]].read() & 0xFFFFFFFF);
+              break;
+            case 1:
+              p_vci_ini_rw.wdata = r_dcache_wdata_save[r_vci_cmd_num_cache].read();
+              break;
+            }
+          }
+          p_vci_ini_rw.be     = 0xF;
+          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  = TYPE_DATA_SC;   // data cache uncached read
+          p_vci_ini_rw.pktid  = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache;
+          p_vci_ini_rw.srcid  = m_srcid_rw;
+          p_vci_ini_rw.cons   = true;
+          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    = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
+
+          break;
+        }
+      case CMD_DATA_WRITE:
+        {
+          p_vci_ini_rw.cmdval  = true;
+
+          addr_40 addr       = (addr_40) r_wbuf[r_vci_cmd_num_cache]->getAddress(r_vci_cmd_cpt)&~0x3;
+
+          PRINTF("      * <CMD> DATA_WRITE : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr));
+
+          p_vci_ini_rw.address = addr;
+          p_vci_ini_rw.wdata   = r_wbuf[r_vci_cmd_num_cache]->getData(r_vci_cmd_cpt);
+          p_vci_ini_rw.be      = r_wbuf[r_vci_cmd_num_cache]->getBe(r_vci_cmd_cpt);
+          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   = r_wbuf[r_vci_cmd_num_cache]->getIndex() + (1<<(vci_param::T-1));
+          p_vci_ini_rw.pktid   = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache;
+          p_vci_ini_rw.srcid   = m_srcid_rw;
+          p_vci_ini_rw.cons    = false;
+          p_vci_ini_rw.wrap    = false;
+          p_vci_ini_rw.contig  = true;
+          p_vci_ini_rw.clen    = 0;
+          p_vci_ini_rw.cfixed  = false;
+          p_vci_ini_rw.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
+
+          break;
+        }
+      case CMD_DATA_MISS:
+        {
+          p_vci_ini_rw.cmdval = true;
+
+          addr_40 addr = r_dcache_addr_save[r_vci_cmd_num_cache].read() & (addr_40) m_dcache_yzmask;
+          set_num_dcache(addr,r_vci_cmd_num_cache);
+
+          PRINTF("      * <CMD> DATA_MISS  : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr));
+
+          p_vci_ini_rw.address = addr;
+          p_vci_ini_rw.be     = 0xF;
+          p_vci_ini_rw.plen   = m_dcache_words << 2;
+          p_vci_ini_rw.cmd    = vci_param::CMD_READ;
+          p_vci_ini_rw.trdid  = TYPE_DATA_MISS;   // data cache cached read
+          p_vci_ini_rw.pktid  = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache;
+          p_vci_ini_rw.srcid  = m_srcid_rw;
+          p_vci_ini_rw.cons   = false;
+          p_vci_ini_rw.wrap   = false;
+          p_vci_ini_rw.contig = true;
+          p_vci_ini_rw.clen   = 0;
+          p_vci_ini_rw.cfixed = false;
+          p_vci_ini_rw.eop = true;
+
+          break;
+        }
+      case CMD_INS_MISS:
+        {
+          p_vci_ini_rw.cmdval = true;
+
+          addr_40 addr = r_icache_addr_save[r_vci_cmd_num_cache].read() & (addr_40) m_icache_yzmask;
+          set_num_icache(addr,r_vci_cmd_num_cache);
+
+          PRINTF("      * <CMD> INS_MISS   : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr));
+
+          p_vci_ini_rw.address = addr;
+          p_vci_ini_rw.be     = 0xF;
+          p_vci_ini_rw.plen   = m_icache_words << 2;
+          p_vci_ini_rw.cmd    = vci_param::CMD_READ;
+          p_vci_ini_rw.trdid  = TYPE_INS_MISS;   // ins cache cached read
+          p_vci_ini_rw.pktid  = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache;
+          p_vci_ini_rw.srcid  = m_srcid_rw;
+          p_vci_ini_rw.cons   = false;
+          p_vci_ini_rw.wrap   = false;
+          p_vci_ini_rw.contig = true;
+          p_vci_ini_rw.clen   = 0;
+          p_vci_ini_rw.cfixed = false;
+          p_vci_ini_rw.eop = true;
+
+          break;
+        }
+      case CMD_INS_UNC:
+        {
+          p_vci_ini_rw.cmdval = true;
+
+          addr_40 addr = r_icache_addr_save[r_vci_cmd_num_cache].read() & ~0x3;
+          set_num_icache(addr,r_vci_cmd_num_cache);
+
+          PRINTF("      * <CMD> INS_UNC    : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr));
+
+          p_vci_ini_rw.address = addr;
+          p_vci_ini_rw.be     = 0xF;
+          p_vci_ini_rw.plen   = 4;
+          p_vci_ini_rw.cmd    = vci_param::CMD_READ;
+          p_vci_ini_rw.trdid  = TYPE_INS_UNC;   // ins cache uncached read
+          p_vci_ini_rw.pktid  = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache;
+          p_vci_ini_rw.srcid  = m_srcid_rw;
+          p_vci_ini_rw.cons   = false;
+          p_vci_ini_rw.wrap   = false;
+          p_vci_ini_rw.contig = true;
+          p_vci_ini_rw.clen   = 0;
+          p_vci_ini_rw.cfixed = false;
+          p_vci_ini_rw.eop = true;
+
+          break;
+        }
+      } // end switch r_vci_cmd_fsm
+
+      {
+        bool ack;
+            
+        switch (r_vci_rsp_fsm.read() ) {
+        case RSP_DATA_WRITE : ack = true; break;
+        case RSP_INS_MISS   :
+        case RSP_INS_UNC    : ack = CACHE_MISS_BUF_RSP_ACK(i,r_vci_rsp_num_cache); break;
+        case RSP_DATA_MISS  :
+        case RSP_DATA_UNC   :
+        case RSP_DATA_SC    : ack = CACHE_MISS_BUF_RSP_ACK(d,r_vci_rsp_num_cache); break;
+                
+        case RSP_IDLE       :
+        default             : ack = false; break;
+                
+        } // end switch r_vci_cmd_fsm
+            
+        s_vci_rsp_ack       = ack;
+        p_vci_ini_rw.rspack = ack;
+
+        PRINTF("      * <RSP> rspack : %d\n", ack);
+      }
+
+      // VCI_TGT
+
+      // PRINTF("      * <TGT> srcid : %d\n", r_tgt_srcid.read());
+
+      switch ( r_vci_tgt_fsm.read() ) {
+
+      case TGT_IDLE:
+      case TGT_UPDT_WORD:
+      case TGT_UPDT_DATA:
+        p_vci_tgt.cmdack  = true;
+        p_vci_tgt.rspval  = false;
+        break;
+
+      case TGT_RSP_BROADCAST:
+        {
+          bool tgt_icache_req;
+          bool tgt_icache_rsp;
+
+#if   (CC_XCACHE_WRAPPER_MULTI_CACHE==1)
+          tgt_icache_req = r_tgt_icache_req[r_tgt_num_cache].read();
+          tgt_icache_rsp = r_tgt_icache_rsp[r_tgt_num_cache].read();
+#elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2)
+          tgt_icache_req = false;
+          tgt_icache_rsp = false;
+          for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+            {
+              tgt_icache_req |= r_tgt_icache_req[num_cache].read();
+              tgt_icache_rsp |= r_tgt_icache_rsp[num_cache].read();
+            }
+#endif
+
+          bool rspval = ((not tgt_icache_req and not r_tgt_dcache_req[r_tgt_num_cache].read()) 
+                         and (tgt_icache_rsp | r_tgt_dcache_rsp[r_tgt_num_cache]));
+
+          PRINTF("      * <TGT> RSP_BROADCAST : rspval : %d (i %d %d, d %d %d)\n",rspval,tgt_icache_req,tgt_icache_rsp, r_tgt_dcache_req[r_tgt_num_cache].read(), r_tgt_dcache_rsp[r_tgt_num_cache].read());
+                    
+          p_vci_tgt.cmdack  = false;
+          p_vci_tgt.rspval  = rspval;
+          p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+          p_vci_tgt.rpktid  = r_tgt_pktid.read();
+          p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+          p_vci_tgt.rdata   = 0;
+          p_vci_tgt.rerror  = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
+          p_vci_tgt.reop    = true;
+          break;
+        }
+      case TGT_RSP_ICACHE:
+        {
+          bool rspval = not r_tgt_icache_req[r_tgt_num_cache].read() and r_tgt_icache_rsp[r_tgt_num_cache].read();
+
+          PRINTF("      * <TGT> RSP_ICACHE : rspval : %d\n",rspval);
+
+          p_vci_tgt.cmdack  = false;
+          p_vci_tgt.rspval  = rspval;
+          p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+          p_vci_tgt.rpktid  = r_tgt_pktid.read();
+          p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+          p_vci_tgt.rdata   = 0;
+          p_vci_tgt.rerror  = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
+          p_vci_tgt.reop    = true;
+          break;
+        }
+      case TGT_RSP_DCACHE:
+        {
+          bool rspval = not r_tgt_dcache_req[r_tgt_num_cache].read() and r_tgt_dcache_rsp[r_tgt_num_cache].read();
+
+          PRINTF("      * <TGT> RSP_DCACHE : rspval : %d\n",rspval);
+                    
+          p_vci_tgt.cmdack  = false;
+          p_vci_tgt.rspval  = rspval;
+          p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+          p_vci_tgt.rpktid  = r_tgt_pktid.read();
+          p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+          p_vci_tgt.rdata   = 0;
+          p_vci_tgt.rerror  = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
+          p_vci_tgt.reop    = true;
+          break;
+        }
+      case TGT_REQ_BROADCAST:
+      case TGT_REQ_ICACHE:
+      case TGT_REQ_DCACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = false;
+        break;
+
+      } // end switch TGT_FSM
+    } // 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
+        
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(void)::log_transaction ( bool generate_file_icache
+                                  ,bool generate_file_dcache
+                                  ,bool generate_file_cmd
+                                  ,bool generate_file_tgt
+                                  ,bool generate_file_cleanup)
+    //////////////////////////////////////////////////////////////////////////////////
+    {
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+      generate_log_transaction_file_icache  = generate_file_icache ;
+      generate_log_transaction_file_dcache  = generate_file_dcache ;
+      generate_log_transaction_file_cmd     = generate_file_cmd    ;
+      generate_log_transaction_file_tgt     = generate_file_tgt    ;
+      generate_log_transaction_file_cleanup = generate_file_cleanup;
+#else
+      std::cout << "CC_XCACHE_WRAPPER \"" << name() << "\" : flag CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION is unset, you can't use log_transaction." << std::endl;
+#endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
+        
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(void)::vhdl_testbench (bool generate_file_mwbuf)
+    //////////////////////////////////////////////////////////////////////////////////
+    {
+#if MWBUF_VHDL_TESTBENCH
+      if (simulation_started)
+        std::cout << "CC_XCACHE_WRAPPER \"" << name() << "\" : Simulation is starting, you can't use vhdl_testbench." << std::endl;
+      else
+        generate_vhdl_testbench_mwbuf = generate_file_mwbuf;
+#else
+      std::cout << "CC_XCACHE_WRAPPER \"" << name() << "\" : flag MWBUF_VHDL_TESTBENCH is unset, you can't use vhdl_testbench." << std::endl;
+#endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(uint32_t)::get_num_cache(addr_40 & addr)
+    //////////////////////////////////////////////////////////////////////////////////
+    {
+      uint32_t num_cache = get_num_cache_only(addr);
+
+      addr = ((addr&m_num_cache_LSB_mask) | // keep LSB
+              ((addr>>m_num_cache_MSB)<<m_num_cache_LSB)); // set MSB
+
+      return num_cache;
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(uint32_t)::get_num_cache_only(addr_40 addr)
+    //////////////////////////////////////////////////////////////////////////////////
+    {
+      return (addr>>m_num_cache_LSB)&m_num_cache_mask;
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(void)::set_num_cache(addr_40 & addr, uint32_t num_cache)
+    //////////////////////////////////////////////////////////////////////////////////
+    {
+      addr = ((addr&m_num_cache_LSB_mask) | // keep LSB
+              ((addr_40)num_cache << m_num_cache_LSB) |
+              ((addr>>m_num_cache_LSB)<<m_num_cache_MSB)); // set MSB
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////
+    // FIXME : mettre le type addr_40
+    tmpl(sc_dt::sc_uint<40>)::set_num_cache_only(addr_40 addr, uint32_t num_cache) 
+    //////////////////////////////////////////////////////////////////////////////////
+    {
+      return ((addr&m_num_cache_LSB_mask) | // keep LSB
+              ((addr_40)num_cache << m_num_cache_LSB) |
+              ((addr>>m_num_cache_LSB)<<m_num_cache_MSB)); // set MSB
+    }
+
+
+  }} // end namespace
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Index: /trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/platform_desc
===================================================================
--- /trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/platform_desc	(revision 151)
+++ /trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/platform_desc	(revision 152)
@@ -5,5 +5,5 @@
 todo = Platform('caba', 'top.cpp',
 	uses = [
-	Uses('caba:vci_cc_xcache_wrapper_v4', iss_t = 'common:gdb_iss', gdb_iss_t = 'common:mips32el'),
+	Uses('caba:vci_cc_xcache_wrapper_v4_cmp', iss_t = 'common:gdb_iss', gdb_iss_t = 'common:mips32el'),
 	Uses('caba:vci_simple_ram'),
         Uses('caba:vci_simhelper'),
Index: /trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/top.cpp
===================================================================
--- /trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/top.cpp	(revision 151)
+++ /trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/top.cpp	(revision 152)
@@ -16,5 +16,5 @@
 #include "vci_simple_ring_fast.h"
 #include "vci_mem_cache_v4.h"
-#include "vci_cc_xcache_wrapper_v4.h"
+#include "vci_cc_xcache_wrapper_v4_cmp.h"
 #include "alloc_elems.h"
 
@@ -279,5 +279,5 @@
         soclib::common::GdbServer<soclib::common::Mips32ElIss>::set_loader(loader);
 
-	soclib::caba::VciCcXCacheWrapperV4<vci_param, proc_iss > * proc [nb_proc];
+	soclib::caba::VciCcXCacheWrapperV4_CMP<vci_param, proc_iss > * proc [nb_proc];
         for (uint32_t i=0; i<nb_proc; ++i)
           {
@@ -287,5 +287,5 @@
             str << "proc_" << num_cpu;
 
-            proc[i] = new soclib::caba::VciCcXCacheWrapperV4<vci_param, proc_iss > (str.str().c_str(), num_cpu, maptabp, maptabc, IntTab(i),IntTab(i),IntTab(i)
+            proc[i] = new soclib::caba::VciCcXCacheWrapperV4_CMP<vci_param, proc_iss > (str.str().c_str(), num_cpu, maptabp, maptabc, IntTab(i),IntTab(i),IntTab(i)
 #if USE_OLD_XCACHE
                                                                                     ,iways, isets, iwords
