Index: trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h	(revision 139)
+++ trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h	(revision 140)
@@ -31,4 +31,5 @@
 
 #include <inttypes.h>
+#include <fstream>
 #include <systemc>
 #include <queue>
@@ -71,4 +72,8 @@
  *     4    - one access with round robin priority
  * 
+ * CC_XCACHE_WRAPPER_MULTI_CACHE :
+ *     1    - icache static partitionnement
+ *     2    - icache dedicated
+ *
  * CC_XCACHE_WRAPPER_STOP_SIMULATION :
  *   stop simulation if processor is stall after a long time
@@ -81,39 +86,53 @@
  *   Number of cycle before to prinf debug message
  *
- * CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
- *   Print transaction between the cpu and the cache
+ * CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+ *   Print transaction between :
+ *     - the cpu and the cache (icache and dcache)
+ *     - vci
+ *     - cleanup
+ *     - coherency
  */
 
 // implementation
 #ifndef CC_XCACHE_WRAPPER_SELECT_VICTIM
-#define CC_XCACHE_WRAPPER_SELECT_VICTIM             0
+#define CC_XCACHE_WRAPPER_SELECT_VICTIM               1
 #endif
 #ifndef CC_XCACHE_WRAPPER_FIFO_RSP
-#define CC_XCACHE_WRAPPER_FIFO_RSP                  0
+#define CC_XCACHE_WRAPPER_FIFO_RSP                    1
 #endif
 #ifndef CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
-#define CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE     1
+#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
+#define CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT   1
 #endif
 #ifndef CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME
-#define CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME        0
+#define CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME          2
 #endif
 #ifndef CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY
-#define CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY          2
+#define CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY            4
+#endif  
+#ifndef CC_XCACHE_WRAPPER_MULTI_CACHE
+#define CC_XCACHE_WRAPPER_MULTI_CACHE                 2
 #endif  
 // debugging
 #ifndef CC_XCACHE_WRAPPER_STOP_SIMULATION
-#define CC_XCACHE_WRAPPER_STOP_SIMULATION           1
+#define CC_XCACHE_WRAPPER_STOP_SIMULATION             1
 #endif
 #ifndef CC_XCACHE_WRAPPER_DEBUG
-#define CC_XCACHE_WRAPPER_DEBUG                     0
+#define CC_XCACHE_WRAPPER_DEBUG                       0
 #endif
 #ifndef CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN
-#define CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN           200000
-#endif
-#ifndef CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
-#define CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION  0
+#define CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN             949900
+#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
+
+// 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
 
@@ -204,6 +223,7 @@
     enum cleanup_fsm_state_e {
         CLEANUP_IDLE,
-        CLEANUP_DCACHE,
-        CLEANUP_ICACHE,
+        CLEANUP_REQ,
+        CLEANUP_RSP_DCACHE,
+        CLEANUP_RSP_ICACHE,
     };
 
@@ -231,5 +251,5 @@
     sc_in<bool>                             p_clk;
     sc_in<bool>                             p_resetn;
-    sc_in<bool>                             p_irq[iss_t::n_irq];
+    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;
@@ -241,8 +261,12 @@
     const soclib::common::AddressDecodingTable<vci_addr_t, bool>    m_cacheability_table;
     const soclib::common::Segment                                   m_segment;
-    iss_t               m_iss;
+    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;
@@ -258,41 +282,48 @@
     bool                m_stop_simulation;
     uint32_t            m_stop_simulation_nb_frz_cycles_max;
-    uint32_t            m_stop_simulation_nb_frz_cycles;
+    uint32_t          * m_stop_simulation_nb_frz_cycles; //[m_nb_cpu]
 #endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
 
     // REGISTERS
-    sc_signal<int>          r_dcache_fsm;
-    sc_signal<int>          r_dcache_fsm_save;
-    sc_signal<addr_40>      r_dcache_addr_save;
-    sc_signal<data_t>       r_dcache_wdata_save;
-    sc_signal<data_t>       r_dcache_rdata_save;
-    sc_signal<int>          r_dcache_type_save;
-    sc_signal<be_t>         r_dcache_be_save;
-    sc_signal<bool>         r_dcache_cached_save;
-    sc_signal<bool>         r_dcache_cleanup_req;
-    sc_signal<addr_40>      r_dcache_cleanup_line;
-    sc_signal<bool>         r_dcache_miss_req;
-    sc_signal<size_t>       r_dcache_miss_way;
-    sc_signal<size_t>       r_dcache_miss_set;
-    sc_signal<bool>         r_dcache_unc_req;
-    sc_signal<bool>         r_dcache_sc_req;
-    sc_signal<bool>         r_dcache_inval_rsp;
-    sc_signal<size_t>       r_dcache_update_addr;
-    sc_signal<data_64>      r_dcache_ll_data;
-    sc_signal<addr_40>      r_dcache_ll_addr;
-    sc_signal<bool>         r_dcache_ll_valid;
-    sc_signal<bool>         r_dcache_previous_unc;
-
-    sc_signal<int>          r_icache_fsm;
-    sc_signal<int>          r_icache_fsm_save;
-    sc_signal<addr_40>      r_icache_addr_save;
-    sc_signal<bool>         r_icache_miss_req;
-    sc_signal<size_t>       r_icache_miss_way;
-    sc_signal<size_t>       r_icache_miss_set;
-    sc_signal<bool>         r_icache_unc_req;
-    sc_signal<bool>         r_icache_cleanup_req;
-    sc_signal<addr_40>      r_icache_cleanup_line;
-    sc_signal<bool>         r_icache_inval_rsp;
-    sc_signal<size_t>       r_icache_update_addr;
+    sc_signal<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<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<uint32_t>   * r_dcache_num_cpu_save; //[m_nb_dcache]
+    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;
@@ -301,24 +332,24 @@
     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<bool>         r_vci_rsp_ins_error;    
-    sc_signal<bool>         r_vci_rsp_data_error;    
     sc_signal<size_t>       r_vci_rsp_cpt;  
-    sc_signal<bool>         r_vci_rsp_ack;
+              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
-    std::queue<data_t>      r_icache_miss_buf;
-    std::queue<data_t>      r_dcache_miss_buf;
+    std::queue<data_t>    * r_icache_miss_buf;    //[m_nb_icache]
+    std::queue<data_t>    * r_dcache_miss_buf;    //[m_nb_dcache]
 #else
-    bool                   *r_icache_miss_val;    //[m_icache_words]
-    data_t                 *r_icache_miss_buf;    //[m_icache_words]
-    bool                   *r_dcache_miss_val;    //[m_dcache_words]
-    data_t                 *r_dcache_miss_buf;    //[m_dcache_words]
-#endif
-    sc_signal<bool>         r_icache_buf_unc_valid;
-
-    data_t                 *r_tgt_buf;            //[m_cache_words]
-    be_t                   *r_tgt_be;             //[m_cache_words]
+    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;
@@ -326,5 +357,6 @@
 
     sc_signal<int>          r_vci_tgt_fsm;
-    sc_signal<addr_40>      r_tgt_addr;
+    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;
@@ -335,64 +367,96 @@
     sc_signal<size_t>       r_tgt_trdid;
   //sc_signal<size_t>       r_tgt_plen;
-    sc_signal<bool>         r_tgt_icache_req;
-    sc_signal<bool>         r_tgt_dcache_req;
-    sc_signal<bool>         r_tgt_icache_rsp;
-    sc_signal<bool>         r_tgt_dcache_rsp;
+    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
-
-    MultiWriteBuffer<addr_40>   r_wbuf;
-    GenericCache<vci_addr_t>    r_icache;
-    GenericCache<vci_addr_t>    r_dcache;
-
-#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
-    std::ofstream               log_dcache_transaction_file;
+    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
+    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
 
     // 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_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_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:
@@ -409,4 +473,6 @@
                        const soclib::common::IntTab &initiator_index_c,
                        const soclib::common::IntTab &target_index,
+                       size_t nb_cpu,
+                       size_t nb_cache,
                        size_t icache_ways,
                        size_t icache_sets,
@@ -435,5 +501,10 @@
     void genMoore();
 
-    soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC);
+    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);
 };
Index: trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp	(revision 139)
+++ trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp	(revision 140)
@@ -55,49 +55,127 @@
 ///////////////////////////////////////////////////////////////////////////////
 
-#include <cassert>
 #include <iomanip>
 #include "arithmetics.h"
+#include "size.h"
 #include "../include/vci_cc_xcache_wrapper_v4.h"
 
+// =====[ DEBUG ]====================================
+
+#define ASSERT_VERBOSE
+#define ASSERT_NCYCLES m_cpt_total_cycles
+
+#include "debug.h"
+
 #if CC_XCACHE_WRAPPER_DEBUG
-# define PRINTF(msg...) do { if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) printf(msg); } while (0); 
+# define PRINTF(msg...) PRINTF_COND(m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN,msg)
 #else
 # define PRINTF(msg...)
 #endif
 
-# define ASSERT(cond,msg) assert ((cond) and msg);
-
+// =====[ FIFO_RSP ]=================================
+
+// FIXME : une FIFO avec le numéro du cache !
 #if CC_XCACHE_WRAPPER_FIFO_RSP
-# define CACHE_MISS_BUF_ALLOC
-# define CACHE_MISS_BUF_DEALLOC
-# define CACHE_MISS_BUF_RESET(c)        while (r_##c##cache_miss_buf.size()>0) {r_##c##cache_miss_buf.pop();}
-# define CACHE_MISS_BUF_REQ_INIT(c)
-# define CACHE_MISS_BUF_RSP_VAL(c,n)    (r_##c##cache_miss_buf.size()>0)
-# define CACHE_MISS_BUF_RSP_ACK(c)      (r_##c##cache_miss_buf.size()<2)
-# define CACHE_MISS_BUF_RSP_DATA(c,n)   r_##c##cache_miss_buf.front()
-# define CACHE_MISS_BUF_RSP_POP(c)      do { r_##c##cache_miss_buf.pop();} while (0)
-# define CACHE_MISS_BUF_RSP_PUSH(c,n,d) do { r_##c##cache_miss_buf.push(d);} while (0)
-# define CACHE_MISS_BUF_RSP_PRINT(c)    do { PRINTF("    * cache_miss_buf - size : %d\n",r_##c##cache_miss_buf.size());} while (0)
+# 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)
+#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
-# define CACHE_MISS_BUF_ALLOC           do { \
-                                        r_icache_miss_val = new bool  [m_icache_words]; \
-                                        r_icache_miss_buf = new data_t[m_icache_words]; \
-                                        r_dcache_miss_val = new bool  [m_dcache_words]; \
-                                        r_dcache_miss_buf = new data_t[m_dcache_words]; \
-                                        } while (0)
-# define CACHE_MISS_BUF_DEALLOC         do { \
-                                        delete [] r_icache_miss_val; \
-                                        delete [] r_icache_miss_buf; \
-                                        delete [] r_dcache_miss_val; \
-                                        delete [] r_dcache_miss_buf; \
-                                        } while (0)
-# define CACHE_MISS_BUF_RESET(c)
-# define CACHE_MISS_BUF_REQ_INIT(c)     do {for (uint32_t i=0; i<m_##c##cache_words;++i) r_##c##cache_miss_val[i] = false;} while (0)
-# define CACHE_MISS_BUF_RSP_VAL(c,n)    r_##c##cache_miss_val[n]
-# define CACHE_MISS_BUF_RSP_ACK(c)      true
-# define CACHE_MISS_BUF_RSP_DATA(c,n)   r_##c##cache_miss_buf[n]
-# define CACHE_MISS_BUF_RSP_POP(c)
-# define CACHE_MISS_BUF_RSP_PUSH(c,n,d) do {r_##c##cache_miss_val[n] = true; r_##c##cache_miss_buf[n] = d;} while (0)
-# define CACHE_MISS_BUF_RSP_PRINT(c)    do {for (uint32_t i=0; i<m_##c##cache_words;++i) PRINTF("%d %x |",r_##c##cache_miss_val[i],r_##c##cache_miss_buf[i]); PRINTF("\n");} while (0)
+#error "Invalid value to CC_XCACHE_WRAPPER_MULTI_CACHE"
 #endif
 
@@ -170,6 +248,7 @@
         const char *cleanup_fsm_state_str[] = {
             "CLEANUP_IDLE",
-            "CLEANUP_DCACHE",
-            "CLEANUP_ICACHE",
+            "CLEANUP_REQ",
+            "CLEANUP_RSP_DCACHE",
+            "CLEANUP_RSP_ICACHE",
         };
     }
@@ -189,4 +268,6 @@
             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,
@@ -210,51 +291,26 @@
             m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()),
             m_segment(mtc.getSegment(target_index)),
-            m_iss(this->name(), proc_id),
             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)+2),
+            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)+2),
+            m_icache_words_shift(uint32_log2(icache_words)+uint32_log2(sizeof(data_t))),
             m_icache_yzmask((~0)<<m_icache_words_shift),
             m_cache_words((dcache_words)?dcache_words:icache_words),
 
-            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_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_cpu_prior("r_cpu_prior"),
 
             r_vci_cmd_fsm("r_vci_cmd_fsm"),
@@ -263,12 +319,10 @@
             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_ins_error("r_vci_rsp_ins_error"),
-            r_vci_rsp_data_error("r_vci_rsp_data_error"),
             r_vci_rsp_cpt("r_vci_rsp_cpt"),
-            r_vci_rsp_ack("r_vci_rsp_ack"),
-
-            r_icache_buf_unc_valid("r_icache_buf_unc_valid"),
+          //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
@@ -277,5 +331,6 @@
 
             r_vci_tgt_fsm("r_vci_tgt_fsm"),
-            r_tgt_addr("r_tgt_addr"),
+            r_tgt_iaddr("r_tgt_iaddr"),
+            r_tgt_daddr("r_tgt_daddr"),
             r_tgt_word("r_tgt_word"),
             r_tgt_update("r_tgt_update"),
@@ -286,26 +341,236 @@
             r_tgt_trdid("r_tgt_trdid"),
          // r_tgt_plen("r_tgt_plen"),
-            r_tgt_icache_req("r_tgt_icache_req"),
-            r_tgt_dcache_req("r_tgt_dcache_req"),
-            r_tgt_icache_rsp("r_tgt_icache_rsp"),
-            r_tgt_dcache_rsp("r_tgt_dcache_rsp"),
+            r_tgt_num_cache("r_tgt_num_cache"),
 
             r_cleanup_fsm("r_cleanup_fsm"),
-
-            r_wbuf("r_wbuf", wbuf_nwords, wbuf_nlines, wbuf_timeout, dcache_words),
-            r_icache("icache", icache_ways, icache_sets, icache_words),
-            r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
+            r_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),
-                        "I need more PLEN bits");
-
-                ASSERT( (vci_param::T > 2) and ((1<<(vci_param::T-1)) >= wbuf_nlines),
-                        "I need more TRDID 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 .");
+
+                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_tgt_buf = new data_t[m_cache_words];
-                r_tgt_be  = new be_t  [m_cache_words];
+                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_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_num_cpu_save  = new sc_signal<uint32_t>   [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_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;
+
+
+                std::cout << "<VciCcXCacheWrapperV4> 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;
+
+                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);
@@ -316,5 +581,4 @@
                 dont_initialize();
                 sensitive << p_clk.neg();
-
 
                 typename iss_t::CacheInfo cache_info;
@@ -326,16 +590,47 @@
                 cache_info.dcache_assoc     = dcache_ways;
                 cache_info.dcache_n_lines   = dcache_sets;
-                m_iss.setCacheInfo(cache_info);
-
+
+                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 = 0;
+                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_DCACHE_TRANSACTION
-                std::ostringstream filename("");
-                filename << "Instruction_flow_" << proc_id << ".log";
-                
-                log_dcache_transaction_file.open(filename.str().c_str() ,std::ios::out | std::ios::trunc);
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                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
             } // end constructor
@@ -345,12 +640,127 @@
     ///////////////////////////////////
     {
-#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
-        log_dcache_transaction_file.close();
-#endif
-
+        delete [] m_stop_simulation_nb_frz_cycles;
+
+#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 [] 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_tgt_be ;
+
+        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   ;
+
+        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;
     }
 
@@ -359,6 +769,7 @@
     ////////////////////////
     {
+        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) << std::endl ;
+                  << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles[num_cpu]) << std::endl ;
     }
     ////////////////////////
@@ -366,12 +777,15 @@
     ////////////////////////
     {
-        float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
-
         uint32_t m_cpt_data_read_cached  = m_cpt_data_read-m_cpt_data_read_uncached;
         uint32_t m_cpt_data_write_cached = m_cpt_data_write-m_cpt_data_write_uncached;
         std::cout << "------------------------------------" << std:: dec << std::endl;
         std::cout << "CPU " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
-        std::cout << "- CPI                            : " << (float)m_cpt_total_cycles/run_cycles << std::endl ;
-        std::cout << "- IPC                            : " << (float)run_cycles/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 ;
@@ -404,7 +818,54 @@
         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 << "%)" << std::endl;
+
+        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 ;
 
-        r_wbuf.printStatistics();
+        for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache)
+            r_wbuf[num_cache]->printStatistics();
     }
 
@@ -421,11 +882,18 @@
         typename iss_t::DataRequest         dreq;
 
-        m_iss.getRequests( ireq, dreq );
         std::cout << std::dec << "Proc \"" << name() << "\"" << std::endl;
-        std::cout << ireq << std::endl;
-        std::cout << dreq << std::endl;
-        std::cout << "  " << dcache_fsm_state_str[r_dcache_fsm]
-                  << "  " << icache_fsm_state_str[r_icache_fsm]
-                  << "  " << cmd_fsm_state_str[r_vci_cmd_fsm]
+
+        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]
@@ -434,27 +902,19 @@
         if(mode & 0x1)
         {
-            r_wbuf.printTrace((mode>>1)&1);
+            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;
-            r_dcache.printTrace();
+            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;
-            r_icache.printTrace();
+            for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+                r_icache[num_cache]->printTrace();
         }
-
-        // if(mode & 0x10)
-        // {
-        //     std::cout << "  Icache miss buffer : ";
-        //     CACHE_MISS_BUF_RSP_PRINT(i);
-        //     std::cout << std::endl;
-
-        //     std::cout << "  Dcache miss buffer : ";
-        //     CACHE_MISS_BUF_RSP_PRINT(d);
-        //     std::cout << std::endl;
-        // }
     }
 
@@ -465,9 +925,24 @@
         if ( not p_resetn.read() ) {
 
-            m_iss.reset();
+            r_cpu_prior = 0;
+
+            for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu)
+                m_iss[num_cpu]->reset();
 
             // FSM states
-            r_dcache_fsm  = DCACHE_IDLE;
-            r_icache_fsm  = ICACHE_IDLE;
+            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;
@@ -475,24 +950,53 @@
             r_cleanup_fsm = CLEANUP_IDLE;
 
+            for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache)
+            {
             // write buffer & caches
-            r_wbuf.reset();
-            r_icache.reset();
-            r_dcache.reset();
+            r_icache[num_cache]->reset();
 
             // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI  FSMs
-            r_icache_miss_req    = false;
-            r_icache_unc_req     = false;
-            r_icache_cleanup_req = false;
-            r_dcache_miss_req    = false;
-            r_dcache_unc_req     = false;
-            r_dcache_sc_req      = false;
-            r_dcache_cleanup_req = false;
-            r_dcache_previous_unc= false;
+            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     = false;
-            r_tgt_dcache_req     = false;
-            r_tgt_icache_rsp     = false;
-            r_tgt_dcache_rsp     = false;
+            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
@@ -500,17 +1004,5 @@
 #endif
 
-
-            // internal messages in DCACHE et ICACHE FSMs
-            r_icache_inval_rsp   = false;
-            r_dcache_inval_rsp   = false;
-
-            // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs
-            r_dcache_ll_valid      = false;
-            r_icache_buf_unc_valid = false;
-
             r_vci_cmd_dcache_prior = false;
-
-            r_vci_rsp_data_error   = false;
-            r_vci_rsp_ins_error    = false;
 
             CACHE_MISS_BUF_RESET(i);
@@ -535,5 +1027,6 @@
             m_cpt_cc_update_dcache_word_useful = 0;
 
-            m_cpt_frz_cycles   = 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;
 
@@ -563,4 +1056,28 @@
             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;
+
+                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;
+
+                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;
         }
@@ -569,22 +1086,43 @@
 
         PRINTF("--------------------------------------------\n");
-        PRINTF("  * CC_XCACHE_WRAPPER \"%s\" - Time = %d\n",name().c_str(),(uint32_t)m_cpt_total_cycles);
-        PRINTF("    * fsm dcache          = %s\n",dcache_fsm_state_str[r_dcache_fsm]);
-        PRINTF("    * fsm icache          = %s\n",icache_fsm_state_str[r_icache_fsm]);
-        PRINTF("    * fsm cmd             = %s\n",cmd_fsm_state_str[r_vci_cmd_fsm]);
-        PRINTF("    * fsm rsp             = %s\n",rsp_fsm_state_str[r_vci_rsp_fsm]);
-        PRINTF("    * fsm tgt             = %s\n",tgt_fsm_state_str[r_vci_tgt_fsm]);
-        PRINTF("    * fsm cleanup         = %s\n",cleanup_fsm_state_str[r_cleanup_fsm]);
-        PRINTF("    * ll info             : %d %llx %llx\n",r_dcache_ll_valid.read(), (uint64_t)r_dcache_ll_addr.read(), (uint64_t)r_dcache_ll_data.read());
-        PRINTF("    * dcache_previous_unc : %d\n",r_dcache_previous_unc.read());
+        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(),(uint64_t)r_dcache_addr_save[num_cache].read(),(uint64_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(),(uint64_t)r_icache_addr_save[num_cache].read(),(uint64_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],(uint64_t)r_tgt_iaddr.read(),(uint64_t)r_tgt_daddr.read());
+      //PRINTF("    * fsm tgt                 =      %s - %llx\n",tgt_fsm_state_str[r_vci_tgt_fsm],(uint64_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()
+                       ,(uint64_t)r_dcache_ll_addr  [num_cache][num_cpu].read()
+                       ,(uint64_t)set_num_dcache_only(r_dcache_ll_addr [num_cache][num_cpu].read(),num_cache)
+                       ,(uint64_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
+        }
         // CACHE_MISS_BUF_RSP_PRINT(i);
         // CACHE_MISS_BUF_RSP_PRINT(d);
 
-#if CC_XCACHE_WRAPPER_DEBUG
-        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
-            {
-                r_wbuf.printTrace(1);
-            }
-#endif
+        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++;
@@ -626,5 +1164,5 @@
                 if ( p_vci_tgt.cmdval.read() ) 
                 {
-                    PRINTF("    * <TGT> request\n");
+                    PRINTF("    * <TGT> Request\n");
 
                     addr_40 address = p_vci_tgt.address.read();
@@ -634,5 +1172,5 @@
                         std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
                         std::cout << "coherence request is not a write" << std::endl;
-                        std::cout << "oddress = " << std::hex << address << std::dec << std::endl;
+                        std::cout << "address = " << std::hex << address << std::dec << std::endl;
                         std::cout << "srcid   = " << p_vci_tgt.srcid.read() << std::endl;
                         exit(0);
@@ -644,20 +1182,26 @@
                         std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
                         std::cout << "out of segment coherence request" << std::endl;
-                        std::cout << "oddress = " << std::hex << address << std::dec << std::endl;
+                        std::cout << "address = " << std::hex << address << std::dec << std::endl;
                         std::cout << "srcid   = " << p_vci_tgt.srcid.read() << std::endl;
                         exit(0);
                     }
 
-                    r_tgt_addr = (((addr_40) ((p_vci_tgt.be.read() & 0x3) << 32)) | 
-                                 ((addr_40) (p_vci_tgt.wdata.read()))) * m_dcache_words * 4;      
-                    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();
+                    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",(uint64_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();
                     
-                    PRINTF("    * <TGT> address : %llx\n",(uint64_t)address);
-                    PRINTF("    * <TGT> address : %llx\n",(uint64_t)((((addr_40) ((p_vci_tgt.be.read() & 0x3) << 32)) | 
-                                                                      ((addr_40) (p_vci_tgt.wdata.read()))) * m_dcache_words * 4));
-
+                    // BROADCAST
                     if ( (address&0x3) == 0x3 )   // broadcast invalidate for data or instruction type
                     {
@@ -671,5 +1215,27 @@
                         // 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
+                        {
+                            log_transaction_file_tgt
+                                << "[" << m_cpt_total_cycles << "] "
+                                << "BROADCAST  "
+                                << std::hex
+                                << " L " << std::setw(10) << (uint64_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
@@ -677,4 +1243,5 @@
                         uint32_t cell = address - m_segment.baseAddress(); // addr_40
                         // r_tgt_brdcast = false;
+
                         if (cell == 0) 
                         {                                       // invalidate data
@@ -687,5 +1254,25 @@
                             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
+                            {
+                                log_transaction_file_tgt
+                                    << "[" << m_cpt_total_cycles << "] "
+                                    << "INVAL DATA "
+                                    << std::hex
+                                    << " L " << std::setw(10) << (uint64_t)tgt_addr
+                                    << std::dec 
+                                    << " - " << tgt_num_cache
+                                    << std::endl;
+                            }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
                         } 
                         else if (cell == 4)                     // invalidate instruction
@@ -699,5 +1286,26 @@
                             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
+                            {
+                                log_transaction_file_tgt
+                                    << "[" << m_cpt_total_cycles << "] "
+                                    << "INVAL INS  "
+                                    << std::hex
+                                    << " L " << std::setw(10) << (uint64_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
@@ -713,4 +1321,23 @@
                                 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
+                                {
+                                    log_transaction_file_tgt
+                                        << "[" << m_cpt_total_cycles << "] "
+                                        << "UPT DATA   "
+                                        << std::hex
+                                        << " L " << std::setw(10) << (uint64_t)tgt_addr
+                                        << std::dec
+                                        << " - " << tgt_num_cache
+                                        << std::endl;
+                                }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
                             }
                             else
@@ -718,4 +1345,24 @@
                                 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
+                                {
+                                    log_transaction_file_tgt
+                                        << "[" << m_cpt_total_cycles << "] "
+                                        << "UPT INS    "
+                                        << std::hex
+                                        << " L " << std::setw(10) << (uint64_t)tgt_addr
+                                        << std::dec
+                                        << " - " << tgt_num_cache
+                                        << std::endl;
+                                }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
                             }
                             r_tgt_update = true; 
@@ -724,4 +1371,9 @@
 
                     } // end if address
+                    
+                    r_tgt_iaddr      = tgt_iaddr;
+                    r_tgt_daddr      = tgt_daddr;
+                    PRINTF("    * <TGT> address (after)  : i %llx, d %llx\n",(uint64_t)tgt_iaddr,(uint64_t)tgt_daddr);
+
                 } // end if cmdval
                 break;
@@ -739,5 +1391,5 @@
                     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_addr.read() << " word : " << p_vci_tgt.wdata.read() << std::dec << std::endl;
+                    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;
@@ -789,9 +1441,27 @@
 
             case TGT_REQ_BROADCAST:
-                if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() ) 
-                {
-                    r_vci_tgt_fsm = TGT_RSP_BROADCAST; 
-                    r_tgt_icache_req = true;
-                    r_tgt_dcache_req = true;
+                {
+                    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;
@@ -799,8 +1469,9 @@
             case TGT_REQ_ICACHE:
                 {
-                    if ( not r_tgt_icache_req.read() ) 
+                    // 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 = true;
+                        r_tgt_icache_req[r_tgt_num_cache] = true;
                     }
                     break;
@@ -808,63 +1479,252 @@
 
             case TGT_REQ_DCACHE:
-                if ( not r_tgt_dcache_req.read() ) 
-                {
-                    r_vci_tgt_fsm = TGT_RSP_DCACHE; 
-                    r_tgt_dcache_req = true;
-                }
-                break;
-
+                {
+                    // 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:
-                if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() ) 
-                {
-                    // one response
-                    if ( not r_tgt_icache_rsp or not r_tgt_dcache_rsp )
+                {
+                    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()) 
                     {
-                        if ( p_vci_tgt.rspack.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)
                         {
-                            r_vci_tgt_fsm = TGT_IDLE; 
-                            r_tgt_icache_rsp = false;
-                            r_tgt_dcache_rsp = false;
+                            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;
                         }
-                    }
-
-                    // if data and instruction have the inval line, need two responses  
-                    if ( r_tgt_icache_rsp and r_tgt_dcache_rsp )
-                    {
-                        if ( p_vci_tgt.rspack.read() )
+
+                        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])
                         {
-                            r_tgt_icache_rsp = false; // only reset one for respond the second time 
+                            // 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;
+                            }
                         }
-                    }
-
-                    // if there is no need for a response
-                    if ( not r_tgt_icache_rsp and not r_tgt_dcache_rsp )
+
+                        // // 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);
+                        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;
-                    }
-
-                }
-                break;
-                ////////////////////
-            case TGT_RSP_ICACHE:
-                {
-                    if ( (p_vci_tgt.rspack.read() or not r_tgt_icache_rsp.read()) and not r_tgt_icache_req.read() ) 
+                        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_icache_rsp = false; 
+                        r_tgt_dcache_rsp[r_tgt_num_cache] = false; 
                     }
                     break;
                 }
-
-            case TGT_RSP_DCACHE:
-                {
-                    if ( (p_vci_tgt.rspack.read() or not r_tgt_dcache_rsp.read()) and not r_tgt_dcache_req.read() ) 
-                    {
-                        r_vci_tgt_fsm = TGT_IDLE;
-                        r_tgt_dcache_rsp = 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);
+
+            // test if already used
+            if (not ireq[num_cache].valid and
+                (r_icache_lock [num_cache] == m_nb_cpu) or
+                (r_icache_lock [num_cache] == num_cpu))
+            {
+                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);
+
+            // test if already used
+            if (not dreq[num_cache].valid and
+                not have_sync and
+                (r_dcache_lock [num_cache] == m_nb_cpu) or
+                (r_dcache_lock [num_cache] == num_cpu))
+            {
+                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;
+                    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;
 
         /////////////////////////////////////////////////////////////////////
@@ -899,75 +1759,85 @@
         //    flip-flop. It is reset by the ICACHE FSM.
         ///////////////////////////////////////////////////////////////////////
-
-        typename iss_t::InstructionRequest  ireq = ISS_IREQ_INITIALIZER;
-        typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
-
-        typename iss_t::DataRequest         dreq = ISS_DREQ_INITIALIZER;
-        typename iss_t::DataResponse        drsp = ISS_DRSP_INITIALIZER;
-
-        m_iss.getRequests( ireq, dreq );
-
-#if CC_XCACHE_WRAPPER_DEBUG
-        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
-            std::cout << "    * Instruction Request  : " << ireq << std::endl;
-#endif
-
-        switch(r_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 ) {   // external request
-                        if ( ireq.valid ) m_cost_ins_miss_frz++;
-                        r_icache_fsm = ICACHE_CC_CHECK;
-                        r_icache_fsm_save = r_icache_fsm.read();
+                    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 = m_cacheability_table[(vci_addr_t)ireq.addr];
-                        bool    icache_cleanup_hit = r_icache_cleanup_req and (((addr_40)ireq.addr >> (addr_40)m_icache_words_shift) == r_icache_cleanup_line.read());
+                    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.read((vci_addr_t) ireq.addr, &icache_ins);
+                            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 and ((addr_40) ireq.addr == (addr_40)r_icache_addr_save));
-                            icache_ins = CACHE_MISS_BUF_RSP_DATA(i,0);
-                            CACHE_MISS_BUF_RSP_POP(i);
+                            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> hit %d - cached %d - cleanup_hit %d\n",icache_hit, icache_cached, icache_cleanup_hit);
-
-                        ASSERT( not (icache_hit and icache_cleanup_hit),
-                                "Icache hit and icache_cleanup_hit");
-
-                        if ( not icache_hit and not icache_cleanup_hit) {
-                            m_cpt_ins_miss++;
-                            m_cost_ins_miss_frz++;
-                            r_icache_addr_save = (addr_40) ireq.addr;
-
-                            CACHE_MISS_BUF_REQ_INIT(i);
-
-                            if ( icache_cached ) {
+                        PRINTF("    * <ICACHE [%d]> hit %d - cached %d - cleanup_hit %d\n",num_cache, icache_hit, icache_cached, icache_cleanup_hit);
+
+                        // ASSERT( not (icache_hit and icache_cleanup_hit),
+                        //         "Icache hit and 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;
+                                
+                                CACHE_MISS_BUF_REQ_INIT(i,num_cache);
+                                
+                                if ( icache_cached )
+                                {
 #if CC_XCACHE_WRAPPER_SELECT_VICTIM
-                                r_icache_fsm = ICACHE_MISS_VICTIM;
+                                    r_icache_fsm     [num_cache] = ICACHE_MISS_VICTIM;
 #else
-                                r_icache_fsm = ICACHE_MISS_WAIT;
-#endif
-                                r_icache_miss_req = true;
-                               
-                            } else {
-                                r_icache_fsm = ICACHE_UNC_WAIT;
-                                r_icache_unc_req = true;
+                                    r_icache_fsm     [num_cache] = ICACHE_MISS_WAIT;
+#endif
+                                    r_icache_miss_req[num_cache] = true;
+                                    
+                                }
+                                else
+                                {
+                                    r_icache_fsm    [num_cache] = ICACHE_UNC_WAIT;
+                                    r_icache_unc_req[num_cache] = true;
+                                }
                             }
-                        } else {
-                            r_icache_buf_unc_valid = false;
+                            else
+                            {
+                                r_icache_buf_unc_valid[num_cache] = false;
+                            }
+                            m_cpt_icache_dir_read += m_icache_ways;
+                            m_cpt_icache_data_read += m_icache_ways;
                         }
-                        m_cpt_icache_dir_read += m_icache_ways;
-                        m_cpt_icache_data_read += m_icache_ways;
-                        irsp.valid          = icache_hit;
-                        irsp.instruction    = icache_ins;
+
+                        _irsp.valid          = icache_hit;
+                        _irsp.instruction    = icache_ins;
                     }
                     break;
@@ -977,17 +1847,17 @@
             case ICACHE_MISS_VICTIM:
                 {
-                    if (not r_icache_cleanup_req)
+                    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.read();
+                        vci_addr_t addr = (vci_addr_t) r_icache_addr_save[num_cache].read();
                         vci_addr_t victim;
                         
-                        r_icache_cleanup_req  = r_icache.victim_select(addr, &victim, &way, &set );
-                        r_icache_cleanup_line = (addr_40) victim;
-                        r_icache_miss_way     = way;
-                        r_icache_miss_set     = set;
+                        r_icache_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 = ICACHE_MISS_WAIT;
+                        r_icache_fsm         [num_cache] = ICACHE_MISS_WAIT;
                     }
                     break;
@@ -998,45 +1868,32 @@
                 {
                     m_cost_ins_miss_frz++;
-                    if ( r_tgt_icache_req ) {   // external request
-                        r_icache_fsm = ICACHE_CC_CHECK;
-                        r_icache_fsm_save = r_icache_fsm.read();
+                    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,0);
-
-                    PRINTF("    * <ICACHE> val                  : %d\n",val);
+                    bool val = CACHE_MISS_BUF_RSP_VAL(i,num_cache,0);
+
+                    PRINTF("    * <ICACHE [%d]> val                  : %d\n",num_cache,val);
 
                     if (val)
                     {
-                        PRINTF("    * <ICACHE> r_icache_inval_rsp   : %d\n",(int) r_icache_inval_rsp  );
-                        PRINTF("    * <ICACHE> r_vci_rsp_ins_error  : %d\n",(int) r_vci_rsp_ins_error );
-                        PRINTF("    * <ICACHE> r_icache_cleanup_req : %d\n",(int) r_icache_cleanup_req);
-
-                        // if (not r_icache_inval_rsp )
-                        // {
-                            // Miss read response and no invalidation
-                            if ( r_vci_rsp_ins_error ) {
-                                r_icache_fsm = ICACHE_ERROR;
-                            } else {
+                        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 {
 #if not CC_XCACHE_WRAPPER_SELECT_VICTIM
-                                if (not r_icache_cleanup_req.read())
-#endif
-                                {
-                                    r_icache_update_addr = 0;
-                                    r_icache_fsm         = ICACHE_MISS_UPDT;
-                                }
+                            if (not r_icache_cleanup_req[num_cache].read())
+#endif
+                            {
+                                r_icache_update_addr[num_cache] = 0;
+                                r_icache_fsm        [num_cache] = ICACHE_MISS_UPDT;
                             }
-                        // }
-                        // else
-                        // {
-                        //     r_icache_inval_rsp = false;
-                            
-                        //     // Miss read response and invalidation
-                        //     if ( r_vci_rsp_ins_error )
-                        //         r_icache_fsm = ICACHE_ERROR;
-                        //     else
-                        //         r_icache_fsm = ICACHE_CC_CLEANUP;
-                        // }
+                        }
                     }
                     break;
@@ -1046,19 +1903,22 @@
                 {
                     m_cost_ins_miss_frz++;
-                    if ( r_tgt_icache_req ) {   // external request
-                        r_icache_fsm = ICACHE_CC_CHECK;
-                        r_icache_fsm_save = r_icache_fsm.read();
+                    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,0);
+                    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 ) {
-                            r_icache_fsm = ICACHE_ERROR;
+                        if ( r_vci_rsp_ins_error [num_cache]) {
+                            r_icache_fsm[num_cache] = ICACHE_ERROR;
                         } else {
-                            r_icache_fsm = ICACHE_IDLE;
-                            r_icache_buf_unc_valid = true;
+                            r_icache_fsm [num_cache] = ICACHE_IDLE;
+                            r_icache_buf_unc_valid[num_cache] = true;
                         }
                     }
@@ -1068,10 +1928,10 @@
             case ICACHE_ERROR:
                 {
-                    if ( (addr_40)ireq.addr == (addr_40)r_icache_addr_save ) {
-                        irsp.error          = true;
-                        irsp.valid          = true;
-                    }
-                    r_icache_fsm = ICACHE_IDLE;
-                    r_vci_rsp_ins_error = false;
+                    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;
                 }
@@ -1079,17 +1939,16 @@
             case ICACHE_MISS_UPDT: 
                 {
-                    size_t     word = r_icache_update_addr.read();
-                    vci_addr_t addr = (vci_addr_t) r_icache_addr_save.read();
+                    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  = 0;
                     size_t     set  = 0;
 
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                    way = r_icache_miss_way[num_cache].read();
+                    set = r_icache_miss_set[num_cache].read();
+#else
                     // need invalid rsp, don't select a victim
-                    if (not r_icache_inval_rsp )
+                    if (not r_icache_inval_rsp[num_cache])
                     {
-#if CC_XCACHE_WRAPPER_SELECT_VICTIM
-                        way = r_icache_miss_way.read();
-                        set = r_icache_miss_set.read();
-#else
-
                         // First word : select an victim !
                         if (word == 0)
@@ -1098,52 +1957,55 @@
                         
                             // r_icache_cleanup_req is false because is the transition condition to go in ICACHE_MISS_UPDT state
-                            r_icache_cleanup_req  = r_icache.victim_select(addr, &victim, &way, &set );
-                            r_icache.victim_update_tag(addr, way, set);
+                            r_icache_cleanup_req[num_cache]  = r_icache[num_cache]->victim_select(addr, &victim, &way, &set );
+                            r_icache[num_cache]->victim_update_tag(addr, way, set);
                         
-                            r_icache_cleanup_line = (addr_40) victim;
-                            r_icache_miss_way     = way;
-                            r_icache_miss_set     = set;
+                            r_icache_cleanup_line[num_cache] = (addr_40) victim;
+                            r_icache_miss_way    [num_cache] = way;
+                            r_icache_miss_set    [num_cache] = set;
                         }
                         else
                         {
-                            way = r_icache_miss_way.read();
-                            set = r_icache_miss_set.read();
+                            way = r_icache_miss_way[num_cache].read();
+                            set = r_icache_miss_set[num_cache].read();
                         }
-#endif
-                    }
-                    bool val = CACHE_MISS_BUF_RSP_VAL(i,word);
+                    }
+#endif
+                    bool val = CACHE_MISS_BUF_RSP_VAL(i,num_cache,word);
 
                     if (val)
                     {
-                        PRINTF("    * <ICACHE> rsp_val            : %d/%d\n",(int)r_icache_update_addr,m_icache_words);
-                        PRINTF("    * <ICACHE> r_icache_inval_rsp : %d\n",(int)r_icache_inval_rsp);
-                        PRINTF("    * <ICACHE> ins : %x\n",(int)CACHE_MISS_BUF_RSP_DATA(i,word));
+                        PRINTF("    * <ICACHE [%d]> rsp_val            : %d/%d\n",num_cache,(int)r_icache_update_addr[num_cache],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 ( _ireq.valid ) m_cost_ins_miss_frz++;
 
                         // if need invalid rsp, don't modify the cache, but pop the buf_rsp
-                        if (not r_icache_inval_rsp )
-                            r_icache.write(way, set, word, CACHE_MISS_BUF_RSP_DATA(i,word));
-                        CACHE_MISS_BUF_RSP_POP(i);
-
-                        r_icache_update_addr = ++word;
+                        if (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)
                         {
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                            // in all case (inval_rsp or not), update the victim tag
+                            r_icache[num_cache]->victim_update_tag(addr, way, set);
+#endif
+
                             // Last word : if previous invalid_rsp, can cleanup, else update the TAG
-                            if (r_icache_inval_rsp)
+                            if (r_icache_inval_rsp[num_cache])
                             {
-                                r_icache_inval_rsp  = false;
-                                r_icache_fsm = ICACHE_CC_CLEANUP;
+                                r_icache_inval_rsp[num_cache] = false;
+                                r_icache_fsm      [num_cache] = ICACHE_CC_CLEANUP;
                             }
                             else
                             {
-#if CC_XCACHE_WRAPPER_SELECT_VICTIM
-                                r_icache.victim_update_tag(addr, way, set);
-#endif
-                                r_icache_fsm = ICACHE_IDLE;
+                                r_icache_fsm [num_cache] = ICACHE_IDLE;
                             }
                         }
@@ -1156,15 +2018,19 @@
                 {
                     // external cache invalidate request
-                    if ( r_tgt_icache_req )     
+                    if ( r_tgt_icache_req[num_cache])     
                     {
-                        r_icache_fsm = ICACHE_CC_CHECK;
-                        r_icache_fsm_save = r_icache_fsm.read();
+                        r_icache_fsm     [num_cache] = ICACHE_CC_CHECK;
+                        r_icache_fsm_save[num_cache] = r_icache_fsm[num_cache].read();
                         break;
                     }
                     // cleanup
-                    if(not r_icache_cleanup_req){
-                        r_icache_cleanup_req = true;
-                        r_icache_cleanup_line = r_icache_addr_save.read() >> m_icache_words_shift;
-                        r_icache_fsm = ICACHE_IDLE;
+                    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;
+
+                        // FIXME : too many access at the cache in this cycle
+                        m_cpt_icache_dir_read += m_icache_ways;
+                        r_icache[num_cache]->inval((addr_40)r_icache_addr_save[num_cache]);
                     }
                     break;
@@ -1176,20 +2042,29 @@
                     m_cpt_icache_dir_read  += m_icache_ways;
                     m_cpt_icache_data_read += m_icache_ways;
-                    addr_40 ad = r_tgt_addr;
+                    addr_40 ad = r_tgt_iaddr;
                     data_t  icache_rdata = 0;
 
-                    if((r_icache_fsm_save == ICACHE_MISS_WAIT) and 
-                            ( (r_icache_addr_save.read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) {
-                        r_icache_inval_rsp = true;
-                        r_tgt_icache_req = false;
+                    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
-                            r_tgt_icache_rsp     = true;
+                            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
-                            r_tgt_icache_rsp     = false;
+                            PRINTF("    * <ICACHE [%d]> send a cleanup and but don't answer\n",num_cache);
+                            r_tgt_icache_rsp[num_cache] = false;
                         }
-                        r_icache_fsm = r_icache_fsm_save;
+                        r_icache_fsm[num_cache] = r_icache_fsm_save[num_cache];
                     } else {
-                        bool    icache_hit   = r_icache.read(ad, &icache_rdata);
-                        if ( icache_hit and r_tgt_update ) 
+                        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
@@ -1198,5 +2073,5 @@
                             data_t   rdata = 0;
 
-                            r_icache.read(ad+word*4,&rdata);
+                            r_icache[num_cache]->read(ad+word*4,&rdata);
                             r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & rdata);
                             
@@ -1210,5 +2085,5 @@
                             if (word==m_icache_words)
                             {
-                                r_icache_fsm = ICACHE_CC_UPDT;
+                                r_icache_fsm[num_cache] = ICACHE_CC_UPDT;
 
 #if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
@@ -1222,23 +2097,23 @@
                             r_cache_word = word;
 #else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
-                            r_icache_fsm = ICACHE_CC_UPDT;
+                            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.read(ad + i*4,&rdata);
+                                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 = ICACHE_CC_INVAL;
+                        } 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 = false;
+                            r_tgt_icache_req[num_cache] = false;
                             if(r_tgt_update){
-                                r_tgt_icache_rsp = true;
+                                r_tgt_icache_rsp[num_cache] = true;
                             } else {
-                                r_tgt_icache_rsp = false;
+                                r_tgt_icache_rsp[num_cache] = false;
                             }
-                            r_icache_fsm = r_icache_fsm_save;
+                            r_icache_fsm[num_cache] = r_icache_fsm_save[num_cache];
                         }
                     }
@@ -1248,11 +2123,11 @@
             case ICACHE_CC_INVAL:  
                 {                       
-                    addr_40    ad  = r_tgt_addr;
-                    if ( ireq.valid ) m_cost_ins_miss_frz++;
+                    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 = true;
-                    r_icache.inval(ad);
-                    r_tgt_icache_req = false;
-                    r_icache_fsm = r_icache_fsm_save;
+                    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;
                 }    
@@ -1260,5 +2135,5 @@
             case ICACHE_CC_UPDT:
                 {                       
-                    addr_40 ad = r_tgt_addr.read();
+                    addr_40 ad = r_tgt_iaddr.read();
                     m_cpt_icache_dir_write++;
                     m_cpt_icache_data_write++;
@@ -1268,5 +2143,5 @@
 
                     if(r_tgt_be[word])
-                        r_icache.write(ad+word*4, r_tgt_buf[word]);
+                        r_icache[num_cache]->write(ad+word*4, r_tgt_buf[word]);
 
                     word ++;
@@ -1279,7 +2154,7 @@
                     if (word==m_icache_words)
                     {
-                        r_tgt_icache_req = false;
-                        r_tgt_icache_rsp = true;
-                        r_icache_fsm     = r_icache_fsm_save.read();
+                        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;
                     }
@@ -1288,9 +2163,9 @@
                     data_t* buf    = r_tgt_buf;
                     for(size_t i=0; i<m_icache_words;i++){
-                        if(r_tgt_be[i]) r_icache.write( ad + i*4, buf[i]);
-                    }
-                    r_tgt_icache_req = false;
-                    r_tgt_icache_rsp = true;
-                    r_icache_fsm     = r_icache_fsm_save.read();
+                        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
 
@@ -1298,10 +2173,16 @@
                 }    
 
-        } // end switch r_icache_fsm
-
-#if CC_XCACHE_WRAPPER_DEBUG
-        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
-            std::cout << "    * Instruction Response : " << irsp << std::endl;
-#endif
+        }// 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
 
         //////////////////////////////////////////////////////////////////////://///////////
@@ -1361,35 +2242,36 @@
         ///////////////////////////////////////////////////////////////////////////////////
 
-#if CC_XCACHE_WRAPPER_DEBUG
-        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
-            std::cout << "    * Data        Request  : " << dreq << std::endl;
-#endif
-
-        switch ( r_dcache_fsm ) {
+        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 ) {   // external request
-                        r_dcache_fsm = DCACHE_CC_CHECK;
-                        r_dcache_fsm_save = r_dcache_fsm;
+                    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> Have dreq\n");
+                    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      = m_cacheability_table[(vci_addr_t)dreq.addr];
-                        bool        dcache_hit         = r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
-                        bool        dcache_cleanup_hit = r_dcache_cleanup_req and (((addr_40)dreq.addr >> (addr_40)m_dcache_words_shift) == r_dcache_cleanup_line.read());
-
-                        PRINTF("    * <DCACHE> hit %d - cached %d - cleanup_hit %d\n",dcache_hit, dcache_cached, dcache_cleanup_hit);
+                        // 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 ) {
+                        switch( _dreq.type ) {
                             case iss_t::DATA_READ:
                             case iss_t::DATA_LL:
@@ -1400,20 +2282,21 @@
                                         {
                                             // address is in the cache : return the word
-                                            r_dcache_fsm = DCACHE_IDLE;
-                                            drsp.valid   = true;
-                                            drsp.rdata   = dcache_rdata; // return read data (cf dcache_hit)
+                                            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)
+                                            if(_dreq.type == iss_t::DATA_LL)
                                                 {
-                                                    PRINTF("    * <DCACHE> ll_valid = true\n");
-
-                                                    r_dcache_ll_valid = true;
-                                                    r_dcache_ll_data = dcache_rdata;
-                                                    r_dcache_ll_addr = (vci_addr_t) dreq.addr;
+                                                    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.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;
+                                                    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
                                                 }
@@ -1423,5 +2306,5 @@
                                             if (not dcache_cleanup_hit)
                                             {
-                                                CACHE_MISS_BUF_REQ_INIT(d);
+                                                CACHE_MISS_BUF_REQ_INIT(d,num_cache);
                                                 
                                                 // Miss : send signal at the CMD_FSM (via r_dcache_miss_req or r_dcache_unc_req)
@@ -1429,20 +2312,20 @@
                                                     m_cpt_data_read_miss++;
                                                     m_cost_data_miss_frz++;
-                                                    r_dcache_miss_req = true;
+                                                    r_dcache_miss_req [num_cache] = true;
 #if CC_XCACHE_WRAPPER_SELECT_VICTIM
-                                                    r_dcache_fsm = DCACHE_MISS_VICTIM;
+                                                    r_dcache_fsm [num_cache] = DCACHE_MISS_VICTIM;
 #else
-                                                    r_dcache_fsm = DCACHE_MISS_WAIT;
+                                                    r_dcache_fsm [num_cache] = DCACHE_MISS_WAIT;
 #endif
                                                     
                                                 } else {
-                                                    if (not r_dcache_previous_unc.read()) // strongly order to the uncached access
+                                                    if (not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access
                                                     {
-                                                        r_dcache_previous_unc = true;
+                                                        r_dcache_previous_unc[num_cache] = true;
                                                         
                                                         m_cpt_data_read_uncached++;
                                                         m_cost_unc_read_frz++;
-                                                        r_dcache_unc_req = true;
-                                                        r_dcache_fsm = DCACHE_UNC_WAIT;
+                                                        r_dcache_unc_req[num_cache] = true;
+                                                        r_dcache_fsm    [num_cache] = DCACHE_UNC_WAIT;
                                                     }
                                                 }
@@ -1453,7 +2336,7 @@
                             case iss_t::DATA_SC:
                             {
-                                PRINTF("    * <DCACHE> DATA_SC - ll_valid = %d\n",r_dcache_ll_valid.read());
-
-                                if (not r_dcache_previous_unc.read() and not dcache_cleanup_hit) // strongly order to the uncached access
+                                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
@@ -1462,20 +2345,20 @@
                                     // if previous load linked (with the same address), make a transaction
                                     // else, keep in IDLE state and return 1 (no OK)
-                                    if(r_dcache_ll_valid.read() and (r_dcache_ll_addr.read() == (vci_addr_t)dreq.addr)){
-                                        PRINTF("    * <DCACHE> have previous load linked\n");
+                                    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 = true;
-
-                                        r_dcache_sc_req   = true;
-
-                                        CACHE_MISS_BUF_REQ_INIT(d);
-
-                                        r_dcache_fsm = DCACHE_SC_WAIT;
+                                        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> don't have previous load linked\n");
+                                        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 = false;
+                                        _drsp.valid = true;
+                                        _drsp.rdata = 1; // SC rsp NOK
+                                        r_dcache_ll_valid[num_cache][dcache_num_cpu] = false;
                                     }
                                 }
@@ -1486,12 +2369,12 @@
                             case iss_t::XTN_WRITE:
                                 {
-                                    bool drsp_valid = false;
+                                    bool valid = false;
                                     // only DCACHE INVALIDATE and SYNC request are supported
-                                    switch (dreq.addr>>2)
+                                    switch (_dreq.addr>>2)
                                         {
                                         case iss_t::XTN_DCACHE_INVAL : 
                                             {
-                                                drsp_valid = true;
-                                                r_dcache_fsm = DCACHE_INVAL;
+                                                valid = true;
+                                                r_dcache_fsm[num_cache] = DCACHE_INVAL;
                                                 break;
                                             }
@@ -1501,13 +2384,19 @@
                                                 //  * gain : 1 cycle
                                                 //  * cost : can be on the critical path
-                                                if (r_wbuf.empty())
+
+                                                bool empty=true;
+                                                for (uint32_t i=0; i<m_nb_dcache; ++i)
+                                                    empty &= r_wbuf[i]->empty();
+
+                                                if (empty)
                                                     {
-                                                        drsp_valid = true;
-                                                        r_dcache_fsm = DCACHE_IDLE;
+                                                        valid = true;
+                                                        r_dcache_fsm [num_cache] = DCACHE_IDLE;
                                                     }
                                                 else
                                                     {
-                                                        drsp_valid = false;
-                                                        r_dcache_fsm = DCACHE_SYNC;
+                                                        valid = false;
+                                                        r_dcache_fsm [num_cache] = DCACHE_SYNC;
+                                                        r_dcache_sync[num_cache] = true;
                                                     }
                                                 break;
@@ -1516,23 +2405,30 @@
                                             {
                                                 // std::cout << "Warning in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
-                                                // std::cout << "Unsupported  external access : " << (dreq.addr>>2) << std::endl;
-
-                                                r_dcache_fsm = DCACHE_IDLE;
+                                                // std::cout << "Unsupported  external access : " << (_dreq.addr>>2) << std::endl;
+
+                                                r_dcache_fsm [num_cache] = DCACHE_IDLE;
                                             }
-                                        }//end switch (dreq.addr>>2)
-
-                                    drsp.valid = drsp_valid;
-                                    drsp.rdata = 0;
+                                        }//end switch (_dreq.addr>>2)
+
+                                    _drsp.valid = valid;
+                                    _drsp.rdata = 0;
                                     break;
                                 }
                             case iss_t::DATA_WRITE:
 
-                                if (dcache_cached or not r_dcache_previous_unc.read()) // strongly order to the uncached access
+                                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 drsp_valid;
-
-                                    drsp_valid = r_wbuf.write((addr_40) dreq.addr, dreq.be, dreq.wdata, dcache_cached);
-
-                                    if (drsp_valid)
+                                    bool valid;
+                                    addr_40 addr = _dreq.addr;
+                                    set_num_dcache(addr,num_cache);
+
+                                    // FIXME : virer le set_num_dcache !
+                                    valid = r_wbuf[num_cache]->write(addr, _dreq.be, _dreq.wdata, dcache_cached);
+
+                                    PRINTF("    * <DCACHE [%d]> r_wbuf valid          : %d\n",num_cache,valid);
+
+                                    if (valid)
                                     {
                                         m_cpt_data_write++;
@@ -1540,5 +2436,5 @@
                                         if (not dcache_cached)
                                         {
-                                            r_dcache_previous_unc = true;
+                                            r_dcache_previous_unc[num_cache] = true;
                                             m_cpt_data_write_uncached++;
                                         }
@@ -1546,26 +2442,29 @@
                                             m_cpt_data_write_miss++;
                                         
-                                        if ( dcache_hit) {
-                                            r_dcache_fsm = DCACHE_WRITE_UPDT;
+                                        if (dcache_hit) {
+                                            // update data cache
+                                            r_dcache_fsm[num_cache] = DCACHE_WRITE_UPDT;
                                         } else {
-                                            r_dcache_fsm = DCACHE_IDLE;
+                                            // write accepted
+                                            r_dcache_fsm [num_cache] = DCACHE_IDLE;
                                         }
                                     }
 
-                                    drsp.valid = drsp_valid;
-                                    drsp.rdata = 0;
+                                    _drsp.valid = valid;
+                                    _drsp.rdata = 0;
                                 }
                                 break;
-                        } // end switch dreq.type
-
-                        r_dcache_addr_save      = (addr_40) dreq.addr;
-                        r_dcache_type_save      = dreq.type;
-                        r_dcache_wdata_save     = dreq.wdata;
-                        r_dcache_be_save        = dreq.be;
-                        r_dcache_rdata_save     = dcache_rdata;
-                        r_dcache_cached_save    = dcache_cached;
-                        
-                    } else {    // end if dreq.valid
-                        r_dcache_fsm = DCACHE_IDLE;
+                        } // 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;
                     }
                     
@@ -1576,10 +2475,10 @@
                 {
                     m_cpt_dcache_data_write++;
-                    data_t mask = vci_param::be2mask(r_dcache_be_save);
-                    data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
-                    vci_addr_t ad = r_dcache_addr_save.read();
-                    r_dcache.write(ad, wdata);
-
-                    r_dcache_fsm = DCACHE_IDLE;
+                    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);
+
+                    r_dcache_fsm [num_cache] = DCACHE_IDLE;
 
                     break;
@@ -1589,17 +2488,20 @@
             case DCACHE_MISS_VICTIM:
                 {
-                    if (not r_dcache_cleanup_req.read())
+                    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.read();
+                         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  = r_dcache.victim_select(addr, &victim, &way, &set );
-                         r_dcache_cleanup_line = (addr_40) victim;
-                         r_dcache_miss_way     = way;
-                         r_dcache_miss_set     = set;
-                         
-                         r_dcache_fsm = DCACHE_MISS_WAIT;
+                         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, (uint64_t)victim, way, set);
+        
+                         r_dcache_fsm          [num_cache] = DCACHE_MISS_WAIT;
                      }
                     
@@ -1611,44 +2513,29 @@
                 {
 
-                    if ( dreq.valid ) m_cost_data_miss_frz++;
-                    if ( r_tgt_dcache_req.read() ) {   // external request
-                        r_dcache_fsm = DCACHE_CC_CHECK;
-                        r_dcache_fsm_save = r_dcache_fsm;
+                    // 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,0);
+                    bool val = CACHE_MISS_BUF_RSP_VAL(d,num_cache,0);
                     if (val)
                     {
-                        // if (not r_dcache_inval_rsp )
-                        //  {
-
                         // Miss read response and no invalidation
-                        if ( r_vci_rsp_data_error )
+                        if (r_vci_rsp_data_error[num_cache])
                         {
-                            r_dcache_fsm = DCACHE_ERROR;
+                            r_dcache_fsm [num_cache] = DCACHE_ERROR;
                         } 
                         else 
                         {
 #if not CC_XCACHE_WRAPPER_SELECT_VICTIM
-                            if (not r_dcache_cleanup_req.read())
+                            if (not r_dcache_cleanup_req[num_cache].read())
 #endif
                             {
-                                r_dcache_update_addr = 0;
-                                r_dcache_fsm         = DCACHE_MISS_UPDT;
+                                r_dcache_update_addr[num_cache] = 0;
+                                r_dcache_fsm        [num_cache] = DCACHE_MISS_UPDT;
                             }
                         }
-                        //  }
-                        // else
-                        // {
-                        //     r_dcache_inval_rsp  = false;
-
-                        //     // Miss read response and invalidation
-                        //     if ( r_vci_rsp_data_error ) {
-                        //         r_dcache_fsm = DCACHE_ERROR;
-                        //     } else {
-                        //         r_dcache_fsm = DCACHE_CC_CLEANUP;
-                        //     }
-                        // }
                     }
                     break;
@@ -1657,16 +2544,16 @@
             case DCACHE_MISS_UPDT:
                 {
-                    size_t     word = r_dcache_update_addr.read();
-                    vci_addr_t addr = (vci_addr_t) r_dcache_addr_save.read();
+                    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  = 0;
                     size_t     set  = 0;
                     
                     // need invalid rsp, don't select a victim
-                    if (not r_dcache_inval_rsp )
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                    way = r_dcache_miss_way[num_cache].read();
+                    set = r_dcache_miss_set[num_cache].read();
+#else
+                    if (not r_dcache_inval_rsp[num_cache] )
                     {
-#if CC_XCACHE_WRAPPER_SELECT_VICTIM
-                        way = r_dcache_miss_way.read();
-                        set = r_dcache_miss_set.read();
-#else
                         // First word : select an victim !
                         if (word == 0)
@@ -1675,50 +2562,55 @@
                         
                             // r_dcache_cleanup_req is false (condition to enter in DCACHE_MISS_UPDT
-                            r_dcache_cleanup_req  = r_dcache.victim_select(addr, &victim, &way, &set );
-                            r_dcache.victim_update_tag(addr, way, set);
-                            r_dcache_cleanup_line = (addr_40) victim;
-
-                            r_dcache_miss_way     = way;
-                            r_dcache_miss_set     = set;
+                            r_dcache_cleanup_req [num_cache]  = r_dcache[num_cache]->victim_select(addr, &victim, &way, &set );
+                            r_dcache[num_cache]->victim_update_tag(addr, way, set);
+                            r_dcache_cleanup_line[num_cache] = (addr_40) victim;
+
+                            r_dcache_miss_way [num_cache] = way;
+                            r_dcache_miss_set [num_cache] = set;
                         }
                         else
                         {
-                            way = r_dcache_miss_way.read();
-                            set = r_dcache_miss_set.read();
+                            way = r_dcache_miss_way[num_cache].read();
+                            set = r_dcache_miss_set[num_cache].read();
                         }
-#endif
-                    }
-
-                    bool val = CACHE_MISS_BUF_RSP_VAL(d,word);
-                    if (val)
+                    }
+#endif
+
+                    PRINTF("    * <DCACHE [%d]> MISS_UPDT : Victim way %d, set %d\n",num_cache, way, set);
+
+                    if (CACHE_MISS_BUF_RSP_VAL(d,num_cache,word))
                     {
                         // m_cpt_dcache_dir_write++;
-                        // if ( ireq.valid ) m_cost_data_miss_frz++;
+                        // if ( _dreq.valid ) m_cost_data_miss_frz++;
 
                         // if need invalid rsp, don't modify the cache, but pop the buf_rsp
-                        if (not r_dcache_inval_rsp )
+                        // (power save)
+                        if (not r_dcache_inval_rsp[num_cache])
                         {
-                            r_dcache.write(way, set, word, CACHE_MISS_BUF_RSP_DATA(d,word));
+                            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);
-                        r_dcache_update_addr = ++word;
+                        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)
                         {
+#if CC_XCACHE_WRAPPER_SELECT_VICTIM
+                            // 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);
+#endif
+
                             // Last word : if previous invalid_rsp, can cleanup, else update the TAG
-                            if (r_dcache_inval_rsp)
+                            if (r_dcache_inval_rsp[num_cache])
                             {
-                                r_dcache_inval_rsp  = false;
-                                r_dcache_fsm = DCACHE_CC_CLEANUP;
+                                r_dcache_inval_rsp[num_cache] = false;
+                                r_dcache_fsm      [num_cache] = DCACHE_CC_CLEANUP;
                             }
                             else
                             {
-#if CC_XCACHE_WRAPPER_SELECT_VICTIM
-                                r_dcache.victim_update_tag(addr, way, set);
-#endif
-                                r_dcache_fsm = DCACHE_IDLE;
+                                r_dcache_fsm [num_cache] = DCACHE_IDLE;
                             }
                         }
@@ -1730,30 +2622,31 @@
             case DCACHE_UNC_WAIT:
                 {
-                    if ( dreq.valid ) m_cost_unc_read_frz++;
-                    if ( r_tgt_dcache_req ) {   // external request
-                        r_dcache_fsm = DCACHE_CC_CHECK;
-                        r_dcache_fsm_save = r_dcache_fsm;
+                    // 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,0);
+                    bool ok = CACHE_MISS_BUF_RSP_VAL(d,num_cache,0);
 
                     if (ok) {
-                        if ( r_vci_rsp_data_error ) {
-                            r_dcache_fsm = DCACHE_ERROR;
+                        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,0);
-                            CACHE_MISS_BUF_RSP_POP(d);
-
-                            if(dreq.type == iss_t::DATA_LL){
-                                PRINTF("    * <DCACHE> ll_valid = true\n");
-
-                                r_dcache_ll_valid = true;
-                                r_dcache_ll_data = rdata;
-                                r_dcache_ll_addr = (vci_addr_t) dreq.addr;
+                            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 = DCACHE_IDLE;
-                            drsp.valid = true;
-                            drsp.rdata = rdata;
+                            r_dcache_fsm [num_cache] = DCACHE_IDLE;
+
+                            _drsp.valid = true;
+                            _drsp.rdata = rdata;
                         }
                     }
@@ -1763,22 +2656,23 @@
             case DCACHE_SC_WAIT:
                 {
-                    if ( dreq.valid ) m_cost_unc_read_frz++;
-                    if ( r_tgt_dcache_req ) {   // external request
-                        r_dcache_fsm = DCACHE_CC_CHECK;
-                        r_dcache_fsm_save = r_dcache_fsm;
+                    // 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,0);
+                    bool ok = CACHE_MISS_BUF_RSP_VAL(d,num_cache,0);
 
                     if (ok) {
-                        if ( r_vci_rsp_data_error ) {
-                            r_dcache_fsm = DCACHE_ERROR;
+                        if (r_vci_rsp_data_error[num_cache]) {
+                            r_dcache_fsm [num_cache] = DCACHE_ERROR;
                         } else {
-                            r_dcache_fsm = DCACHE_IDLE;
-                            drsp.valid = true;
-                            drsp.rdata = CACHE_MISS_BUF_RSP_DATA(d,0);
-                            CACHE_MISS_BUF_RSP_POP(d);
-                            r_dcache_ll_valid = false;
+                            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;
                         }
                     }
@@ -1789,8 +2683,9 @@
             case DCACHE_ERROR:
                 {
-                    r_dcache_fsm = DCACHE_IDLE;
-                    r_vci_rsp_data_error = false;
-                    drsp.error = true;
-                    drsp.valid = true;
+                    r_dcache_fsm        [num_cache] = DCACHE_IDLE;
+
+                    r_vci_rsp_data_error[num_cache] = false;
+                    _drsp.error = true;
+                    _drsp.valid = true;
                     break;
                 }
@@ -1798,16 +2693,16 @@
             case DCACHE_INVAL:
                 {
-                    if ( r_tgt_dcache_req.read() ) {   // external request
-                        r_dcache_fsm = DCACHE_CC_CHECK;
-                        r_dcache_fsm_save = r_dcache_fsm;
+                    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.read() ){
+                    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.read();
-                        r_dcache_cleanup_req = r_dcache.inval(ad);
-                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> m_dcache_words_shift;
-
-                        r_dcache_fsm = DCACHE_IDLE;
+                        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;
@@ -1815,15 +2710,20 @@
             case DCACHE_SYNC :
                 {
-                    if ( r_tgt_dcache_req ) {   // external request
-                        r_dcache_fsm = DCACHE_CC_CHECK;
-                        r_dcache_fsm_save = r_dcache_fsm;
+                    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 (r_wbuf.empty())
-                        {
-                            drsp.valid = true; // end, can accept the sync request
-                            r_dcache_fsm = DCACHE_IDLE;
-                        }
+                    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;
                 }
@@ -1831,19 +2731,27 @@
             case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
                 {
-                    addr_40  ad          = r_tgt_addr;
+                    addr_40  ad          = r_tgt_daddr;
                     data_t  dcache_rdata = 0;
 
-                    if((r_dcache_fsm_save == DCACHE_MISS_WAIT) and 
-                            ( (r_dcache_addr_save.read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) {
-                        r_dcache_inval_rsp = true;
-                        r_tgt_dcache_req = false;
+                    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
-                            r_tgt_dcache_rsp     = true;
+                            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
-                            r_tgt_dcache_rsp     = false;
+                            PRINTF("    * <DCACHE [%d]> send a cleanup and but don't answer\n",num_cache);
+                            r_tgt_dcache_rsp[num_cache]     = false;
                         }
-                        r_dcache_fsm = r_dcache_fsm_save;
+                        r_dcache_fsm[num_cache] = r_dcache_fsm_save[num_cache];
                     } else {
-                        bool    dcache_hit   = r_dcache.read(ad, &dcache_rdata);
+                        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;
@@ -1860,5 +2768,5 @@
                             data_t   rdata = 0;
 
-                            r_dcache.read(ad+word*4,&rdata);
+                            r_dcache[num_cache]->read(ad+word*4,&rdata);
                             
                             r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & rdata);
@@ -1873,5 +2781,5 @@
                             if (word==m_dcache_words)
                             {
-                                r_dcache_fsm = DCACHE_CC_UPDT;
+                                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)
@@ -1887,20 +2795,20 @@
                             for(size_t i=0; i<m_dcache_words; i++){
                                 data_t rdata = 0;
-                                r_dcache.read(ad + i*4,&rdata);
+                                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 = DCACHE_CC_UPDT;
+                            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 = DCACHE_CC_INVAL;
+                            r_dcache_fsm[num_cache] = DCACHE_CC_INVAL;
                         } else {
                             if(r_tgt_update){
-                                r_tgt_dcache_rsp = true;
+                                r_tgt_dcache_rsp[num_cache] = true;
                             } else {
-                                r_tgt_dcache_rsp = false;
+                                r_tgt_dcache_rsp[num_cache] = false;
                             }
-                            r_tgt_dcache_req = false;
-                            r_dcache_fsm = r_dcache_fsm_save;
+                            r_tgt_dcache_req[num_cache] = false;
+                            r_dcache_fsm    [num_cache] = r_dcache_fsm_save[num_cache];
                         }
                     }
@@ -1910,5 +2818,5 @@
             case DCACHE_CC_UPDT:    // update directory and data cache        
                 {
-                    addr_40 ad = r_tgt_addr;
+                    addr_40 ad = r_tgt_daddr;
 
                     m_cpt_dcache_dir_write++;
@@ -1923,9 +2831,9 @@
                     
                     if(r_tgt_be[word])
-                        r_dcache.write(ad+word*4, r_tgt_buf[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.read(ad+word*4,&rdata);
+                    r_dcache[num_cache]->read(ad+word*4,&rdata);
                     std::cout << "data written " << rdata << std::endl; 
 # endif
@@ -1940,7 +2848,7 @@
                     if (word==m_dcache_words)
                     {
-                        r_tgt_dcache_req = false;
-                        r_tgt_dcache_rsp = true;
-                        r_dcache_fsm = r_dcache_fsm_save;
+                        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;
                     }
@@ -1950,16 +2858,16 @@
                     for(size_t i=0; i<m_dcache_words; i++){
                         if(r_tgt_be[i]) {
-                            r_dcache.write( ad + i*4, buf[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.read(ad + i*4,&rdata);
+                            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 = false;
-                    r_tgt_dcache_rsp = true;
-                    r_dcache_fsm = r_dcache_fsm_save;
+                    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;
@@ -1968,9 +2876,9 @@
             case DCACHE_CC_INVAL:   // invalidate a cache line
                 {
-                    addr_40  ad      = r_tgt_addr;
-                    r_tgt_dcache_rsp = true;
-                    r_dcache.inval(ad);
-                    r_tgt_dcache_req = false;
-                    r_dcache_fsm = r_dcache_fsm_save;
+                    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;
                 }
@@ -1979,15 +2887,19 @@
                 {
                     // external cache invalidate request
-                    if ( r_tgt_dcache_req )   
+                    if ( r_tgt_dcache_req[num_cache] )   
                     {
-                        r_dcache_fsm = DCACHE_CC_CHECK;
-                        r_dcache_fsm_save = r_dcache_fsm;
+                        r_dcache_fsm     [num_cache] = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save[num_cache] = r_dcache_fsm[num_cache];
                         break;
                     }        
                     // cleanup
-                    if(not r_dcache_cleanup_req){
-                        r_dcache_cleanup_req = true;
-                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> m_dcache_words_shift;
-                        r_dcache_fsm = DCACHE_IDLE;
+                    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;
+
+                        // FIXME : too many access at the cache in this cycle
+                        m_cpt_dcache_dir_read += m_dcache_ways;
+                        r_dcache[num_cache]->inval((addr_40)r_dcache_addr_save[num_cache]);
                     }
                     break;
@@ -1999,94 +2911,135 @@
         // The update() method must be called at each cycle to update the internal state.
         // All pending write requests must be locked in case of SYNC
-        bool wbuf_flush=(r_dcache_fsm == DCACHE_SYNC);
+
+        // bool have_sync=(r_dcache_fsm[num_cache] == DCACHE_SYNC);
 #if   (CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME==1)
-        r_wbuf.update_multi_scan      (wbuf_flush);
+        r_wbuf[num_cache]->update_multi_scan      (have_sync);
 #elif (CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME==2)
-        r_wbuf.update_round_robin_scan(wbuf_flush);
+        r_wbuf[num_cache]->update_round_robin_scan(have_sync);
 #elif (CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME==3)
-        r_wbuf.update_one_scan        (wbuf_flush);
+        r_wbuf[num_cache]->update_one_scan        (have_sync);
 #else
-        r_wbuf.update                 (wbuf_flush);
+        r_wbuf[num_cache]->update                 (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 << "    * Data        Response : " << drsp << std::endl;
-#endif
-
-        /////////// execute one iss cycle /////////////////////////////////////////////
-        {
-            uint32_t it = 0;
-            for (size_t i=0; i<(size_t)iss_t::n_irq; i++) 
-                if(p_irq[i].read()) it |= (1<<i);
-            m_iss.executeNCycles(1, irsp, drsp, it);
-        }
-
-        if ( (ireq.valid and not irsp.valid) or 
-             (dreq.valid and not drsp.valid))
-        {
-            m_cpt_frz_cycles++;
+            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 ++;
+                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 (m_stop_simulation and (m_stop_simulation_nb_frz_cycles >= m_stop_simulation_nb_frz_cycles_max))
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+            if (_ireq.valid and _irsp.valid)
             {
-                std::cout << std::dec << "CC_XCACHE_WRAPPER \"" << name() << "\" : cycle " << m_cpt_total_cycles << ", the cpu is frozen since " << m_stop_simulation_nb_frz_cycles << " cycles." << std::endl;
-                ASSERT(false,"CPU : anormal activity"); // exit
+                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;
             }
-        }
-        else
-        {
-            m_stop_simulation_nb_frz_cycles = 0; // reinit counter
-#endif //CC_XCACHE_WRAPPER_STOP_SIMULATION
-        }
-
-
-#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
-        if (dreq.valid and drsp.valid)
-        {
-            log_dcache_transaction_file 
-                << "[" << m_cpt_total_cycles << "]"
-                << std::hex
-                << " @ "     << std::setw(8) << (uint32_t)dreq.addr
-                << " be "    << std::setw(1) << (uint32_t)dreq.be
-                << " W "     << std::setw(8) << (uint32_t)dreq.wdata
-                << " R "     << std::setw(8) << (uint32_t)drsp.rdata
-                << " error "            << (uint32_t)drsp.error
-                << std::dec
-                << " "  << type_str(dreq.type);
-
-            if ((dreq.type == iss_t::XTN_READ) or 
-                (dreq.type == iss_t::XTN_WRITE))
-                //log_dcache_transaction_file << xtn_str(dreq.addr>>2);
-                switch (dreq.addr>>2)
-                {
-                case iss_t::XTN_DCACHE_INVAL : log_dcache_transaction_file << " INVAL"; break;
-                case iss_t::XTN_SYNC         : log_dcache_transaction_file << " SYNC"; break;
-                default                      : log_dcache_transaction_file << " invalid"; break;
-                }                                                                            
-
-            log_dcache_transaction_file << std::endl;
-
-            // printf("[%d] @ %.8x be %.1x W %.8x R %.8x error %d - %s"
-            //        ,(uint32_t)m_cpt_total_cycles
-            //        ,(uint32_t)dreq.addr
-            //        ,(uint32_t)dreq.be
-            //        ,(uint32_t)dreq.wdata
-            //        ,(uint32_t)drsp.rdata
-            //        ,(uint32_t)drsp.error
-            //        ,type_str(dreq.type));
-            // if ((dreq.type == iss_t::XTN_READ) or 
-            //     (dreq.type == iss_t::XTN_WRITE))
-            //     //     printf(" %s",xtn_str(dreq.addr>>2));
-            //     switch (dreq.addr>>2)
-            //     {
-            //     case iss_t::XTN_DCACHE_INVAL : printf(" INVAL"); break;
-            //     case iss_t::XTN_SYNC         : printf(" SYNC"); break;
-            //     default                      : printf(" invalid"); break;
-            //     }                                                                            
-            // printf("\n");
-        }
-#endif //CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
+
+            if (_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
 
         ////////////////////////////////////////////////////////////////////////////
@@ -2113,30 +3066,95 @@
 
             case CLEANUP_IDLE:
-            {    
-                if ( p_vci_ini_c.cmdack )
-                {
-                    if      (r_dcache_cleanup_req) 	r_cleanup_fsm = CLEANUP_DCACHE;
-                    else if (r_icache_cleanup_req) 	r_cleanup_fsm = CLEANUP_ICACHE;
+            {
+                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)?((uint64_t)set_num_icache_only(r_icache_cleanup_line[num_cache].read()<<m_icache_words_shift,num_cache)):((uint64_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
+                    log_transaction_file_cleanup
+                        << "[" << m_cpt_total_cycles << "] "
+                        << ((cleanup_icache_req)?("icache "):("dcache "))
+                        << num_cache << " : "
+                        << std::hex
+                        << " L "     << std::setw(10) << ((cleanup_icache_req)?((uint64_t)set_num_icache_only(r_icache_cleanup_line[num_cache].read()<<m_icache_words_shift,num_cache)):((uint64_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_DCACHE:
+            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");
+                           "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 = false;
-                    // m_cpt_cc_cleanup_data++; TODO
+                    r_dcache_cleanup_req[r_cleanup_num_cache] = false;
+                    // m_cpt_cc_cleanup_data++;
                 }
                 break;
             }
-            case CLEANUP_ICACHE:
+            case CLEANUP_RSP_ICACHE:
             {
                 if ( p_vci_ini_c.rspval )
@@ -2150,6 +3168,6 @@
                     
                     r_cleanup_fsm = CLEANUP_IDLE;
-                    r_icache_cleanup_req = false;
-                    // m_cpt_cc_cleanup_ins++; TODO
+                    r_icache_cleanup_req[r_cleanup_num_cache] = false;
+                    // m_cpt_cc_cleanup_ins++;
                 }
                 break;
@@ -2195,7 +3213,10 @@
                 // if (r_vci_rsp_fsm != RSP_IDLE) break;
 
-                size_t	min;
-                size_t	max;
-
+                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
                 r_vci_cmd_cpt = 0;
 
@@ -2204,74 +3225,254 @@
                 // multi_write_buffer access is conditionnal with dcache_miss_req and icache_miss_req
 
-#if   (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==1)
-                //  1) two access authorized
-                bool dcache_miss_req =  r_dcache_miss_req;
-                bool icache_miss_req =  r_icache_miss_req;
-#elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==2)
-                //  2) one access with static priority (dcache prior)
-                bool dcache_miss_req = r_dcache_miss_req; // dcache prior
-                bool icache_miss_req = not dcache_miss_req and r_icache_miss_req;
+                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;
+
+                {
+                    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) 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];
+// #el
+#if   (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==2)
+                    //  2) one access with static priority (dcache prior)
+                    icache_miss_req &= not dcache_miss_req;
 #elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==3)
-                //  3) one access with static priority (icache prior)
-                bool icache_miss_req = r_icache_miss_req;
-                bool dcache_miss_req = not icache_miss_req and r_dcache_miss_req; // dcache prior
+                    //  3) one access with static priority (icache prior)
+                    dcache_miss_req &= not icache_miss_req;
 #elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==4)
-                //  4) one access with round robin priority
-                bool dcache_miss_req = ((r_dcache_miss_req and not r_icache_miss_req) or // only dcache
-                                        (r_dcache_miss_req and r_vci_cmd_dcache_prior)); // dcache prior
-                bool icache_miss_req = not dcache_miss_req and r_icache_miss_req;
+                    //  4) 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;
 #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",(uint64_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",(uint64_t)addr);
+                    }
+                }
+
+                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;
+                uint32_t dcache_write_num_cache = 0;
+                for (; dcache_write_num_cache<m_nb_dcache; ++dcache_write_num_cache)
+                {
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                    if ( r_wbuf[dcache_write_num_cache]->debug_rok(&wbuf_min, &wbuf_max, &wbuf_addr, &wbuf_index))
+                        break;
+#else
+                    if ( r_wbuf[dcache_write_num_cache]->rok(&wbuf_min, &wbuf_max))
+                        break;
+#endif
+                }
+                
                 // 1 - Data Read
-                if (dcache_miss_req and r_wbuf.miss(r_dcache_addr_save))
+                if (dcache_miss_req and r_wbuf[dcache_miss_num_cache]->miss(addr))
                 { 
-                    r_vci_cmd_fsm = CMD_DATA_MISS;
-                    r_dcache_miss_req = false;
+                    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
+                    {
+                        log_transaction_file_cmd
+                            << "[" << m_cpt_total_cycles << "] "
+                            << "CMD DATA MISS  "
+                            << "(" << dcache_miss_num_cache << ") "
+                            << std::hex
+                            << " @ " << std::setw(10) << (uint64_t)addr
+                            << " (L " << std::setw(10) << ((uint64_t)addr&(uint64_t)m_dcache_yzmask) << ")"
+                            << std::dec
+                            << std::endl;
+                    }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+
                 } 
 
                 // 2 - Data Read Uncachable
-                else if ( r_dcache_unc_req )
+                else if (dcache_unc_num_cache < m_nb_dcache) // have r_dcache_unc_req
                 { 
-                    r_vci_cmd_fsm = CMD_DATA_UNC;
-                    r_dcache_unc_req = false;
-                 // m_cpt_data_unc_transaction++; 
+                    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
+                    {
+                        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) << (uint64_t)addr
+                            << " (L " << std::setw(10) << ((uint64_t)addr&(uint64_t)m_dcache_yzmask) << ")"
+                            << std::dec
+                            << std::endl;
+                    }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
                 }
 
                 // 3 - Instruction Miss
-                else if (icache_miss_req and r_wbuf.miss(r_icache_addr_save))
+                else if (icache_miss_req and r_wbuf[icache_miss_num_cache]->miss(addr))
+              //else if (icache_miss_req and r_wbuf[dcache_miss_num_cache]->miss(addr))
                 { 
-                    r_vci_cmd_fsm = CMD_INS_MISS; 
-                    r_icache_miss_req = false;
+                    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
+                    {
+                        log_transaction_file_cmd
+                            << "[" << m_cpt_total_cycles << "] "
+                            << "CMD INS  MISS  "
+                            << "(" << icache_miss_num_cache << ") "
+                            << std::hex
+                            << " @ " << std::setw(10) << (uint64_t)addr
+                            << " (L " << std::setw(10) << ((uint64_t)addr&(uint64_t)m_icache_yzmask) << ")"
+                            << std::dec
+                            << std::endl;
+                    }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
                 } 
 
                 // 4 - Instruction Uncachable
-                else if ( r_icache_unc_req )
+                else if (icache_unc_num_cache < m_nb_icache) // have r_icache_unc_req
                 { 
-                    r_vci_cmd_fsm = CMD_INS_UNC; 
-                    r_icache_unc_req = false;
+                    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
+                    {
+                        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) << (uint64_t)addr
+                            << " (L " << std::setw(10) << ((uint64_t)addr&(uint64_t)m_icache_yzmask) << ")"
+                            << std::dec
+                            << std::endl;
+                    }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
                 }
 
                 // 5 - Data Write
-                else if ( r_wbuf.rok(&min, &max) ) 
+                else if (dcache_write_num_cache < m_nb_dcache) // have r_wbuf.rok(&wbuf_min, &wbuf_max)
                 { 
-                    r_vci_cmd_fsm = CMD_DATA_WRITE;
-                    r_vci_cmd_cpt = min;
-                    r_vci_cmd_min = min;
-                    r_vci_cmd_max = 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 += (max-min+1); 
+                    m_length_write_transaction += (wbuf_max-wbuf_min+1); 
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                    {
+                        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) << (uint64_t)addr
+                            << " (L " << std::setw(10) << ((uint64_t)addr&(uint64_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 ( r_dcache_sc_req ) 
+                else if (dcache_sc_num_cache < m_nb_dcache) // have r_dcache_sc_req
                 { 
-                    r_vci_cmd_fsm = CMD_DATA_SC;
-                    r_vci_cmd_max = 1; 
+                    r_vci_cmd_fsm       = CMD_DATA_SC;
+                    r_vci_cmd_num_cache = dcache_sc_num_cache;
+                    r_vci_cmd_max       = 1; 
                     m_cpt_unc_transaction++; 
-                    r_dcache_sc_req = false;
+                    r_dcache_sc_req[dcache_sc_num_cache] = false;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                    {
+                        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) << (uint64_t)addr
+                            << " (L " << std::setw(10) << ((uint64_t)addr&(uint64_t)m_dcache_yzmask) << ")"
+                            << std::dec
+                            << std::endl;
+                    }
+#endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
                 }
 
@@ -2283,5 +3484,5 @@
                     if (r_vci_cmd_cpt == r_vci_cmd_max) {
                         r_vci_cmd_fsm = CMD_IDLE ;
-                        r_wbuf.sent() ;
+                        r_wbuf[r_vci_cmd_num_cache]->sent() ;
                     }
                 }
@@ -2339,19 +3540,110 @@
                 if( p_vci_ini_rw.rspval.read() )
                 {
-                    PRINTF("      * <RSP> have rsp - trdid : %x\n",(uint32_t)p_vci_ini_rw.rtrdid.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
+                        {
+                            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;     break;
-                        case TYPE_INS_UNC      : r_vci_rsp_fsm = RSP_INS_UNC;      break;
-                        case TYPE_DATA_MISS    : r_vci_rsp_fsm = RSP_DATA_MISS;    break;
-                        case TYPE_DATA_UNC     : r_vci_rsp_fsm = RSP_DATA_UNC;     break;
-                        case TYPE_DATA_SC      : r_vci_rsp_fsm = RSP_DATA_SC;      break;
+                        case TYPE_INS_MISS     : 
+                            {
+                                r_vci_rsp_fsm = RSP_INS_MISS;
+
+#if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION
+                                {
+                                    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
+                                {
+                                    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
+                                {
+                                    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
+                                {
+                                    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
+                                {
+                                    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 : 
                             {
@@ -2360,4 +3652,6 @@
                         }
                     }
+
+                    r_vci_rsp_num_cache = p_vci_ini_rw.rpktid.read();
                 }
                 break;
@@ -2366,7 +3660,7 @@
 
                 m_cost_imiss_transaction++;
-                PRINTF("      * <RSP> rspval/ack : %d - %d\n",(uint32_t)p_vci_ini_rw.rspval.read(), (uint32_t)r_vci_rsp_ack);
-
-                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                PRINTF("      * <RSP> 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);
@@ -2376,5 +3670,5 @@
                             "The VCI response packet for instruction miss is too long" );
                     r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
-                    CACHE_MISS_BUF_RSP_PUSH(i,r_vci_rsp_cpt,(data_t)p_vci_ini_rw.rdata.read());
+                    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() ) 
                     {
@@ -2383,5 +3677,5 @@
                         ASSERT( ((r_vci_rsp_cpt == m_icache_words - 1) or
                                  p_vci_ini_rw.rerror.read() or
-                                 (r_vci_rsp_ins_error.read()&0x1)),
+                                 (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;
@@ -2389,5 +3683,5 @@
 
                     }
-                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error[r_vci_rsp_num_cache] = true;
                 }
                 break;
@@ -2396,14 +3690,14 @@
 
                 m_cost_imiss_transaction++;
-                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                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,0,(data_t)p_vci_ini_rw.rdata.read());
+                    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 = true;
+                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error[r_vci_rsp_num_cache] = true;
                 }
                 break;
@@ -2412,5 +3706,5 @@
 
                 m_cost_dmiss_transaction++;
-                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                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());
@@ -2420,20 +3714,19 @@
                     r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
 
-                    CACHE_MISS_BUF_RSP_PUSH(d,r_vci_rsp_cpt,(data_t)p_vci_ini_rw.rdata.read());
+                    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.read()),
+                                 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 = true;
+                    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())
@@ -2444,12 +3737,13 @@
                            "A VCI response packet must contain one flit for a write transaction");
                     r_vci_rsp_fsm = RSP_IDLE;
-                    bool cached = r_wbuf.completed(p_vci_ini_rw.rtrdid.read() - (1<<(vci_param::T-1)) );
+                    bool cached = r_wbuf[r_vci_rsp_num_cache]->completed(p_vci_ini_rw.rtrdid.read() - (1<<(vci_param::T-1)));
 
                     PRINTF("      * <RSP> cached : %d\n",cached);
 
                     if (not cached)
-                        r_dcache_previous_unc = false;
-
-                    if ((p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL) m_iss.setWriteBerr();
+                        r_dcache_previous_unc[r_vci_rsp_num_cache] = false;
+
+                    // FIXME : r_vci_rsp_num_cache != num_cpu ! -> pktid
+                    if ((p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL) m_iss[r_vci_rsp_num_cache]->setWriteBerr();
                 }
                 break;
@@ -2457,15 +3751,15 @@
             case RSP_DATA_UNC:
                 m_cost_unc_transaction++;
-                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                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,0,(data_t)p_vci_ini_rw.rdata.read());
+                    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 = false;
-
-                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                    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;
@@ -2473,15 +3767,15 @@
             case RSP_DATA_SC:
                 m_cost_unc_transaction++;
-                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
+                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,0,(data_t)p_vci_ini_rw.rdata.read());
+                    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 = false;
-
-                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                    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;
@@ -2489,5 +3783,5 @@
         } // end switch r_vci_rsp_fsm
 
-    } // end transition()
+   } // end transition()
 
     //////////////////////////////////////////////////////////////////////////////////
@@ -2495,36 +3789,67 @@
     //////////////////////////////////////////////////////////////////////////////////
     {
+        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  = r_icache_cleanup_req || r_dcache_cleanup_req;
-                if ( r_dcache_cleanup_req )
-                {
-                    p_vci_ini_c.address =  r_dcache_cleanup_line.read() * (m_dcache_words << 2);
-                    p_vci_ini_c.trdid   = TYPE_DATA_CLEANUP;
+                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",(uint64_t)addr);
                 }
                 else
                 {
-                    p_vci_ini_c.address =  r_icache_cleanup_line.read() * (m_icache_words << 2); 
-                    p_vci_ini_c.trdid   = TYPE_INS_CLEANUP;
-                }
-                p_vci_ini_c.wdata  = 0;
-                p_vci_ini_c.be     = 0xF;
-                p_vci_ini_c.plen   = 4;
-                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
-                p_vci_ini_c.pktid  = 0;
-                p_vci_ini_c.srcid  = m_srcid_c;
-                p_vci_ini_c.cons   = false;
-                p_vci_ini_c.wrap   = false;
-                p_vci_ini_c.contig = false;
-                p_vci_ini_c.clen   = 0;
-                p_vci_ini_c.cfixed = false;
-                p_vci_ini_c.eop    = true;
+                    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",(uint64_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_DCACHE:
+                }
+
+           case CLEANUP_RSP_DCACHE:
                 p_vci_ini_c.rspack  = true;
                 p_vci_ini_c.cmdval  = false;
@@ -2545,5 +3870,5 @@
                 break;
 
-           case CLEANUP_ICACHE:
+           case CLEANUP_RSP_ICACHE:
                 p_vci_ini_c.rspack  = true;
                 p_vci_ini_c.cmdval  = false;
@@ -2568,6 +3893,6 @@
 
         switch (r_vci_cmd_fsm.read() ) {
-
             case CMD_IDLE:
+                {
                 p_vci_ini_rw.cmdval  = false;
                 p_vci_ini_rw.address = 0;
@@ -2587,12 +3912,19 @@
 
                 break;
-
+                }
             case CMD_DATA_UNC:
+                {
                 p_vci_ini_rw.cmdval = true;
-                p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
-                switch( r_dcache_type_save ) {
+
+                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,(uint64_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.read();
+                        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;
@@ -2607,5 +3939,5 @@
                 p_vci_ini_rw.plen = 4;
                 p_vci_ini_rw.trdid  = TYPE_DATA_UNC;   // data cache uncached read
-                p_vci_ini_rw.pktid  = 0;
+                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;
@@ -2617,8 +3949,15 @@
 
                 break;
-
+                }
             case CMD_DATA_SC:
+                {
                 p_vci_ini_rw.cmdval = true;
-                p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
+
+                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,(uint64_t)(addr));
+
+                p_vci_ini_rw.address = addr;
                 if(r_vci_cmd_max.read() == 3){
                     ASSERT(false, "Not handled yet");
@@ -2626,8 +3965,8 @@
                     switch(r_vci_cmd_cpt.read()){
                         case 0:
-                            p_vci_ini_rw.wdata = (uint32_t)(r_dcache_ll_data.read() & 0xFFFFFFFF);
+                            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.read();
+                            p_vci_ini_rw.wdata = r_dcache_wdata_save[r_vci_cmd_num_cache].read();
                             break;
                     }
@@ -2637,5 +3976,5 @@
                 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  = 0;
+                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;
@@ -2647,14 +3986,20 @@
 
                 break;
-
+                }
             case CMD_DATA_WRITE:
+                {
                 p_vci_ini_rw.cmdval  = true;
-                p_vci_ini_rw.address = r_wbuf.getAddress(r_vci_cmd_cpt)&~0x3;
-                p_vci_ini_rw.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
-                p_vci_ini_rw.be      = r_wbuf.getBe(r_vci_cmd_cpt);
+
+                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,(uint64_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.getIndex() + (1<<(vci_param::T-1));
-                p_vci_ini_rw.pktid   = 0;
+                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;
@@ -2666,13 +4011,20 @@
 
                 break;
-
+                }
             case CMD_DATA_MISS:
+                {
                 p_vci_ini_rw.cmdval = true;
-                p_vci_ini_rw.address = r_dcache_addr_save.read() & (addr_40) m_dcache_yzmask;
+
+                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,(uint64_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  = 0;
+                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;
@@ -2684,13 +4036,20 @@
 
                 break;
-
+                }
             case CMD_INS_MISS:
+                {
                 p_vci_ini_rw.cmdval = true;
-                p_vci_ini_rw.address = r_icache_addr_save.read() & (addr_40) m_icache_yzmask;
+
+                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,(uint64_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  = 0;
+                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;
@@ -2702,13 +4061,20 @@
 
                 break;
-
+                }
             case CMD_INS_UNC:
+                {
                 p_vci_ini_rw.cmdval = true;
-                p_vci_ini_rw.address = r_icache_addr_save.read() & ~0x3;
+
+                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,(uint64_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  = 0;
+                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;
@@ -2720,23 +4086,32 @@
 
                 break;
-
+                }
         } // end switch r_vci_cmd_fsm
 
-        bool ack;
-
-        switch (r_vci_rsp_fsm.read() ) {
-        case RSP_IDLE       : ack = false; break;
-        case RSP_DATA_WRITE : ack = true; break;
-        case RSP_INS_MISS   :
-        case RSP_INS_UNC    : ack = CACHE_MISS_BUF_RSP_ACK(i); break;
-        case RSP_DATA_MISS  :
-        case RSP_DATA_UNC   :
-        case RSP_DATA_SC    : ack = CACHE_MISS_BUF_RSP_ACK(d); break;
-        } // end switch r_vci_cmd_fsm
-
-        r_vci_rsp_ack       = ack;
-        p_vci_ini_rw.rspack = ack;
-        
+        {
+            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() ) {
@@ -2750,36 +4125,68 @@
 
             case TGT_RSP_BROADCAST:
-                p_vci_tgt.cmdack  = false;
-                p_vci_tgt.rspval  = not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() and ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
-                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
-                p_vci_tgt.rpktid  = r_tgt_pktid.read();
-                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;
-
+                {
+                    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:
-                p_vci_tgt.cmdack  = false;
-                p_vci_tgt.rspval  = not r_tgt_icache_req.read() and r_tgt_icache_rsp.read();
-                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
-                p_vci_tgt.rpktid  = r_tgt_pktid.read();
-                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;
-
+                {
+                    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:
-                p_vci_tgt.cmdack  = false;
-                p_vci_tgt.rspval  = not r_tgt_dcache_req.read() and r_tgt_dcache_rsp.read();
-                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
-                p_vci_tgt.rpktid  = r_tgt_pktid.read();
-                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;
-
+                {
+                    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:
@@ -2814,4 +4221,43 @@
     }
 
+    //////////////////////////////////////////////////////////////////////////////////
+    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
 
Index: trunk/modules/vci_mem_cache_v4/caba/source/include/mem_cache_directory_v4.h
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/include/mem_cache_directory_v4.h	(revision 139)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/mem_cache_directory_v4.h	(revision 140)
@@ -6,4 +6,6 @@
 #include <cassert>
 #include "arithmetics.h"
+
+#define L1_MULTI_CACHE      1
 
 namespace soclib { namespace caba {
@@ -37,11 +39,22 @@
       bool      inst;       // Is the owner an ICache ?
       size_t    srcid;      // The SRCID of the owner
+#if L1_MULTI_CACHE
+      size_t    cache_id;   // In multi_cache configuration
+#endif
 
     ////////////////////////
     // Constructors
     ////////////////////////
-      Owner(bool i_inst,size_t i_srcid){
+      Owner(bool   i_inst
+            ,size_t i_srcid
+#if L1_MULTI_CACHE
+            ,size_t i_cache_id
+#endif
+            ){
         inst    = i_inst;
         srcid   = i_srcid;
+#if L1_MULTI_CACHE
+        cache_id= i_cache_id;
+#endif
       }
 
@@ -49,4 +62,7 @@
         inst    = a.inst;
         srcid   = a.srcid;
+#if L1_MULTI_CACHE
+        cache_id= a.cache_id;
+#endif
       }
 
@@ -54,4 +70,7 @@
         inst    = false;
         srcid   = 0;
+#if L1_MULTI_CACHE
+        cache_id= 0;
+#endif
       }
       // end constructors
@@ -89,4 +108,7 @@
       owner.inst    = 0;
       owner.srcid   = 0;
+#if L1_MULTI_CACHE
+      owner.cache_id= 0;
+#endif
       ptr           = 0;
     }
@@ -137,5 +159,13 @@
     {
       std::cout << "Valid = " << valid << " ; IS COUNT = " << is_cnt << " ; Dirty = " << dirty << " ; Lock = " 
-        << lock << " ; Tag = " << std::hex << tag << std::dec << " ; Count = " << count << " ; Owner = " << owner.srcid << " " << owner.inst << " ; Pointer = " << ptr << std::endl;
+                << lock 
+                << " ; Tag = " << std::hex << tag << std::dec 
+                << " ; Count = " << count 
+                << " ; Owner = " << owner.srcid 
+#if L1_MULTI_CACHE
+                << "." << owner.cache_id 
+#endif
+                << " " << owner.inst 
+                << " ; Pointer = " << ptr << std::endl;
     }
 
@@ -346,5 +376,9 @@
     ////////////////////////
       HeapEntry()
-      :owner(false,0)
+      :owner(false,0
+#if L1_MULTI_CACHE
+             ,0
+#endif
+             )
       {
         next = 0;
@@ -355,7 +389,10 @@
     ////////////////////////
       HeapEntry(const HeapEntry &entry){
+        owner.inst  = entry.owner.inst;
         owner.srcid = entry.owner.srcid;
-        owner.inst  = entry.owner.inst;
-        next        = entry.next;
+#if L1_MULTI_CACHE
+        owner.cache_id = entry.owner.cache_id;
+#endif        
+        next           = entry.next;
       } // end constructor
 
@@ -364,7 +401,10 @@
     /////////////////////////////////////////////////////////////////////
       void copy(const HeapEntry &entry){
-        owner.srcid = entry.owner.srcid;
-        owner.inst  = entry.owner.inst;
-        next        = entry.next;
+        owner.inst     = entry.owner.inst;
+        owner.srcid    = entry.owner.srcid;
+#if L1_MULTI_CACHE
+        owner.cache_id = entry.owner.cache_id;
+#endif
+        next           = entry.next;
       } // end copy()
 
@@ -374,7 +414,10 @@
       void print(){
         std::cout 
-        << " -- owner.srcid : " << std::dec << owner.srcid << std::endl
-        << " -- owner.inst  : " << std::dec << owner.inst << std::endl
-        << " -- next        : " << std::dec << next << std::endl;
+        << " -- owner.inst     : " << std::dec << owner.inst << std::endl
+        << " -- owner.srcid    : " << std::dec << owner.srcid << std::endl
+#if L1_MULTI_CACHE
+        << " -- owner.cache_id : " << std::dec << owner.cache_id << std::endl
+#endif
+        << " -- next           : " << std::dec << next << std::endl;
 
       } // end print()
Index: trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h	(revision 139)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h	(revision 140)
@@ -405,4 +405,5 @@
       sc_signal<int>         r_read_fsm;        // FSM state 
       sc_signal<size_t>      r_read_copy;       // Srcid of the first copy
+      sc_signal<size_t>      r_read_copy_cache; // Srcid of the first copy
       sc_signal<bool>        r_read_copy_inst;  // Type of the first copy
       sc_signal<tag_t>       r_read_tag;	    // cache line tag (in directory)
@@ -450,4 +451,5 @@
       sc_signal<tag_t>     r_write_tag;             // cache line tag (in directory)
       sc_signal<size_t>    r_write_copy;            // first owner of the line
+      sc_signal<size_t>    r_write_copy_cache;      // first owner of the line
       sc_signal<bool>      r_write_copy_inst;       // is this owner a ICache ?
       sc_signal<size_t>	   r_write_count;           // number of copies
@@ -483,4 +485,5 @@
       GenericFifo<bool>    m_write_to_init_cmd_inst_fifo;   // fifo for the L1 type
       GenericFifo<size_t>  m_write_to_init_cmd_srcid_fifo;  // fifo for srcids
+      GenericFifo<size_t>  m_write_to_init_cmd_cache_id_fifo;  // fifo for srcids
 
       // Buffer between WRITE fsm and INIT_RSP fsm (Decrement UPT entry)
@@ -516,4 +519,5 @@
 
       sc_signal<copy_t>      r_cleanup_copy;        // first copy
+      sc_signal<copy_t>      r_cleanup_copy_cache;  // first copy
       sc_signal<size_t>      r_cleanup_copy_inst;   // type of the first copy
       sc_signal<copy_t>      r_cleanup_count;       // number of copies 
@@ -521,4 +525,5 @@
       sc_signal<size_t>      r_cleanup_prev_ptr;    // previous pointer to the heap
       sc_signal<size_t>      r_cleanup_prev_srcid;  // srcid of previous heap entry
+      sc_signal<size_t>      r_cleanup_prev_cache_id;  // srcid of previous heap entry
       sc_signal<bool>        r_cleanup_prev_inst;   // inst bit of previous heap entry
       sc_signal<size_t>      r_cleanup_next_ptr;    // next pointer to the heap
@@ -552,4 +557,5 @@
       sc_signal<size_t>    r_llsc_cpt;  	    // size of command
       sc_signal<copy_t>    r_llsc_copy; 	    // Srcid of the first copy
+      sc_signal<copy_t>    r_llsc_copy_cache;   // Srcid of the first copy
       sc_signal<bool>      r_llsc_copy_inst;	// Type of the first copy
       sc_signal<size_t>    r_llsc_count;	    // number of copies
@@ -590,4 +596,5 @@
       GenericFifo<bool>    m_llsc_to_init_cmd_inst_fifo;    // fifo for the L1 type
       GenericFifo<size_t>  m_llsc_to_init_cmd_srcid_fifo;   // fifo for srcids
+      GenericFifo<size_t>  m_llsc_to_init_cmd_cache_id_fifo;// fifo for srcids
 
       // Buffer between LLSC fsm and INIT_RSP fsm (Decrement UPT entry)
@@ -620,4 +627,5 @@
       sc_signal<addr_t>    r_xram_rsp_victim_nline;     // victim line index
       sc_signal<copy_t>    r_xram_rsp_victim_copy;  	// victim line first copy
+      sc_signal<copy_t>    r_xram_rsp_victim_copy_cache;// victim line first copy
       sc_signal<bool>      r_xram_rsp_victim_copy_inst;	// victim line type of first copy
       sc_signal<size_t>    r_xram_rsp_victim_count;	    // victim line number of copies
@@ -644,4 +652,5 @@
       GenericFifo<bool>     m_xram_rsp_to_init_cmd_inst_fifo;       // fifo for the L1 type
       GenericFifo<size_t>   m_xram_rsp_to_init_cmd_srcid_fifo;      // fifo for srcids
+      GenericFifo<size_t>   m_xram_rsp_to_init_cmd_cache_id_fifo;      // fifo for srcids
 
       // Buffer between XRAM_RSP fsm and IXR_CMD fsm (XRAM write)
Index: trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp	(revision 139)
+++ trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp	(revision 140)
@@ -29,14 +29,20 @@
 #include "../include/vci_mem_cache_v4.h"
 
-//#define TDEBUG // Transaction tab debug
-//#define IDEBUG // Update tab debug
-//#define DDEBUG // Directory debug
-//#define LOCK_DEBUG // Lock debug
+// #define TDEBUG // Transaction tab debug
+// #define IDEBUG // Update tab debug
+// #define DDEBUG // Directory debug
+// #define LOCK_DEBUG // Lock debug
+
 #define DEBUG_VCI_MEM_CACHE 0
-#define DEBUG_START_CYCLE   200000
+#define DEBUG_START_CYCLE   949900
 #define RANDOMIZE_SC
 
+#define ASSERT_VERBOSE
+#define ASSERT_NCYCLES m_cpt_cycles
+
+#include "debug.h"
+
 #if DEBUG_VCI_MEM_CACHE
-# define PRINTF(msg...) do { if (m_cpt_cycles > DEBUG_START_CYCLE) printf(msg); } while (0); 
+# define PRINTF(msg...) PRINTF_COND(m_cpt_cycles > DEBUG_START_CYCLE,msg)
 #else
 # define PRINTF(msg...)
@@ -301,4 +307,7 @@
     m_write_to_init_cmd_inst_fifo("m_write_to_init_cmd_inst_fifo",8),
     m_write_to_init_cmd_srcid_fifo("m_write_to_init_cmd_srcid_fifo",8),
+#if L1_MULTI_CACHE
+    m_write_to_init_cmd_cache_id_fifo("m_write_to_init_cmd_cache_id_fifo",8),
+#endif
     r_init_rsp_fsm("r_init_rsp_fsm"),
     r_cleanup_fsm("r_cleanup_fsm"),
@@ -306,8 +315,14 @@
     m_llsc_to_init_cmd_inst_fifo("m_llsc_to_init_cmd_inst_fifo",8),
     m_llsc_to_init_cmd_srcid_fifo("m_llsc_to_init_cmd_srcid_fifo",8),
+#if L1_MULTI_CACHE
+    m_llsc_to_init_cmd_cache_id_fifo("m_llsc_to_init_cmd_cache_id_fifo",8),
+#endif
     r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
     r_xram_rsp_fsm("r_xram_rsp_fsm"),
     m_xram_rsp_to_init_cmd_inst_fifo("m_xram_rsp_to_init_cmd_inst_fifo",8),
     m_xram_rsp_to_init_cmd_srcid_fifo("m_xram_rsp_to_init_cmd_srcid_fifo",8),
+#if L1_MULTI_CACHE
+    m_xram_rsp_to_init_cmd_cache_id_fifo("m_xram_rsp_to_init_cmd_cache_id_fifo",8),
+#endif
     r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
     r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
@@ -532,4 +547,7 @@
       m_write_to_init_cmd_inst_fifo.init();
       m_write_to_init_cmd_srcid_fifo.init();
+#if L1_MULTI_CACHE
+      m_write_to_init_cmd_cache_id_fifo.init();
+#endif
 
       r_cleanup_to_tgt_rsp_req	= false;
@@ -545,4 +563,7 @@
       m_llsc_to_init_cmd_inst_fifo.init();
       m_llsc_to_init_cmd_srcid_fifo.init();
+#if L1_MULTI_CACHE
+      m_llsc_to_init_cmd_cache_id_fifo.init();
+#endif
 
       for(size_t i=0; i<TRANSACTION_TAB_LINES ; i++){
@@ -557,4 +578,7 @@
       m_xram_rsp_to_init_cmd_inst_fifo.init();
       m_xram_rsp_to_init_cmd_srcid_fifo.init();
+#if L1_MULTI_CACHE
+      m_xram_rsp_to_init_cmd_cache_id_fifo.init();
+#endif
 
       r_ixr_cmd_cpt         = 0;
@@ -591,18 +615,27 @@
     bool    cmd_llsc_fifo_get = false;
 
-    bool    write_to_init_cmd_fifo_put   = false;
-    bool    write_to_init_cmd_fifo_get   = false;
-    bool    write_to_init_cmd_fifo_inst  = false;
-    size_t  write_to_init_cmd_fifo_srcid = 0;
-
-    bool    xram_rsp_to_init_cmd_fifo_put   = false;
-    bool    xram_rsp_to_init_cmd_fifo_get   = false;
-    bool    xram_rsp_to_init_cmd_fifo_inst  = false;
-    size_t  xram_rsp_to_init_cmd_fifo_srcid = 0;
-
-    bool    llsc_to_init_cmd_fifo_put   = false;
-    bool    llsc_to_init_cmd_fifo_get   = false;
-    bool    llsc_to_init_cmd_fifo_inst  = false;
-    size_t  llsc_to_init_cmd_fifo_srcid = 0;
+    bool    write_to_init_cmd_fifo_put      = false;
+    bool    write_to_init_cmd_fifo_get      = false;
+    bool    write_to_init_cmd_fifo_inst     = false;
+    size_t  write_to_init_cmd_fifo_srcid    = 0;
+#if L1_MULTI_CACHE
+    size_t  write_to_init_cmd_fifo_cache_id = 0;
+#endif
+
+    bool    xram_rsp_to_init_cmd_fifo_put      = false;
+    bool    xram_rsp_to_init_cmd_fifo_get      = false;
+    bool    xram_rsp_to_init_cmd_fifo_inst     = false;
+    size_t  xram_rsp_to_init_cmd_fifo_srcid    = 0;
+#if L1_MULTI_CACHE
+    size_t  xram_rsp_to_init_cmd_fifo_cache_id = 0;
+#endif
+
+    bool    llsc_to_init_cmd_fifo_put      = false;
+    bool    llsc_to_init_cmd_fifo_get      = false;
+    bool    llsc_to_init_cmd_fifo_inst     = false;
+    size_t  llsc_to_init_cmd_fifo_srcid    = 0;
+#if L1_MULTI_CACHE
+    size_t  llsc_to_init_cmd_fifo_cache_id = 0;
+#endif
 
 #if DEBUG_VCI_MEM_CACHE 
@@ -628,4 +661,11 @@
 #endif
 
+#ifdef IDEBUG
+if(m_cpt_cycles > DEBUG_START_CYCLE){
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+}
+#endif
+
     ////////////////////////////////////////////////////////////////////////////////////
     //		TGT_CMD FSM
@@ -651,5 +691,5 @@
           if ( p_vci_tgt.cmdval ) {
 
-              PRINTF("  * <TGT> Request from %d at address %llx\n",(uint32_t)p_vci_tgt.srcid.read(),(uint64_t)p_vci_tgt.address.read());
+              PRINTF("  * <MEM_CACHE.TGT> Request from %d.%d (%d) at address %llx\n",(uint32_t)p_vci_tgt.srcid.read(),(uint32_t)p_vci_tgt.pktid.read(),(uint32_t)p_vci_tgt.trdid.read(),(uint64_t)p_vci_tgt.address.read());
 
             if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) 
@@ -676,6 +716,6 @@
 
         {
-          assert(((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2))<=16)
-              && "VCI_MEM_CACHE All read request to the MemCache must stay within a cache line"); 
+            ASSERT(((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2))<=16),
+                   "VCI_MEM_CACHE All read request to the MemCache must stay within a cache line"); 
 
           if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) {
@@ -744,9 +784,10 @@
 
           if ( p_vci_ini.rspval ) {
-
-            assert ( ( p_vci_ini.rtrdid.read() < m_update_tab.size() )
-                && "VCI_MEM_CACHE UPT index too large in VCI response paquet received by memory cache" );
-            assert ( p_vci_ini.reop 
-                && "VCI_MEM_CACHE All response packets to update/invalidate requests must be one cell" );
+            PRINTF("  * <MEM_CACHE.INIT_RSP> rsp val - trdid %d\n",(uint32_t)p_vci_ini.rtrdid.read());
+
+            ASSERT (( p_vci_ini.rtrdid.read() < m_update_tab.size())
+                    ,"VCI_MEM_CACHE UPT index too large in VCI response paquet received by memory cache" );
+            ASSERT (p_vci_ini.reop 
+                    ,"VCI_MEM_CACHE All response packets to update/invalidate requests must be one cell") ;
             r_init_rsp_upt_index = p_vci_ini.rtrdid.read(); 
             r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
@@ -772,6 +813,6 @@
 #endif
             while(!valid);
-            assert ( valid 
-                && "VCI_MEM_CACHE Invalid UPT entry in VCI response paquet received by memory cache" );
+            ASSERT ( valid 
+                     ,"VCI_MEM_CACHE Invalid UPT entry in VCI response paquet received by memory cache" );
 
             if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
@@ -830,5 +871,5 @@
     ////////////////////////////////////////////////////////////////////////////////////
 
-    PRINTF("  * TOP : Request from %d at address %llx\n",(uint32_t)m_cmd_read_srcid_fifo.read(),(uint64_t)m_cmd_read_addr_fifo.read());
+    PRINTF("  * <MEM_CACHE.TOP> Request from %d.%d at address %llx\n",(uint32_t)m_cmd_read_srcid_fifo.read(),(uint32_t)m_cmd_read_pktid_fifo.read(),(uint64_t)m_cmd_read_addr_fifo.read());
 
     switch ( r_read_fsm.read() ) {
@@ -838,5 +879,5 @@
         {
           if (m_cmd_read_addr_fifo.rok()) {
-            PRINTF("  * <READ> Request from %d at address %llx\n",(uint32_t)m_cmd_read_srcid_fifo.read(),(uint64_t)m_cmd_read_addr_fifo.read());
+            PRINTF("  * <MEM_CACHE.READ> Request from %d.%d at address %llx\n",(uint32_t)m_cmd_read_srcid_fifo.read(),(uint32_t)m_cmd_read_pktid_fifo.read(),(uint64_t)m_cmd_read_addr_fifo.read());
 
             m_cpt_read++;
@@ -858,13 +899,16 @@
 }
 #endif
-            r_read_is_cnt   = entry.is_cnt;
-            r_read_dirty    = entry.dirty;
-            r_read_lock	    = entry.lock;
-            r_read_tag	    = entry.tag;
-            r_read_way	    = way;
-            r_read_count    = entry.count;
-            r_read_copy     = entry.owner.srcid; 
-            r_read_copy_inst= entry.owner.inst;
-            r_read_ptr      = entry.ptr;
+            r_read_is_cnt     = entry.is_cnt;
+            r_read_dirty      = entry.dirty;
+            r_read_lock	      = entry.lock;
+            r_read_tag	      = entry.tag;
+            r_read_way	      = way;
+            r_read_count      = entry.count;
+            r_read_copy       = entry.owner.srcid; 
+#if L1_MULTI_CACHE
+            r_read_copy_cache = entry.owner.cache_id; 
+#endif
+            r_read_copy_inst  = entry.owner.inst;
+            r_read_ptr        = entry.ptr;
 
             bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
@@ -910,8 +954,15 @@
               if(!is_cnt){ // Not counter mode
                 entry.owner.srcid   = m_cmd_read_srcid_fifo.read();
+#if L1_MULTI_CACHE
+                entry.owner.cache_id= m_cmd_read_pktid_fifo.read();
+#endif
+
                 entry.owner.inst    = inst_read;
                 entry.count         = r_read_count.read() + 1;
               } else { // Counter mode
                 entry.owner.srcid   = 0;
+#if L1_MULTI_CACHE
+                entry.owner.cache_id= 0;
+#endif
                 entry.owner.inst    = false;
                 entry.count         = r_read_count.read() + 1;
@@ -919,4 +970,8 @@
             } else { // Uncached read
               entry.owner.srcid     = r_read_copy.read();
+#if L1_MULTI_CACHE
+              entry.owner.cache_id  = r_read_copy_cache.read();
+#endif
+
               entry.owner.inst      = r_read_copy_inst.read();
               entry.count           = r_read_count.read();
@@ -956,4 +1011,7 @@
             if(!is_cnt){ // Not counter mode
                 entry.owner.srcid   = r_read_copy.read();
+#if L1_MULTI_CACHE
+                entry.owner.cache_id= r_read_copy_cache.read();
+#endif
                 entry.owner.inst    = r_read_copy_inst.read();
                 entry.count         = r_read_count.read() + 1;
@@ -961,4 +1019,7 @@
             } else { // Counter mode
                 entry.owner.srcid   = 0;
+#if L1_MULTI_CACHE
+                entry.owner.cache_id= 0;
+#endif
                 entry.owner.inst    = false;
                 entry.count         = r_read_count.read() + 1;
@@ -1008,6 +1069,9 @@
             bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
             HeapEntry new_heap_entry;
-            new_heap_entry.owner.srcid  = m_cmd_read_srcid_fifo.read();
-            new_heap_entry.owner.inst   = inst_read;
+            new_heap_entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
+#if L1_MULTI_CACHE
+            new_heap_entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
+#endif
+            new_heap_entry.owner.inst     = inst_read;
             if(r_read_count.read() == 1){ // creation of a new list
               new_heap_entry.next         = m_heap_directory.next_free_ptr(); 
@@ -1023,5 +1087,5 @@
             r_read_fsm = READ_RSP;
           } else {
-            assert(false && "MEMCACHE Error : Bad HEAP allocation");
+              ASSERT(false,"MEMCACHE Error : Bad HEAP allocation");
           }
           break;
@@ -1039,5 +1103,5 @@
             }
           } else {
-            assert(false && "MEMCACHE Error : Bad HEAP allocation");
+              ASSERT(false,"MEMCACHE Error : Bad HEAP allocation");
           }
           break;
@@ -1048,6 +1112,9 @@
           if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
             HeapEntry last_entry;
-            last_entry.owner.srcid = 0;
-            last_entry.owner.inst  = false;
+            last_entry.owner.srcid    = 0;
+#if L1_MULTI_CACHE
+            last_entry.owner.cache_id = 0;
+#endif
+            last_entry.owner.inst     = false;
             if(m_heap_directory.is_full()){
               last_entry.next      = r_read_ptr.read();
@@ -1059,5 +1126,5 @@
             r_read_fsm = READ_RSP;
           } else {
-            assert(false && "MEMCACHE Error : Bad HEAP allocation");
+              ASSERT(false,"MEMCACHE Error : Bad HEAP allocation");
           }
           break;
@@ -1107,5 +1174,5 @@
         {
           if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
-            m_transaction_tab.set(r_read_trt_index.read(),
+              m_transaction_tab.set(r_read_trt_index.read(),
                 true,
                 m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
@@ -1178,4 +1245,6 @@
         {
           if ( m_cmd_write_addr_fifo.rok()) {
+              PRINTF("  * <MEM_CACHE.WRITE> KANE Request from %d.%d (%d) at address %llx\n",(uint32_t)m_cmd_write_srcid_fifo.read(),(uint32_t)m_cmd_write_pktid_fifo.read(),(uint32_t) m_cmd_write_trdid_fifo.read(), (uint64_t)m_cmd_write_addr_fifo.read());
+
             m_cpt_write++;
             m_cpt_write_cells++;
@@ -1212,6 +1281,6 @@
 
             // check that the next word is in the same cache line
-            assert( (m_nline[(vci_addr_t)(r_write_address.read())] == m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())])  
-                && "VCI_MEM_CACHE write error in vci_mem_cache : write burst over a line" );
+            ASSERT( (m_nline[(vci_addr_t)(r_write_address.read())] == m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())])  
+                    ,"VCI_MEM_CACHE write error in vci_mem_cache : write burst over a line" );
             // consume a word in the FIFO & write it in the local buffer 
             cmd_write_fifo_get=true;
@@ -1239,4 +1308,7 @@
               r_write_tag       = entry.tag;
               r_write_copy      = entry.owner.srcid;
+#if L1_MULTI_CACHE
+              r_write_copy_cache= entry.owner.cache_id;
+#endif
               r_write_copy_inst = entry.owner.inst;
               r_write_count     = entry.count;
@@ -1287,18 +1359,26 @@
           // update directory with Dirty bit
           DirectoryEntry entry;
-          entry.valid	    = true;
-          entry.dirty	    = true;
-          entry.tag	        = r_write_tag.read();
-          entry.is_cnt      = r_write_is_cnt.read();
-          entry.lock	    = r_write_lock.read();
-          entry.owner.srcid = r_write_copy.read();
-          entry.owner.inst  = r_write_copy_inst.read();
-          entry.count       = r_write_count.read();
-          entry.ptr         = r_write_ptr.read();
-          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
-          size_t way	    = r_write_way.read();
+          entry.valid	      = true;
+          entry.dirty	      = true;
+          entry.tag	          = r_write_tag.read();
+          entry.is_cnt        = r_write_is_cnt.read();
+          entry.lock	      = r_write_lock.read();
+          entry.owner.srcid   = r_write_copy.read();
+#if L1_MULTI_CACHE
+          entry.owner.cache_id= r_write_copy_cache.read();
+#endif
+          entry.owner.inst    = r_write_copy_inst.read();
+          entry.count         = r_write_count.read();
+          entry.ptr           = r_write_ptr.read();
+          size_t set	      = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	      = r_write_way.read();
           m_cache_directory.write(set, way, entry);
 
-          bool owner = (r_write_copy.read()==r_write_srcid.read()) && !r_write_copy_inst.read();
+          bool owner = (((r_write_copy.read()==r_write_srcid.read())
+#if L1_MULTI_CACHE
+                         and (r_write_copy_cache.read()==r_write_pktid.read())
+#endif
+                         ) and not r_write_copy_inst.read());
+
           bool no_update = (r_write_count.read()==0) || ( owner && (r_write_count.read()==1));
 
@@ -1387,6 +1467,6 @@
       case WRITE_UPT_REQ:
         {
-          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
-                    "MemCache ERROR : bad HEAP allocation");
+          ASSERT( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE)
+                  ,"MemCache ERROR : bad HEAP allocation");
           if( !r_write_to_init_cmd_multi_req.read() && 
               !r_write_to_init_cmd_brdcast_req.read()  ){
@@ -1407,9 +1487,16 @@
             }
             
-            if( (r_write_copy.read() != r_write_srcid.read()) || r_write_copy_inst.read() ) {
+            if((r_write_copy.read() != r_write_srcid.read()) or
+#if L1_MULTI_CACHE
+               (r_write_copy_cache.read() != r_write_pktid.read()) or
+#endif
+               r_write_copy_inst.read() ) {
               // We put the first copy in the fifo
               write_to_init_cmd_fifo_put     = true;
               write_to_init_cmd_fifo_inst    = r_write_copy_inst.read();
               write_to_init_cmd_fifo_srcid   = r_write_copy.read();
+#if L1_MULTI_CACHE
+              write_to_init_cmd_fifo_cache_id= r_write_copy_cache.read();
+#endif
               if(r_write_count.read() == 1){
                 r_write_fsm = WRITE_IDLE;
@@ -1427,11 +1514,19 @@
       case WRITE_UPDATE:	// send a multi-update request to INIT_CMD fsm
         {
-          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
-                    "MemCache ERROR : bad HEAP allocation");
+          ASSERT( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE)
+                  ,"MemCache ERROR : bad HEAP allocation");
           HeapEntry entry = m_heap_directory.read(r_write_ptr.read());
-          write_to_init_cmd_fifo_inst  = entry.owner.inst;
-          write_to_init_cmd_fifo_srcid = entry.owner.srcid;
+          write_to_init_cmd_fifo_inst     = entry.owner.inst;
+          write_to_init_cmd_fifo_srcid    = entry.owner.srcid;
+#if L1_MULTI_CACHE
+          write_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
+#endif
+          
           bool dec_upt_counter = r_write_to_dec.read();
-          if( (entry.owner.srcid != r_write_srcid.read()) || entry.owner.inst ){
+          if( (entry.owner.srcid != r_write_srcid.read()) or
+#if L1_MULTI_CACHE
+              (entry.owner.cache_id != r_write_pktid.read()) or
+#endif
+              entry.owner.inst){
             write_to_init_cmd_fifo_put = true;
           } else {
@@ -1471,4 +1566,7 @@
         {
           if ( !r_write_to_tgt_rsp_req.read() ) {
+
+            PRINTF("  * <MEM_CACHE.WRITE> YURI Request from %d.%d (%d)\n",(uint32_t)r_write_srcid.read(), (uint32_t)r_write_trdid.read(), (uint32_t)r_write_pktid.read());
+
             r_write_to_tgt_rsp_req	    = true;
             r_write_to_tgt_rsp_srcid	= r_write_srcid.read();
@@ -1644,8 +1742,8 @@
       case WRITE_DIR_INVAL:
         {
-            assert(((r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) &&
+            ASSERT(((r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) &&
                     (r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) &&
-                    (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ))&&
-                    "MemCache ERROR : bad TRT,DIR or UPT allocation error");
+                    (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ))
+                   ,"MemCache ERROR : bad TRT,DIR or UPT allocation error");
             m_transaction_tab.set(r_write_trt_index.read(),
                 false,				// write request to XRAM
@@ -1675,4 +1773,7 @@
             entry.lock          = false;
             entry.owner.srcid   = 0;
+#if L1_MULTI_CACHE
+            entry.owner.cache_id= 0;
+#endif
             entry.owner.inst    = false;
             entry.ptr           = 0;
@@ -1890,7 +1991,7 @@
             data_t data 	= p_vci_ixr.rdata.read();
             size_t index        = r_ixr_rsp_trt_index.read();
-            assert( ((eop == (r_ixr_rsp_cpt.read() == (m_words-1))) ||
-                     p_vci_ixr.rerror.read())
-                && "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
+            ASSERT(((eop == (r_ixr_rsp_cpt.read() == (m_words-1))) ||
+                    p_vci_ixr.rerror.read())
+                   ,"Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
             m_transaction_tab.write_rsp(index, r_ixr_rsp_cpt.read(), data, p_vci_ixr.rerror.read()&0x1);
             r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
@@ -1988,4 +2089,7 @@
 
             r_xram_rsp_victim_copy      = victim.owner.srcid;
+#if L1_MULTI_CACHE
+            r_xram_rsp_victim_copy_cache= victim.owner.cache_id;
+#endif
             r_xram_rsp_victim_copy_inst = victim.owner.inst;
             r_xram_rsp_victim_count     = victim.count;
@@ -2005,5 +2109,5 @@
 if(m_cpt_cycles > DEBUG_START_CYCLE){
 	std::cout << "XRAM_RSP FSM in XRAM_RSP_TRT_COPY state" << std::endl;
-	std::cout << "Victim way : " << std::hex << way << " set " << std::hex << set << std::endl;
+	std::cout << "Victim way : " << std::hex << way << " set " << set << std::dec << std::endl;
 	victim.print();
 }
@@ -2093,17 +2197,17 @@
           entry.ptr       = 0;
           if(cached_read) {
-            if(inst_read) {
-              entry.owner.srcid = r_xram_rsp_trt_buf.srcid;
-              entry.owner.inst  = true;
-              entry.count       = 1;
-            } else {
-              entry.owner.srcid = r_xram_rsp_trt_buf.srcid;
-              entry.owner.inst  = false;
-              entry.count       = 1;
-            }
+              entry.owner.srcid   = r_xram_rsp_trt_buf.srcid;
+#if L1_MULTI_CACHE
+              entry.owner.cache_id= r_xram_rsp_trt_buf.pktid;
+#endif
+              entry.owner.inst    = inst_read;
+              entry.count         = 1;
           } else {
-            entry.owner.srcid = 0;
-            entry.owner.inst  = 0;
-            entry.count       = 0;
+            entry.owner.srcid    = 0;
+#if L1_MULTI_CACHE
+            entry.owner.cache_id = 0;
+#endif
+            entry.owner.inst     = 0;
+            entry.count          = 0;
           }
           m_cache_directory.write(set, way, entry);
@@ -2125,14 +2229,15 @@
 
           if(r_xram_rsp_victim_inval.read()){
-            bool    brdcast = r_xram_rsp_victim_is_cnt.read();
-            size_t index;
+            bool   brdcast = r_xram_rsp_victim_is_cnt.read();
+            size_t index = 0;
             size_t count_copies = r_xram_rsp_victim_count.read();
-
+            
+            //@@
             bool	 wok = m_update_tab.set(false,	// it's an inval transaction
                 brdcast,                          // set brdcast bit
                 false,  // it does not need a response
-                0,
-                0,
-                0,
+                0,//srcid
+                0,//trdid
+                0,//pktid
                 r_xram_rsp_victim_nline.read(),
                 count_copies,
@@ -2147,5 +2252,5 @@
             r_xram_rsp_upt_index = index;
             if(!wok) {
-              assert(false && "mem_cache error : xram_rsp_dir_upt, an update_tab entry was free but write unsuccessful");
+                ASSERT(false,"mem_cache error : xram_rsp_dir_upt, an update_tab entry was free but write unsuccessful");
             }
           }
@@ -2234,4 +2339,7 @@
             xram_rsp_to_init_cmd_fifo_srcid     = r_xram_rsp_victim_copy.read();
             xram_rsp_to_init_cmd_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
+#if L1_MULTI_CACHE
+            xram_rsp_to_init_cmd_fifo_cache_id  = r_xram_rsp_victim_copy_cache.read();
+#endif
             xram_rsp_to_init_cmd_fifo_put       = multi_req;
             
@@ -2277,5 +2385,8 @@
           if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP ) {
             HeapEntry entry = m_heap_directory.read(r_xram_rsp_next_ptr.read());
-            xram_rsp_to_init_cmd_fifo_srcid = entry.owner.srcid;
+            xram_rsp_to_init_cmd_fifo_srcid    = entry.owner.srcid;
+#if L1_MULTI_CACHE
+            xram_rsp_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
+#endif
             xram_rsp_to_init_cmd_fifo_inst  = entry.owner.inst;
             xram_rsp_to_init_cmd_fifo_put   = true;
@@ -2297,11 +2408,14 @@
       case XRAM_RSP_HEAP_LAST:	// last member of the list
         {
-          assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP) &&
-                  "MemCache ERROR : bad HEAP allocation");
+          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP)
+                 ,"MemCache ERROR : bad HEAP allocation");
           size_t free_pointer = m_heap_directory.next_free_ptr();
 
           HeapEntry last_entry;
-          last_entry.owner.srcid = 0;
-          last_entry.owner.inst  = false;
+          last_entry.owner.srcid    = 0;
+#if L1_MULTI_CACHE
+          last_entry.owner.cache_id = 0;
+#endif
+          last_entry.owner.inst     = false;
           if(m_heap_directory.is_full()){
             last_entry.next     = r_xram_rsp_next_ptr.read();
@@ -2377,6 +2491,6 @@
         {
           if ( p_vci_tgt_cleanup.cmdval.read() ) {
-            assert( (p_vci_tgt_cleanup.srcid.read() < m_initiators) &&
-            "VCI_MEM_CACHE error in a cleanup request : received SRCID is larger than the number of initiators");
+            ASSERT((p_vci_tgt_cleanup.srcid.read() < m_initiators)
+                   ,"VCI_MEM_CACHE error in a cleanup request : received SRCID is larger than the number of initiators");
 
             bool reached = false;
@@ -2391,4 +2505,6 @@
                  reached) 
             {
+              PRINTF("  * <MEM_CACHE.CLEANUP> Request from %d.%d at address %llx\n",(uint32_t)p_vci_tgt_cleanup.srcid.read(),(uint32_t)p_vci_tgt_cleanup.pktid.read(),(uint64_t)p_vci_tgt_cleanup.address.read());
+
               m_cpt_cleanup++;
 
@@ -2425,8 +2541,10 @@
             r_cleanup_way	    = way;
             r_cleanup_copy      = entry.owner.srcid;
+#if L1_MULTI_CACHE
+            r_cleanup_copy_cache= entry.owner.cache_id;
+#endif
             r_cleanup_copy_inst = entry.owner.inst;
             r_cleanup_count     = entry.count;
             r_cleanup_ptr       = entry.ptr;
-
 
             // In case of hit, the copy must be cleaned in the copies bit-vector
@@ -2446,6 +2564,6 @@
       case CLEANUP_DIR_WRITE:
         {
-          assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) && 
-                "MemCache ERROR : Bad DIR allocation");
+          ASSERT((r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP)
+                 ,"MemCache ERROR : Bad DIR allocation");
           size_t way      = r_cleanup_way.read();
 #define L2 soclib::common::uint32_log2
@@ -2453,5 +2571,9 @@
 #undef L2
           bool cleanup_inst  = r_cleanup_trdid.read() & 0x1; 
-          bool match_srcid   = (r_cleanup_copy.read() == r_cleanup_srcid.read());
+          bool match_srcid   = ((r_cleanup_copy.read() == r_cleanup_srcid.read())
+#if L1_MULTI_CACHE
+                                and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read())
+#endif
+                                );
           bool match_inst    = (r_cleanup_copy_inst.read()  == cleanup_inst);
           bool match         = match_srcid && match_inst;
@@ -2467,6 +2589,9 @@
           if(r_cleanup_is_cnt.read()) { // Directory is a counter
             entry.count  = r_cleanup_count.read() -1;
-            entry.owner.srcid = 0;
-            entry.owner.inst  = 0;
+            entry.owner.srcid   = 0;
+#if L1_MULTI_CACHE
+            entry.owner.cache_id= 0;
+#endif
+            entry.owner.inst    = 0;
             // response to the cache 
             r_cleanup_fsm = CLEANUP_RSP;
@@ -2474,13 +2599,19 @@
           else{                         // Directory is a list
             if(match) { // hit
-              entry.count       = 0; // no more copy
-              entry.owner.srcid = 0;
-              entry.owner.inst  = 0;
-              r_cleanup_fsm     = CLEANUP_RSP; 
+              entry.count         = 0; // no more copy
+              entry.owner.srcid   = 0;
+#if L1_MULTI_CACHE
+              entry.owner.cache_id=0;
+#endif
+              entry.owner.inst    = 0;
+              r_cleanup_fsm       = CLEANUP_RSP; 
             } else { // miss
-              entry.count       = r_cleanup_count.read();
-              entry.owner.srcid = r_cleanup_copy.read();
-              entry.owner.inst  = r_cleanup_copy_inst.read();
-              r_cleanup_fsm     = CLEANUP_UPT_LOCK;
+              entry.count          = r_cleanup_count.read();
+              entry.owner.srcid    = r_cleanup_copy.read();
+#if L1_MULTI_CACHE
+              entry.owner.cache_id = r_cleanup_copy_cache.read();
+#endif
+              entry.owner.inst     = r_cleanup_copy_inst.read();
+              r_cleanup_fsm        = CLEANUP_UPT_LOCK;
             }
           }
@@ -2501,43 +2632,72 @@
             bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
             bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
+#if L1_MULTI_CACHE
+            bool match_dir_cache_id = (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
+#endif
             bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
-            bool match_dir          = match_dir_srcid && match_dir_inst;
+            bool match_dir          = match_dir_srcid and match_dir_cache_id and match_dir_inst;
             bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+#if L1_MULTI_CACHE
+            bool match_heap_cache_id= (heap_entry.owner.cache_id == r_cleanup_pktid.read());
+#endif
             bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
-            bool match_heap         = match_heap_srcid && match_heap_inst;
-
-            r_cleanup_prev_ptr = r_cleanup_ptr.read();
-            r_cleanup_prev_srcid = heap_entry.owner.srcid;
-            r_cleanup_prev_inst  = heap_entry.owner.inst;
+            bool match_heap         = match_heap_srcid and match_heap_cache_id and match_heap_inst;
+
+#if L1_MULTI_CACHE
+            PRINTF("  * <MEM_CACHE.CLEANUP> match_dir  %d (match_dir_srcid  %d, match_dir_cache_id  %d, match_dir_inst  %d)\n",
+                   match_dir , match_dir_srcid , match_dir_cache_id , match_dir_inst);
+            PRINTF("  * <MEM_CACHE.CLEANUP> match_heap %d (match_heap_srcid %d, match_heap_cache_id %d, match_heap_inst %d)\n",
+                   match_heap, match_heap_srcid, match_heap_cache_id, match_heap_inst);
+#else
+            PRINTF("  * <MEM_CACHE.CLEANUP> match_dir  %d (match_dir_srcid  %d, match_dir_inst  %d)\n",
+                   match_dir , match_dir_srcid , match_dir_inst);
+            PRINTF("  * <MEM_CACHE.CLEANUP> match_heap %d (match_heap_srcid %d, match_heap_inst %d)\n",
+                   match_heap, match_heap_srcid, match_heap_inst);
+#endif
+            PRINTF("  * <MEM_CACHE.CLEANUP> last %d\n",last);
+
+            r_cleanup_prev_ptr      = r_cleanup_ptr.read();
+            r_cleanup_prev_srcid    = heap_entry.owner.srcid;
+#if L1_MULTI_CACHE
+            r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
+#endif
+
+            r_cleanup_prev_inst     = heap_entry.owner.inst;
 
             if(match_dir){
               DirectoryEntry dir_entry;
-              dir_entry.valid	    = true;
-              dir_entry.is_cnt      = r_cleanup_is_cnt.read();
-              dir_entry.dirty	    = r_cleanup_dirty.read();
-              dir_entry.tag	        = r_cleanup_tag.read();
-              dir_entry.lock	    = r_cleanup_lock.read();
-              dir_entry.ptr         = heap_entry.next;
-              dir_entry.count       = r_cleanup_count.read()-1;
-              dir_entry.owner.srcid = heap_entry.owner.srcid;
-              dir_entry.owner.inst  = heap_entry.owner.inst;
+              dir_entry.valid	       = true;
+              dir_entry.is_cnt         = r_cleanup_is_cnt.read();
+              dir_entry.dirty	       = r_cleanup_dirty.read();
+              dir_entry.tag	           = r_cleanup_tag.read();
+              dir_entry.lock	       = r_cleanup_lock.read();
+              dir_entry.ptr            = heap_entry.next;
+              dir_entry.count          = r_cleanup_count.read()-1;
+              dir_entry.owner.srcid    = heap_entry.owner.srcid;
+#if L1_MULTI_CACHE
+              dir_entry.owner.cache_id = heap_entry.owner.cache_id;
+#endif
+              dir_entry.owner.inst     = heap_entry.owner.inst;
               m_cache_directory.write(set,way,dir_entry);
-              r_cleanup_next_ptr    = r_cleanup_ptr.read();
-              r_cleanup_fsm         = CLEANUP_HEAP_FREE;
+              r_cleanup_next_ptr       = r_cleanup_ptr.read();
+              r_cleanup_fsm            = CLEANUP_HEAP_FREE;
             }
             else if(match_heap){
               DirectoryEntry dir_entry;
-              dir_entry.valid	    = true;
-              dir_entry.is_cnt      = r_cleanup_is_cnt.read();
-              dir_entry.dirty	    = r_cleanup_dirty.read();
-              dir_entry.tag	        = r_cleanup_tag.read();
-              dir_entry.lock	    = r_cleanup_lock.read();
-              dir_entry.ptr         = heap_entry.next;
-              dir_entry.count       = r_cleanup_count.read()-1;
-              dir_entry.owner.srcid = r_cleanup_copy.read();
-              dir_entry.owner.inst  = r_cleanup_copy_inst.read();
+              dir_entry.valid	       = true;
+              dir_entry.is_cnt         = r_cleanup_is_cnt.read();
+              dir_entry.dirty	       = r_cleanup_dirty.read();
+              dir_entry.tag	           = r_cleanup_tag.read();
+              dir_entry.lock	       = r_cleanup_lock.read();
+              dir_entry.ptr            = heap_entry.next;
+              dir_entry.count          = r_cleanup_count.read()-1;
+              dir_entry.owner.srcid    = r_cleanup_copy.read();
+#if L1_MULTI_CACHE
+              dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
+#endif
+              dir_entry.owner.inst     = r_cleanup_copy_inst.read();
               m_cache_directory.write(set,way,dir_entry);
-              r_cleanup_next_ptr    = r_cleanup_ptr.read();
-              r_cleanup_fsm         = CLEANUP_HEAP_FREE; 
+              r_cleanup_next_ptr       = r_cleanup_ptr.read();
+              r_cleanup_fsm            = CLEANUP_HEAP_FREE; 
             }
             else{
@@ -2552,4 +2712,7 @@
                 dir_entry.count         = r_cleanup_count.read()-1;
                 dir_entry.owner.srcid   = r_cleanup_copy.read();
+#if L1_MULTI_CACHE
+                dir_entry.owner.cache_id= r_cleanup_copy_cache.read();
+#endif
                 dir_entry.owner.inst    = r_cleanup_copy_inst.read();
                 m_cache_directory.write(set,way,dir_entry);
@@ -2559,5 +2722,5 @@
 
               } else{
-                assert(false && "MemCache ERROR : CLEANUP hit but line not shared");
+                  ASSERT(false,"MemCache ERROR : CLEANUP hit but line not shared");
               }
             }
@@ -2568,10 +2731,14 @@
       case CLEANUP_HEAP_SEARCH:
         {
-          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
-                    "MemCache ERROR : bad HEAP allocation");
+          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP)
+                 ,"MemCache ERROR : bad HEAP allocation");
           HeapEntry heap_entry = m_heap_directory.read(r_cleanup_next_ptr.read());
           bool last = (heap_entry.next == r_cleanup_next_ptr.read());
           bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
-          bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+          bool match_heap_srcid   = ((heap_entry.owner.srcid == r_cleanup_srcid.read())
+#if L1_MULTI_CACHE
+                                     and (heap_entry.owner.cache_id == r_cleanup_pktid.read())
+#endif
+                                     );
           bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
           bool match_heap         = match_heap_srcid && match_heap_inst;
@@ -2583,9 +2750,12 @@
           else{
             if(last) {
-              assert(false && "MemCache ERROR : CLEANUP hit but line not shared");
+                ASSERT(false,"MemCache ERROR : CLEANUP hit but line not shared");
             } else {
-              r_cleanup_prev_ptr = r_cleanup_next_ptr.read();
-              r_cleanup_prev_srcid = heap_entry.owner.srcid;
-              r_cleanup_prev_inst  = heap_entry.owner.inst;
+              r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
+              r_cleanup_prev_srcid    = heap_entry.owner.srcid;
+#if L1_MULTI_CACHE
+              r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
+#endif
+              r_cleanup_prev_inst     = heap_entry.owner.inst;
               r_cleanup_next_ptr = heap_entry.next;
               r_cleanup_fsm      = CLEANUP_HEAP_SEARCH;
@@ -2598,10 +2768,13 @@
       case CLEANUP_HEAP_CLEAN:
         {
-          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
-                    "MemCache ERROR : bad HEAP allocation");
+            ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP)
+                   ,"MemCache ERROR : bad HEAP allocation");
           bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
           HeapEntry heap_entry; 
-          heap_entry.owner.srcid = r_cleanup_prev_srcid.read();
-          heap_entry.owner.inst  = r_cleanup_prev_inst.read();
+          heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
+#if L1_MULTI_CACHE
+          heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
+#endif
+          heap_entry.owner.inst     = r_cleanup_prev_inst.read();
           if(last){ // this is the last entry of the list of copies
             heap_entry.next     = r_cleanup_prev_ptr.read();
@@ -2616,9 +2789,12 @@
       case CLEANUP_HEAP_FREE:
         {
-          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
-                    "MemCache ERROR : bad HEAP allocation");
+          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP)
+                 ,"MemCache ERROR : bad HEAP allocation");
           HeapEntry heap_entry;
-          heap_entry.owner.srcid = 0;
-          heap_entry.owner.inst  = false;
+          heap_entry.owner.srcid    = 0;
+#if L1_MULTI_CACHE
+          heap_entry.owner.cache_id = 0;
+#endif
+          heap_entry.owner.inst     = false;
           if(m_heap_directory.is_full()){
             heap_entry.next     = r_cleanup_next_ptr.read();
@@ -2760,5 +2936,5 @@
                 r_llsc_wdata = m_cmd_llsc_wdata_fifo.read();
             if(r_llsc_cpt.read()>3)
-                assert(false && "MEMCACHE error : SC too long");
+                ASSERT(false,"MEMCACHE error : SC too long");
             if(r_llsc_cpt.read()==2){
                 r_llsc_wdata = m_cmd_llsc_wdata_fifo.read();
@@ -2774,12 +2950,16 @@
             size_t way = 0;
             DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
-            r_llsc_is_cnt   = entry.is_cnt;
-            r_llsc_dirty    = entry.dirty;
-            r_llsc_tag      = entry.tag;
-            r_llsc_way      = way;
-            r_llsc_copy     = entry.owner.srcid;
-            r_llsc_copy_inst= entry.owner.inst;
-            r_llsc_ptr      = entry.ptr;
-            r_llsc_count    = entry.count;
+            r_llsc_is_cnt     = entry.is_cnt;
+            r_llsc_dirty      = entry.dirty;
+            r_llsc_tag        = entry.tag;
+            r_llsc_way        = way;
+            r_llsc_copy       = entry.owner.srcid;
+#if L1_MULTI_CACHE
+            r_llsc_copy_cache = entry.owner.cache_id;
+#endif
+
+            r_llsc_copy_inst  = entry.owner.inst;
+            r_llsc_ptr        = entry.ptr;
+            r_llsc_count      = entry.count;
             if ( entry.valid ){
                 r_llsc_fsm = SC_DIR_HIT_READ;
@@ -2798,13 +2978,16 @@
           // update directory (lock & dirty bits
           DirectoryEntry entry;
-          entry.valid	    = true;
-          entry.is_cnt      = r_llsc_is_cnt.read();
-          entry.dirty	    = true;
-          entry.lock	    = true;
-          entry.tag	        = r_llsc_tag.read();
-          entry.owner.srcid = r_llsc_copy.read();
-          entry.owner.inst  = r_llsc_copy_inst.read();
-          entry.count       = r_llsc_count.read();
-          entry.ptr         = r_llsc_ptr.read();
+          entry.valid	       = true;
+          entry.is_cnt         = r_llsc_is_cnt.read();
+          entry.dirty	       = true;
+          entry.lock	       = true;
+          entry.tag	           = r_llsc_tag.read();
+          entry.owner.srcid    = r_llsc_copy.read();
+#if L1_MULTI_CACHE
+          entry.owner.cache_id = r_llsc_copy_cache.read();
+#endif
+          entry.owner.inst     = r_llsc_copy_inst.read();
+          entry.count          = r_llsc_count.read();
+          entry.ptr            = r_llsc_ptr.read();
           m_cache_directory.write(set, way, entry);
 
@@ -2938,6 +3121,6 @@
       case SC_UPT_REQ: 	// Request the update
         {
-          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
-                    "MemCache ERROR : bad HEAP allocation");
+          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC)
+                 ,"MemCache ERROR : bad HEAP allocation");
           if( !r_llsc_to_init_cmd_multi_req.read() && 
               !r_llsc_to_init_cmd_brdcast_req.read()  ){
@@ -2959,4 +3142,7 @@
             llsc_to_init_cmd_fifo_inst    = r_llsc_copy_inst.read();
             llsc_to_init_cmd_fifo_srcid   = r_llsc_copy.read();
+#if L1_MULTI_CACHE
+            llsc_to_init_cmd_fifo_cache_id= r_llsc_copy_cache.read();
+#endif
             if(r_llsc_count.read() == 1){
 #ifdef LOCK_DEBUG
@@ -2978,9 +3164,12 @@
       case SC_UPDATE:   	// send a multi-update request to INIT_CMD fsm
         {
-          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
-                    "MemCache ERROR : bad HEAP allocation");
+          ASSERT((r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC)
+                 ,"MemCache ERROR : bad HEAP allocation");
           HeapEntry entry = m_heap_directory.read(r_llsc_ptr.read());
-          llsc_to_init_cmd_fifo_inst  = entry.owner.inst;
-          llsc_to_init_cmd_fifo_srcid = entry.owner.srcid;
+          llsc_to_init_cmd_fifo_srcid    = entry.owner.srcid;
+#if L1_MULTI_CACHE
+          llsc_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
+#endif
+          llsc_to_init_cmd_fifo_inst     = entry.owner.inst;
           llsc_to_init_cmd_fifo_put = true;
 
@@ -3106,4 +3295,7 @@
             entry.count         = 0;
             entry.owner.srcid   = 0;
+#if L1_MULTI_CACHE
+            entry.owner.cache_id= 0;
+#endif
             entry.owner.inst    = false;
             entry.ptr           = 0;
@@ -3114,5 +3306,5 @@
             r_llsc_fsm = SC_INVAL;
           } else {
-            assert(false && "LOCK ERROR in LLSC_FSM, STATE = LLSC_DIR_INVAL");
+              ASSERT(false,"LOCK ERROR in LLSC_FSM, STATE = LLSC_DIR_INVAL");
           }
 
@@ -3150,5 +3342,5 @@
             r_llsc_cpt = 0;
           } else {
-            assert( false && "MEM_CACHE, LLSC FSM : SC_XRAM_SEND state : the request should not have been previously set");
+              ASSERT(false,"MEM_CACHE, LLSC FSM : SC_XRAM_SEND state : the request should not have been previously set");
           }
           break;
@@ -4109,7 +4301,13 @@
         m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
         m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
+#if L1_MULTI_CACHE
+        m_write_to_init_cmd_cache_id_fifo.put_and_get(write_to_init_cmd_fifo_cache_id);
+#endif
       } else {
         m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
         m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
+#if L1_MULTI_CACHE
+        m_write_to_init_cmd_cache_id_fifo.simple_put(write_to_init_cmd_fifo_cache_id);
+#endif
       }
     } else {
@@ -4117,4 +4315,7 @@
         m_write_to_init_cmd_inst_fifo.simple_get();
         m_write_to_init_cmd_srcid_fifo.simple_get();
+#if L1_MULTI_CACHE
+        m_write_to_init_cmd_cache_id_fifo.simple_get();
+#endif
       }
     }
@@ -4127,7 +4328,13 @@
         m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
         m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
+#if L1_MULTI_CACHE
+        m_xram_rsp_to_init_cmd_cache_id_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_cache_id);
+#endif
       } else {
         m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
         m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
+#if L1_MULTI_CACHE
+        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_put(xram_rsp_to_init_cmd_fifo_cache_id);
+#endif
       }
     } else {
@@ -4135,4 +4342,7 @@
         m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
         m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
+#if L1_MULTI_CACHE
+        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_get();
+#endif
       }
     }
@@ -4145,12 +4355,21 @@
         m_llsc_to_init_cmd_inst_fifo.put_and_get(llsc_to_init_cmd_fifo_inst);
         m_llsc_to_init_cmd_srcid_fifo.put_and_get(llsc_to_init_cmd_fifo_srcid);
+#if L1_MULTI_CACHE
+        m_llsc_to_init_cmd_cache_id_fifo.put_and_get(llsc_to_init_cmd_fifo_cache_id);
+#endif
       } else {
-        m_llsc_to_init_cmd_inst_fifo.simple_put(llsc_to_init_cmd_fifo_inst);
-        m_llsc_to_init_cmd_srcid_fifo.simple_put(llsc_to_init_cmd_fifo_srcid);
+          m_llsc_to_init_cmd_inst_fifo.simple_put(llsc_to_init_cmd_fifo_inst);
+          m_llsc_to_init_cmd_srcid_fifo.simple_put(llsc_to_init_cmd_fifo_srcid);
+#if L1_MULTI_CACHE
+          m_llsc_to_init_cmd_cache_id_fifo.simple_put(llsc_to_init_cmd_fifo_cache_id);
+#endif
       }
     } else {
-      if ( llsc_to_init_cmd_fifo_get ) {
-        m_llsc_to_init_cmd_inst_fifo.simple_get();
-        m_llsc_to_init_cmd_srcid_fifo.simple_get();
+        if ( llsc_to_init_cmd_fifo_get ) {
+            m_llsc_to_init_cmd_inst_fifo.simple_get();
+            m_llsc_to_init_cmd_srcid_fifo.simple_get();
+#if L1_MULTI_CACHE
+            m_llsc_to_init_cmd_cache_id_fifo.simple_get();
+#endif
       }
     }
@@ -4160,5 +4379,5 @@
     m_cpt_cycles++;
 
-  } // end transition()
+    } // end transition()
 
   /////////////////////////////
@@ -4297,4 +4516,10 @@
         break;
       case TGT_RSP_READ:
+          PRINTF("  * <MEM_CACHE.TGT> RSP_READ     : srcid %d, trdid %d, pktid %d\n"
+                 ,(uint32_t)r_read_to_tgt_rsp_srcid.read()
+                 ,(uint32_t)r_read_to_tgt_rsp_trdid.read()
+                 ,(uint32_t)r_read_to_tgt_rsp_pktid.read()
+                 );
+
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
@@ -4306,4 +4531,10 @@
         break;
       case TGT_RSP_WRITE:
+          PRINTF("  * <MEM_CACHE.TGT> RSP_WRITE    : BURP srcid %d, trdid %d, pktid %d\n"
+                 ,(uint32_t)r_write_to_tgt_rsp_srcid.read()
+                 ,(uint32_t)r_write_to_tgt_rsp_trdid.read()
+                 ,(uint32_t)r_write_to_tgt_rsp_pktid.read()
+                 );
+
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = 0;
@@ -4315,4 +4546,10 @@
         break;
       case TGT_RSP_CLEANUP:
+          PRINTF("  * <MEM_CACHE.TGT> RSP_CLEANUP  : srcid %d, trdid %d, pktid %d\n"
+                 ,(uint32_t)r_cleanup_to_tgt_rsp_srcid.read()
+                 ,(uint32_t)r_cleanup_to_tgt_rsp_trdid.read()
+                 ,(uint32_t)r_cleanup_to_tgt_rsp_pktid.read()
+                 );
+
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = 0;
@@ -4324,4 +4561,10 @@
         break;
       case TGT_RSP_LLSC:
+          PRINTF("  * <MEM_CACHE.TGT> RSP_LLSC     : srcid %d, trdid %d, pktid %d\n"
+                 ,(uint32_t)r_llsc_to_tgt_rsp_srcid.read()
+                 ,(uint32_t)r_llsc_to_tgt_rsp_trdid.read()
+                 ,(uint32_t)r_llsc_to_tgt_rsp_pktid.read()
+                 );
+
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = r_llsc_to_tgt_rsp_data.read();
@@ -4333,4 +4576,10 @@
         break;
       case TGT_RSP_XRAM:
+          PRINTF("  * <MEM_CACHE.TGT> RSP_XRAM     : srcid %d, trdid %d, pktid %d\n"
+                 ,(uint32_t)r_xram_rsp_to_tgt_rsp_srcid.read()
+                 ,(uint32_t)r_xram_rsp_to_tgt_rsp_trdid.read()
+                 ,(uint32_t)r_xram_rsp_to_tgt_rsp_pktid.read()
+                 );
+
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
@@ -4343,4 +4592,10 @@
         break;
       case TGT_RSP_INIT:
+          PRINTF("  * <MEM_CACHE.TGT> RSP_INIT     : srcid %d, trdid %d, pktid %d\n"
+                 ,(uint32_t)r_init_rsp_to_tgt_rsp_srcid.read()
+                 ,(uint32_t)r_init_rsp_to_tgt_rsp_trdid.read()
+                 ,(uint32_t)r_init_rsp_to_tgt_rsp_pktid.read()
+                 );
+
         p_vci_tgt.rspval   = true;
         p_vci_tgt.rdata    = 0;
@@ -4359,5 +4614,4 @@
     p_vci_ini.cmd     = vci_param::CMD_WRITE;
     p_vci_ini.srcid   = m_srcid_ini;
-    p_vci_ini.pktid   = 0;
     p_vci_ini.cons    = true;
     p_vci_ini.wrap    = false;
@@ -4377,7 +4631,14 @@
         p_vci_ini.plen    = 0;
         p_vci_ini.trdid   = 0;
+        p_vci_ini.pktid   = 0;
         p_vci_ini.eop     = false;
         break;
       case INIT_CMD_INVAL_NLINE:
+      {
+        PRINTF("  * <MEM_CACHE.INIT_CMD> INVAL_NLINE : trdid %d, pktid %d\n"
+               ,(uint32_t)r_xram_rsp_to_init_cmd_trdid.read()
+               ,(uint32_t)m_xram_rsp_to_init_cmd_cache_id_fifo.read()
+               );
+        
         p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
         if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
@@ -4392,6 +4653,8 @@
         p_vci_ini.plen    = 4;
         p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_xram_rsp_to_init_cmd_cache_id_fifo.read();
         p_vci_ini.eop     = true;
         break;
+      }
       case INIT_CMD_XRAM_BRDCAST:
         p_vci_ini.cmdval  = true;
@@ -4401,4 +4664,5 @@
         p_vci_ini.plen    = 4;
         p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = 0;
         p_vci_ini.eop     = true;
         break;
@@ -4412,4 +4676,5 @@
         p_vci_ini.eop     = true;
         p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = 0;
         break;
       case INIT_CMD_UPDT_NLINE:
@@ -4429,4 +4694,5 @@
         p_vci_ini.eop     = false;
         p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
         break;
       case INIT_CMD_UPDT_INDEX:
@@ -4441,4 +4707,5 @@
         p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
         p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
         p_vci_ini.eop     = false;
         break;
@@ -4456,4 +4723,5 @@
         p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
         p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
         p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
         break;
@@ -4467,4 +4735,5 @@
         p_vci_ini.eop     = true;
         p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = 0;
         break;
       case INIT_CMD_SC_UPDT_NLINE:
@@ -4488,4 +4757,5 @@
         p_vci_ini.eop     = false;
         p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_llsc_to_init_cmd_cache_id_fifo.read();
         break;
       case INIT_CMD_SC_UPDT_INDEX:
@@ -4504,4 +4774,5 @@
         }
         p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_llsc_to_init_cmd_cache_id_fifo.read();
         p_vci_ini.eop     = false;
         break;
@@ -4516,4 +4787,5 @@
         p_vci_ini.be      = 0xF;
         p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_llsc_to_init_cmd_cache_id_fifo.read();
         if(r_llsc_to_init_cmd_is_long.read()){
             p_vci_ini.plen    = 4 * 4;
@@ -4535,4 +4807,5 @@
         p_vci_ini.plen    = 4 * 4;
         p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.pktid   = m_llsc_to_init_cmd_cache_id_fifo.read();
         p_vci_ini.eop     = true;
         break;
@@ -4567,4 +4840,6 @@
       case CLEANUP_RSP:
         {
+            PRINTF("  * <MEM_CACHE.CLEANUP_RSP> Respons to %d.%d\n",(uint32_t)r_cleanup_srcid.read(),(uint32_t)r_cleanup_pktid.read());
+
           p_vci_tgt_cleanup.rspval = true;
           p_vci_tgt_cleanup.rdata  = 0;
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/Makefile
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/Makefile	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/Makefile	(revision 140)
@@ -1,7 +1,7 @@
 #NO_SOFT		=  1
 ARCH			=  mips32el
-#SIMULATION_ARGS	=  100000
-#SOCLIB_CC_ADD_ARGS	= "-DCC_XCACHE_WRAPPER_DEBUG=1"
-SOCLIB_CC_ADD_ARGS=-t systemcass
+#SIMULATION_ARGS	=  
+#SOCLIB_CC_ADD_ARGS	= -t systemc_32
+SOCLIB_CC_ADD_ARGS	= -t systemcass
 SOCLIB			?= $(shell soclib-cc --getpath)
 export SOCLIB
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/configuration/default.cfg
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/configuration/default.cfg	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/configuration/default.cfg	(revision 140)
@@ -1,5 +1,6 @@
 4
+1 1
 4 64 16
 4 64 16
-8 8 16
+4 8 16
 16 256 16 4096
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/configuration/gen_config.sh
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/configuration/gen_config.sh	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/configuration/gen_config.sh	(revision 140)
@@ -1,35 +1,43 @@
 #!/bin/bash
 
-#               archi1  archi2  archi3  archi4
-archi_name=(    "00512" "16384" "01024" "02048");
-iways=(         "1"     "4"     "16"    "4"    );
-isets=(         "8"     "64"    "1"     "8"    );
-iwords=(        "16"    "16"    "16"    "16"   );
-dways=(         "1"     "4"     "16"    "4"    );
-dsets=(         "8"     "64"    "1"     "8"    );
-dwords=(        "16"    "16"    "16"    "16"   );
-memc_nways=(    "4"     "16"    "8"     "2"    );
-memc_nsets=(    "4"     "256"   "64"    "32"   );
-memc_words=(    "16"    "16"    "16"    "16"   );
-memc_heap_size=("4096"  "4096"  "4096"  "4096" );
+#               archi1  archi2  archi3       archi4  archi5 
+archi_name=(    "min"   "tsar"  "full_assoc" "2k"    "4k"   );
+iways=(         "1"     "4"     "16"         "4"     "4"    );
+isets=(         "8"     "64"    "1"          "8"     "16"   );
+iwords=(        "16"    "16"    "16"         "16"    "16"   );
+dways=(         "1"     "4"     "16"         "4"     "4"    );
+dsets=(         "8"     "64"    "1"          "8"     "16"   );
+dwords=(        "16"    "16"    "16"         "16"    "16"   );
+memc_nways=(    "4"     "16"    "8"          "2"     "16"   );
+memc_nsets=(    "4"     "256"   "64"         "32"    "64"   );
+memc_words=(    "16"    "16"    "16"         "16"    "16"   );
+memc_heap_size=("4096"  "4096"  "4096"       "4096"  "4096" );
 
-nb_proc=( "1" "15" "+1" "4");
-wnwords=( "1" "16" "*2" "8");
-wnlines=( "1" "8"  "*2" "8");
-wtimeout=("1" "1024" "*4" "16");
+nb_proc=(        "1" "15"   "+1" "4");
+nb_cpu_by_cache=("1" "15"   "*2" "1");
+nb_cache=(       "1" "16"   "*2" "1");
+#wnwords=(        "1" "16"   "*2" "4");
+#wnlines=(        "1" "8"    "*2" "8");
+#wtimeout=(       "1" "1024" "*4" "16");
+
+wnwords=(        "4"  "4"  "*2" "4");
+wnlines=(        "8"  "8"  "*2" "8");
+wtimeout=(       "16" "16" "*4" "16");
 
 archi_default="1";
+gen_cfg=0;
 
 function gen_file ()
 {
-        filename=$(printf "x%.2d-xcache_%s-wbuf_%.2d_%.2d_%.4d.cfg" ${1} ${archi_name[${2}]} ${3} ${4} ${5});
+        filename=$(printf "archi_%s-x%.2d_%.2d_%.2d-wbuf_%.2d_%.2d_%.4d.cfg" ${archi_name[${4}]} ${1} ${2} ${3} ${5} ${6} ${7});
 
         echo ${filename};
 
-        echo "${1}" > ${filename};
-        echo "${iways[${2}]} ${isets[${2}]} ${iwords[${2}]}" >> ${filename};
-        echo "${dways[${2}]} ${dsets[${2}]} ${dwords[${2}]}" >> ${filename};
-        echo "${3} ${4} ${5}" >> ${filename};
-        echo "${memc_nways[${2}]} ${memc_nsets[${2}]} ${memc_words[${2}]} ${memc_heap_size[${2}]}" >> ${filename};
+        echo "${1}" >  ${filename};
+        echo "${2} ${3}" >> ${filename};
+        echo "${iways[${4}]} ${isets[${4}]} ${iwords[${4}]}" >> ${filename};
+        echo "${dways[${4}]} ${dsets[${4}]} ${dwords[${4}]}" >> ${filename};
+        echo "${5} ${6} ${7}" >> ${filename};
+        echo "${memc_nways[${4}]} ${memc_nsets[${4}]} ${memc_words[${4}]} ${memc_heap_size[${4}]}" >> ${filename};
 }
 
@@ -41,5 +49,6 @@
         echo ${filename};
 
-        echo "${nb_proc[3]}" > ${filename};
+        echo "${nb_proc[3]}"  >  ${filename};
+        echo "${nb_cpu_by_cache[3]} ${nb_cache[3]}" >> ${filename};
         echo "${iways[${archi}]} ${isets[${archi}]} ${iwords[${archi}]}" >> ${filename};
         echo "${dways[${archi}]} ${dsets[${archi}]} ${dwords[${archi}]}" >> ${filename};
@@ -50,29 +59,48 @@
 gen_default ${archi_default};
 
-nb_archi=${#iways[*]};
+if test ${gen_cfg} -ne 0; then
+    nb_archi=${#iways[*]};
+    
+    num_archi=0;
+    while test ${num_archi} -lt ${nb_archi}; do
+        num_proc=${nb_proc[0]};
+        while test ${num_proc} -le ${nb_proc[1]}; do
+            num_cpu_by_cache=${nb_cpu_by_cache[0]};
+            while test ${num_cpu_by_cache} -le ${nb_cpu_by_cache[1]}; do
 
-num_archi=0;
-while test ${num_archi} -lt ${nb_archi}; do
-    num_proc=${nb_proc[0]};
-    while test ${num_proc} -le ${nb_proc[1]}; do
-        num_words=${wnwords[0]};
-        while test ${num_words} -le ${wnwords[1]}; do
-            num_lines=${wnlines[0]};
-            while test ${num_lines} -le ${wnlines[1]}; do
-                num_timeout=${wtimeout[0]};
-                while test ${num_timeout} -le ${wtimeout[1]}; do
+                if test $((${num_proc} * ${num_cpu_by_cache})) -le ${nb_cpu_by_cache[1]}; then
 
-                    gen_file ${num_proc} ${num_archi} ${num_words} ${num_lines} ${num_timeout};
+                num_cache=${nb_cache[0]};
+                while test ${num_cache} -le ${nb_cache[1]}; do
+                
+                    if test ${num_cache} -ge ${num_cpu_by_cache}; then
+                    if test ${num_cpu_by_cache} -ne 1 -o ${num_cache} -eq 1; then
 
-                    num_timeout=$((${num_timeout} ${wtimeout[2]}));
+                    num_words=${wnwords[0]};
+                    while test ${num_words} -le ${wnwords[1]}; do
+                        num_lines=${wnlines[0]};
+                        while test ${num_lines} -le ${wnlines[1]}; do
+                            num_timeout=${wtimeout[0]};
+                            while test ${num_timeout} -le ${wtimeout[1]}; do
+                                
+                                gen_file ${num_proc} ${num_cpu_by_cache} ${num_cache} ${num_archi} ${num_words} ${num_lines} ${num_timeout};
+                                
+                                num_timeout=$((${num_timeout} ${wtimeout[2]}));
+                            done;
+                            num_lines=$((${num_lines} ${wnlines[2]}));
+                        done;
+                        num_words=$((${num_words} ${wnwords[2]}));
+                    done;
+                    fi;
+                    fi;
+                    num_cache=$((${num_cache} ${nb_cache[2]}));
                 done;
-                num_lines=$((${num_lines} ${wnlines[2]}));
+                fi;
+                num_cpu_by_cache=$((${num_cpu_by_cache} ${nb_cpu_by_cache[2]}));
             done;
-            num_words=$((${num_words} ${wnwords[2]}));
+            num_proc=$((${num_proc} ${nb_proc[2]}));
         done;
-        num_proc=$((${num_proc} ${nb_proc[2]}));
+        num_archi=$((${num_archi}+1));
     done;
-    num_archi=$((${num_archi}+1));
-done;
+fi;
 
-
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/segmentation.h
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/segmentation.h	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/segmentation.h	(revision 140)
@@ -35,4 +35,10 @@
 #define MC_M_SIZE	0x000F0000
 
+#define MC_R_BASE	0x20200000
+#define MC_R_SIZE	0x00000008
+
+#define MC_U_BASE	0x30000000
+#define MC_U_SIZE	0x000F0000
+
 //////////////////////////////////////////////////////////
 //	System devices
@@ -51,13 +57,2 @@
 #define C_PROC_SIZE	0x00000010
 #define C_PROC_SPAN     0x01000000
-
-#define MC_R_BASE	0x20200000
-#define MC_R_SIZE	0x00000008
-
-//#define C_MC_M_BASE	0x00200000
-//#define C_MC_M_SIZE	0x00000008
-
-//#define XRAM_BASE	0xB0200000
-//#define XRAM_SIZE	0x00000008
-
-//#define CLEANUP_OFFSET  0x20200000
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/Makefile
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/Makefile	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/Makefile	(revision 140)
@@ -1,12 +1,16 @@
-ADD_OBJS	= 	stdio.o stdlib.o exception.o system.o \
-			$(patsubst %.c,%.o,$(wildcard *.c)) \
-			$(patsubst common/%.c,common/%.o,$(wildcard common/*.c)) \
-			$(patsubst irq/%.c,irq/%.o,$(wildcard irq/*.c)) \
-			$(patsubst benchmark/%.c,benchmark/%.o,$(wildcard benchmark/*.c)) \
+ADD_OBJS	= 	\
+			$(patsubst self_code_modifying/%.c,self_code_modifying/%.o,$(wildcard self_code_modifying/*.c))  \
 			$(patsubst matrix_multiplication/%.c,matrix_multiplication/%.o,$(wildcard matrix_multiplication/*.c)) \
 			$(patsubst sort/%.c,sort/%.o,$(wildcard sort/*.c)) \
-			$(patsubst dhrystone/%.c,dhrystone/%.o,$(wildcard dhrystone/*.c))
+			$(patsubst dhrystone/%.c,dhrystone/%.o,$(wildcard dhrystone/*.c)) \
+			$(patsubst benchmark/%.c,benchmark/%.o,$(wildcard benchmark/*.c)) \
+			$(patsubst irq/%.c,irq/%.o,$(wildcard irq/*.c)) \
+			$(patsubst common/%.c,common/%.o,$(wildcard common/*.c)) \
+			$(patsubst %.c,%.o,$(wildcard *.c)) \
+			stdio.o stdlib.o exception.o system.o
+
 
 ADD_CFLAGS	=
+ADD_LDFLAGS	=
 SOCLIB		?=	$(shell soclib-cc --getpath)
 
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark.c
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark.c	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark.c	(revision 140)
@@ -6,50 +6,84 @@
 void benchmark (void)
 {
-  /* if(procnum() != 0) */
-  /*   EXIT(0); */
-
-  int result = 0;
+  int result      = 0;
+  int num_cpu     = procnum();
   int cycle_begin = cycle_begin = cpu_cycles();
-
-  switch (procnum())
-    {
-    default :
-      {
+  
+  if (num_cpu < BENCHMARK_NB_THREAD)
+   switch (num_cpu)
+     {
+     default :
+        {
 #if BENCHMARK_MATRIX_MULTIPLICATION_MT
-        int result_mm_mt = benchmark_matrix_multiplication_mt();
-        result += result_mm_mt;
+          int result_mm_mt = benchmark_matrix_multiplication_mt();
+          result += result_mm_mt;
 #endif
 #if BENCHMARK_DHRYSTONE
-        int result_dhrystone = benchmark_dhrystone();
-        result += result_dhrystone;
+          int result_dhrystone = benchmark_dhrystone();
+          result += result_dhrystone;
 #endif
-#if BENCHMARK_SORT
-        int result_sort = benchmark_sort();
-        result += result_sort;
+#if BENCHMARK_SORT_ALL
+          int result_sort_all = benchmark_sort_all();
+          result += result_sort_all;
+#endif
+#if BENCHMARK_SORT_BUBBLE
+          int result_sort_bubble = benchmark_sort_bubble();
+          result += result_sort_bubble;
+#endif
+#if BENCHMARK_SORT_INSERTION
+          int result_sort_insertion = benchmark_sort_insertion();
+          result += result_sort_insertion;
+#endif
+#if BENCHMARK_SORT_SELECTION
+          int result_sort_selection = benchmark_sort_selection();
+          result += result_sort_selection;
+#endif
+#if BENCHMARK_SORT_SHELL
+          int result_sort_shell = benchmark_sort_shell();
+          result += result_sort_shell;
 #endif
 #if BENCHMARK_MATRIX_MULTIPLICATION_ST
-        int result_mm_st = benchmark_matrix_multiplication_st();
-        result += result_mm_st;
+          int result_mm_st = benchmark_matrix_multiplication_st();
+          result += result_mm_st;
 #endif
-
-        printf("\n");
-        printf("--------------------------------\n");
-        printf( "Partial results :\n");
+#if BENCHMARK_SELF_CODE_MODIFYING
+          int result_self_code_modifying = benchmark_self_code_modifying();
+          result += result_self_code_modifying;
+#endif
+          
+          printf("\n");
+          printf("--------------------------------\n");
+          printf( "Partial results :\n");
 #if BENCHMARK_MATRIX_MULTIPLICATION_MT
-        printf(" * MM MT           : %d\n",result_mm_mt);
+          printf(" * MM MT               : %d\n",result_mm_mt);
 #endif
 #if BENCHMARK_DHRYSTONE
-        printf(" * DHRYSTONE       : %d\n",result_dhrystone);
+          printf(" * DHRYSTONE           : %d\n",result_dhrystone);
 #endif
-#if BENCHMARK_SORT
-        printf(" * SORT            : %d\n",result_sort);
+#if BENCHMARK_SORT_ALL
+          printf(" * SORT_ALL            : %d\n",result_sort_all);
+#endif
+#if BENCHMARK_SORT_BUBBLE
+          printf(" * SORT_BUBBLE         : %d\n",result_sort_bubble);
+#endif
+#if BENCHMARK_SORT_INSERTION
+          printf(" * SORT_INSERTION      : %d\n",result_sort_insertion);
+#endif
+#if BENCHMARK_SORT_SELECTION
+          printf(" * SORT_SELECTION      : %d\n",result_sort_selection);
+#endif
+#if BENCHMARK_SORT_SHELL
+          printf(" * SORT_SHELL          : %d\n",result_sort_shell);
 #endif
 #if BENCHMARK_MATRIX_MULTIPLICATION_ST
-        printf(" * MM ST           : %d\n",result_mm_st);
+          printf(" * MM ST               : %d\n",result_mm_st);
 #endif 
-        printf("--------------------------------\n");
-       break;
+#if BENCHMARK_SELF_CODE_MODIFYING
+          printf(" * SELF_CODE_MODIFYING : %d\n",result_self_code_modifying);
+#endif
+          printf("--------------------------------\n");
+          break;
+        }
       }
-    }
 
   printf("\n");
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark.h
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark.h	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark.h	(revision 140)
@@ -5,5 +5,9 @@
 
 void benchmark                         (void);
-int  benchmark_sort                    (void);
+int  benchmark_sort_all                (void);
+int  benchmark_sort_bubble             (void);
+int  benchmark_sort_insert             (void);
+int  benchmark_sort_selection          (void);
+int  benchmark_sort_shell              (void);
 int  benchmark_dhrystone               (void);
 int  benchmark_matrix_multiplication_st(void);
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark_matrix_multiplication.c
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark_matrix_multiplication.c	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark_matrix_multiplication.c	(revision 140)
@@ -127,7 +127,9 @@
   /* matrix_multiplication_print(matrix_local_d, size); */
   
+#if VERIFICATION_MATRIX_MULTIPLICATION
   printf(" * Verification... ");
   
   benchmark_matrix_validation (matrix_local_d, size);
+#endif
   
   printf(" * Free...\n");
@@ -230,7 +232,9 @@
   if (matrix_nb_thread_stop == matrix_nb_thread_start)
     {
+#if VERIFICATION_MATRIX_MULTIPLICATION
       printf(" * Verification... ");
 
       benchmark_matrix_validation (matrix_global_d, size);
+#endif
       
       printf(" * Free...\n");
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark_self_code_modifying.c
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark_self_code_modifying.c	(revision 140)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark_self_code_modifying.c	(revision 140)
@@ -0,0 +1,31 @@
+#include "benchmark.h"
+#include "system.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "../self_code_modifying/self_code_modifying.h"
+
+static uint32_t nb_thread;
+
+int _benchmark_self_code_modifying (unsigned int nb_runs)
+{
+  printf("\n");
+  printf("================================\n");
+  printf("Benchmark Self_Code_Modifying\n");
+  printf("================================\n");
+  printf("\n");
+
+  int result = 0;
+  
+  if (atomic_inc(&nb_thread) == 1)
+    {
+      result = self_code_modifying(nb_runs);
+    }
+  else
+    {
+      printf("The self_code_modifying benchmark is not multi threaded.\n");
+    }
+    
+  return result;
+}
+
+int benchmark_self_code_modifying (void) { return _benchmark_self_code_modifying(SELF_CODE_MODIFYING_NB_RUNS); }
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark_sort.c
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark_sort.c	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/benchmark/benchmark_sort.c	(revision 140)
@@ -9,5 +9,82 @@
 static uint32_t sort_lock;
 
-int _benchmark_sort (unsigned int size)
+int _benchmark_sort (sort_t sort_type,
+                     unsigned int size)
+{
+  printf(" * Size : %d\n",size);
+
+  unsigned int* SortArray;
+  
+  int cycle_begin;
+
+  int num_cpu=procnum();
+  
+  printf(" * Algo : %s\n",sort_str(sort_type));
+  
+  printf("   * Init...\n");
+  
+  lock_lock(&sort_lock);
+  SortArray = (unsigned int*) malloc(size*sizeof(unsigned int));
+  lock_unlock(&sort_lock);
+  
+  unsigned int seed = num_cpu;
+  int i;
+  for (i=0; i<size; ++i)
+    {
+      seed = seed * 1103515245 + 12345;
+      SortArray[i] = seed&0xff;
+    }
+  printf("   * Sort... \n");
+  
+  cycle_begin = cpu_cycles();
+  sort((unsigned int *) (SortArray), (unsigned int) size, sort_type);
+  int cycle_exec = cpu_cycles()-cycle_begin;
+  
+  printf("   * Executed in %d cycles\n",cycle_exec);
+  
+  int result = cycle_exec;
+  
+#if VERIFICATION_SORT      
+  printf("   * Verification... ");
+  
+  for (i = 1; i < size; i++)
+    {
+      /* printf("%d ",SortArray[i-1]); */
+      
+      if (SortArray[i] < SortArray[i-1])
+        {
+          printf("KO !!!\n");
+          EXIT(1);
+        }
+    }
+  printf("OK\n");
+#endif
+  
+  free (SortArray);
+
+  return result;
+}
+
+int _benchmark_sort_all (unsigned int size)
+{
+  printf("\n");
+  printf("================================\n");
+  printf("Benchmark Sort (ALL)\n");
+  printf("================================\n");
+  printf("\n");
+
+  int result = 0;
+  int num_cpu=procnum();
+  sort_t _sort_type;
+  const sort_t nb_sort_type = 4;
+  
+  for (_sort_type=0; _sort_type < nb_sort_type; _sort_type++)
+    result += _benchmark_sort((_sort_type+num_cpu)%nb_sort_type,size);
+  
+  return result;
+}
+
+int _benchmark_sort_one (sort_t sort_type,
+                         unsigned int size)
 {
   printf("\n");
@@ -17,68 +94,10 @@
   printf("\n");
 
-  printf(" * Size : %d\n",size);
-
-  unsigned int* SortArray;
-  
-  int cycle_begin, result;
-
-  result = 0;
-  
-  int p=procnum();
-  
-  sort_t _sort_type;
-  const sort_t nb_sort_type = 4;
-  
-  for (_sort_type=0; _sort_type < nb_sort_type; _sort_type++)
-    {
-      sort_t sort_type = (_sort_type+p)%nb_sort_type;
-      
-      printf(" * Algo : %s\n",sort_str(sort_type));
-      
-      printf("   * Init...\n");
-      
-      lock_lock(&sort_lock);
-      SortArray = (unsigned int*) malloc(size*sizeof(unsigned int));
-      lock_unlock(&sort_lock);
-      
-      unsigned int seed = p;
-      int i;
-      for (i=0; i<size; ++i)
-        {
-          seed = seed * 1103515245 + 12345;
-          SortArray[i] = seed&0xff;
-        }
-      printf("   * Sort... \n");
-      
-      cycle_begin = cpu_cycles();
-      sort((unsigned int *) (SortArray), (unsigned int) size, sort_type);
-      int cycle_exec = cpu_cycles()-cycle_begin;
-      
-      printf("   * Executed in %d cycles\n",cycle_exec);
-      
-      result += cycle_exec;
-      
-      printf("   * Verification... ");
-      
-      for (i = 1; i < size; i++)
-        {
-          /* printf("%d ",SortArray[i-1]); */
-          
-          if (SortArray[i] < SortArray[i-1])
-            {
-              printf("KO !!!\n");
-              EXIT(1);
-            }
-        }
-      printf("OK\n");
-
-      free (SortArray);
-
-    }
-  
-  return result;
+  return _benchmark_sort(sort_type,size);
 }
 
-int benchmark_sort (void) { return _benchmark_sort(SORT_SIZE); }
-
-  
+int benchmark_sort_all       (void) { return _benchmark_sort_all(SORT_ALL_SIZE); }
+int benchmark_sort_bubble    (void) { return _benchmark_sort_one(SORT_BUBBLE   ,SORT_BUBBLE_SIZE   ); }
+int benchmark_sort_insertion (void) { return _benchmark_sort_one(SORT_INSERTION,SORT_INSERTION_SIZE); }
+int benchmark_sort_selection (void) { return _benchmark_sort_one(SORT_SELECTION,SORT_SELECTION_SIZE); }
+int benchmark_sort_shell     (void) { return _benchmark_sort_one(SORT_SHELL    ,SORT_SHELL_SIZE    ); }
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/common/common.c
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/common/common.c	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/common/common.c	(revision 140)
@@ -41,4 +41,6 @@
     }
 
+  pause();
+  
   while(1);
 }
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/define.h
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/define.h	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/define.h	(revision 140)
@@ -3,17 +3,32 @@
 
 // List of benchmark
+#define BENCHMARK_NB_THREAD                   4
+
 #define BENCHMARK_DHRYSTONE                   0
-#define BENCHMARK_SORT                        0
+#define BENCHMARK_SORT_ALL                    0
+#define BENCHMARK_SORT_BUBBLE                 0
+#define BENCHMARK_SORT_INSERTION              0
+#define BENCHMARK_SORT_SELECTION              0
+#define BENCHMARK_SORT_SHELL                  1
 #define BENCHMARK_MATRIX_MULTIPLICATION_ST    0
-#define BENCHMARK_MATRIX_MULTIPLICATION_MT    1
+#define BENCHMARK_MATRIX_MULTIPLICATION_MT    0
+#define BENCHMARK_SELF_CODE_MODIFYING         0
 
 #define VERBOSE_SORT                          0
 
+#define VERIFICATION_SORT                     0
+#define VERIFICATION_MATRIX_MULTIPLICATION    0
+
 // Benchmark size
 #define DHRYSTONE_NB_RUNS                     5000
-#define SORT_SIZE                             850
+#define SORT_ALL_SIZE                         1000
+#define SORT_BUBBLE_SIZE                      1500
+#define SORT_INSERTION_SIZE                   2300
+#define SORT_SELECTION_SIZE                   1600
+#define SORT_SHELL_SIZE                       4000
 #define MATRIX_MULTIPLICATION_ST_SIZE         50
-#define MATRIX_MULTIPLICATION_MT_SIZE         75
+#define MATRIX_MULTIPLICATION_MT_SIZE         96
 #define MATRIX_MULTIPLICATION_MT_LOCK_BY_LINE 1
+#define SELF_CODE_MODIFYING_NB_RUNS           10
 
 // Timer configuration
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/dhrystone/dhry21a.c
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/dhrystone/dhry21a.c	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/dhrystone/dhry21a.c	(revision 140)
@@ -76,6 +76,6 @@
   DOUBLE   dtime();
 
-        One_Fifty       Int_1_Loc;
-  REG   One_Fifty       Int_2_Loc;
+        One_Fifty       Int_1_Loc = 0;
+  REG   One_Fifty       Int_2_Loc = 0;
         One_Fifty       Int_3_Loc;
   REG   char            Ch_Index;
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/matrix_multiplication/matrix_multiplication.c
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/matrix_multiplication/matrix_multiplication.c	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/matrix_multiplication/matrix_multiplication.c	(revision 140)
@@ -2,4 +2,5 @@
 #include "stdio.h"
 #include "system.h"
+#include "stdint.h"
 
 void matrix_multiplication_st (int ** a,
@@ -8,5 +9,5 @@
                                unsigned int n)
 {
-  int x, y;
+  uint32_t x, y;
 
   for (x=0; x<n; ++x)
@@ -16,5 +17,5 @@
       for (y=0; y<n; ++y)
         {
-          int i;
+          uint32_t i;
 
           int tmp = 0;
@@ -28,6 +29,6 @@
 }
 
-static int lock;
-static int next;
+static uint32_t lock;
+static uint32_t next;
 
 void matrix_multiplication_mt (int ** a,
@@ -37,5 +38,5 @@
                                int lock_by_line)
 {
-  int x, y;
+  uint32_t x, y;
 
   while (1)
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/self_code_modifying/self_code_modifying.c
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/self_code_modifying/self_code_modifying.c	(revision 140)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/self_code_modifying/self_code_modifying.c	(revision 140)
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <stdlib.h>
+/* #include <unistd.h> */
+/* #include <sys/mman.h> */
+/* #include <errno.h> */
+/* #include <string.h> */
+
+#define SELF_CODE_MODIFYING      1
+#define SELF_CODE_MODIFYING_ADDR 1
+// 0 : with label in function
+// 1 : fixed
+
+
+#if SELF_CODE_MODIFYING
+static int  self_code_modifying_nb_runs;
+extern char self_code_modifying_function_destination_start;
+extern char self_code_modifying_function_destination_end;
+extern char self_code_modifying_function_source_start;
+extern char self_code_modifying_function_source_end;
+
+int  self_code_modifying_manage              (int nb_runs);
+void self_code_modifying_function_source     (void);
+void self_code_modifying_function_destination(void);
+
+int self_code_modifying(int nb_runs)
+{
+ return self_code_modifying_manage(nb_runs);
+}
+
+int  self_code_modifying_manage(int nb_runs)
+{
+  
+//  // Change the memory protection
+//  unsigned page = (unsigned)&self_code_modifying_function_destination_start & ~( getpagesize() - 1 );
+//  
+//  if( mprotect( (char*)page, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC ) )
+//    {
+//      perror( "mprotect failed" );
+//      exit( errno );
+//    }
+
+  // First execution
+  self_code_modifying_function_destination();
+
+
+#if   (SELF_CODE_MODIFYING_ADDR==0)
+  int function_source_start      = (int)&self_code_modifying_function_source_start     ;
+  int function_source_end        = (int)&self_code_modifying_function_source_end       ;
+  int function_destination_start = (int)&self_code_modifying_function_destination_start;
+  int function_destination_end   = (int)&self_code_modifying_function_destination_end  ;
+#elif (SELF_CODE_MODIFYING_ADDR==1)
+  int function_source_start      = 0x00400330;
+  int function_source_end        = 0x00400358;
+  int function_destination_start = 0x0040036c;
+  int function_destination_end   = 0x004004d8;
+#else
+  #error "Invalid SELF_CODE_MODIFYING_ADDR."
+#endif
+
+  int size_source      = function_source_end     -function_source_start;
+  int size_destination = function_destination_end-function_destination_start;
+  
+  printf(" * self_code_modifying_function_destination : %x to %x (%d bytes)\n",function_destination_start,function_destination_end,size_destination);
+  printf(" * self_code_modifying_function_source      : %x to %x (%d bytes)\n",function_source_start     ,function_source_end     ,size_source);
+  
+  if (size_destination<size_source)
+    {
+      printf("Size of destination is too short\n");
+      return 1;
+    }
+  
+  printf(" * memcpy\n");
+  memcpy((void*)function_destination_start, (void*)function_source_start, function_source_end - function_source_start );
+  
+  while (self_code_modifying_nb_runs<nb_runs)
+    {
+      self_code_modifying_function_destination();
+    }
+
+  return 0;
+}
+
+void self_code_modifying_function_source(void)
+{
+  int  (*callPrintf  )(const char *format, ...); 
+ 
+  asm volatile( "self_code_modifying_function_source_start:" );
+  
+  (*(callPrintf=&printf))( " + self_code_modifying_function_source\n" );
+  self_code_modifying_nb_runs++;
+  (*(callPrintf=&printf))( " + Number of call : %d\n",self_code_modifying_nb_runs);
+  
+  asm volatile( "self_code_modifying_function_source_end:");
+}
+
+void self_code_modifying_function_destination(void)
+{
+  int  (*callPrintf  )(const char *format, ...); 
+
+  asm volatile( "self_code_modifying_function_destination_start:");
+
+  (*(callPrintf=&printf))( " + self_code_modifying_function_destination\n" );
+  
+  // Padding
+  asm volatile (//".set push        \n\t"
+                //".set noreorder   \n\t"
+                //".set noat        \n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t"
+                "nop; nop; nop; nop; nop; nop; nop; nop;\n\t");
+    
+  asm volatile( "self_code_modifying_function_destination_end:");
+}
+
+#else
+
+int self_code_modifying(int nb_runs)
+{
+  return 0;
+}
+
+#endif
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/self_code_modifying/self_code_modifying.h
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/self_code_modifying/self_code_modifying.h	(revision 140)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/soft/self_code_modifying/self_code_modifying.h	(revision 140)
@@ -0,0 +1,6 @@
+#ifndef self_code_modifying_h
+#define self_code_modifying_h
+
+int self_code_modifying(int nb_runs);
+
+#endif // self_code_modifying_h
Index: trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/top.cpp
===================================================================
--- trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/top.cpp	(revision 139)
+++ trunk/platforms/caba-ring-ccxcachev4_memcachev4-mips32el/top.cpp	(revision 140)
@@ -31,12 +31,15 @@
 #  define PARAM_VCI                         4,8,32,1,1,1,8,4,4,1
 
+#  define USE_OLD_XCACHE                    0
+#  define USE_VGMN                          1
 #  define NB_PROC_MIN                       1
 #  define NB_PROC_MAX                       15
-//                                          min_latency, fifo_depth
+//                                          fifo_depth
 #  define PARAM_RING_P                      2
 #  define PARAM_RING_C                      2
 #  define PARAM_RING_X                      2
 //                                          pti    , hwi    , wti, irq
-#  define PARAM_XICU                        nb_proc, nb_proc, 0  , nb_proc
+#  define PARAM_XICU                        nb_proc*nb_cpu_by_cache, nb_proc*nb_cpu_by_cache, 0  , nb_proc*nb_cpu_by_cache
+//#define PARAM_XICU                        nb_proc, nb_proc, 0  , nb_proc
 
 // * Debug
@@ -46,5 +49,5 @@
                                             
 // * Simulation                             
-#  define FILE_DEFAULT                      "configuration/default.cfg"
+#  define CONFIG_DEFAULT                      "configuration/default.cfg"
 #  define NCYCLES_DEFAULT                   0
 #  define SOFT_DEFAULT                      "soft/bin.soft"
@@ -53,8 +56,17 @@
 void usage (char * funcname)
 {
-  std::cout << funcname << " [nb_cycle [file [soft]]] " << std::endl;
-  std::cout << " * nb_cycle : number of simulated cycle, if 0 then no stop condition. (default : " << NCYCLES_DEFAULT << " cycle(s))" << std::endl;
-  std::cout << " * file     : Configuration file : nb_proc, iways, isets, iwords, dways, dsets, dwords, wnwords, wnlines, wtimeout, memc_nways, memc_nsets, memc_words, memc_heap_size. (default : " << FILE_DEFAULT << " cycle(s))" << std::endl;
-  std::cout << " * soft     : software executed by this platforms. (default : \"" << SOFT_DEFAULT << "\")" << std::endl;
+  std::cout << funcname << " [option] " << std::endl;
+  std::cout << " * -NCYCLES int : number of simulated cycle, if 0 then no stop condition." << std::endl;
+  std::cout << "                  default : " << NCYCLES_DEFAULT << " cycle(s)" << std::endl;
+  std::cout << " * -CFG string  : configuration file" << std::endl;
+  std::cout << "                    - nb_proc," << std::endl;
+  std::cout << "                    - nb_cpu_by_cache, nb_dcache," << std::endl;
+  std::cout << "                    - iways, isets, iwords," << std::endl;
+  std::cout << "                    - dways, dsets, dwords," << std::endl;
+  std::cout << "                    - wnwords, wnlines, wtimeout," << std::endl;
+  std::cout << "                    - memc_nways, memc_nsets, memc_words, memc_heap_size." << std::endl;
+  std::cout << "                  default : \"" << CONFIG_DEFAULT << "\"" << std::endl;
+  std::cout << " * -SOFT string : software executed by this platform." << std::endl;
+  std::cout << "                  default : \"" << SOFT_DEFAULT << "\"" << std::endl;
 
   exit(1);
@@ -63,23 +75,39 @@
 int _main(int argc, char *argv[])
 {
-        if ((argc < 1) or (argc > 4))
-          {
-            std::cout << "Invalid parameters number." << std::endl;
-            usage(argv[0]);
-          }
-
-#if not SOCVIEW
-	int  ncycles = 0;
-
-	if (argc >= 2)
-          ncycles = std::atoi(argv[1]);
-        else
-          ncycles = NCYCLES_DEFAULT;
+	int    ncycles = NCYCLES_DEFAULT;
+	char * config  = CONFIG_DEFAULT;
+        char * soft    = SOFT_DEFAULT;
+
+        if (argc > 1)
+          {
+            for( int n=1 ; n<argc ; n=n+2 )
+              {
+                if( (strcmp(argv[n],"-NCYCLES") == 0) && (n+1<argc) )
+                  {
+                    ncycles = atoi(argv[n+1]);
+                  }
+                else if( (strcmp(argv[n],"-CFG") == 0) && (n+1<argc) )
+                  {
+                    // strcpy(config, argv[n+1]);
+                    config = argv[n+1];
+                  }
+                else if( (strcmp(argv[n],"-SOFT") == 0) && (n+1<argc) )
+                  {
+                    // strcpy(soft, argv[n+1]);
+                    soft = argv[n+1];
+                  }
+                else
+                  {
+                    usage(argv[0]);
+                  }
+              }
+          }
 
         if (ncycles == 0)
           ncycles = -1;
-#endif
 
         uint32_t nb_proc;
+        uint32_t nb_cpu_by_cache;
+        uint32_t nb_dcache;
         uint32_t iways, isets, iwords;
         uint32_t dways, dsets, dwords;
@@ -88,5 +116,5 @@
 
         std::ifstream inFile;
-        const char * filename = (argc>=3)?argv[2]:FILE_DEFAULT;
+        const char * filename = config;
 
         inFile.open(filename);
@@ -102,4 +130,8 @@
         nb_proc         =std::atoi(str.c_str());
         if (not (inFile >> str)){std::cout << "Invalid parameters number in configuration file." << std::endl; usage(argv[0]);}
+        nb_cpu_by_cache =std::atoi(str.c_str());
+        if (not (inFile >> str)){std::cout << "Invalid parameters number in configuration file." << std::endl; usage(argv[0]);}
+        nb_dcache       =std::atoi(str.c_str());
+        if (not (inFile >> str)){std::cout << "Invalid parameters number in configuration file." << std::endl; usage(argv[0]);}
         iways           =std::atoi(str.c_str());
         if (not (inFile >> str)){std::cout << "Invalid parameters number in configuration file." << std::endl; usage(argv[0]);}
@@ -128,6 +160,6 @@
         memc_heap_size  =std::atoi(str.c_str());
 
-        if ((nb_proc<NB_PROC_MIN) or
-            (nb_proc>NB_PROC_MAX))
+        if (((nb_proc*nb_cpu_by_cache)<NB_PROC_MIN) or
+            ((nb_proc*nb_cpu_by_cache)>NB_PROC_MAX))
           {
             std::cout << "Parameters nb_proc is out of bound." << std::endl;
@@ -135,13 +167,8 @@
           }
 
-        char * soft;
-
-        if (argc >= 4)
-          soft = argv[3];
-        else
-          soft = SOFT_DEFAULT;
-
         std::cout << "  * Parameters : " << std::endl;
         std::cout << "    * nb_proc          : " << nb_proc          << std::endl;
+        std::cout << "    * nb_cpu_by_cache  : " << nb_cpu_by_cache  << std::endl;
+        std::cout << "    * nb_dcache        : " << nb_dcache        << std::endl;
         std::cout << "    * iways            : " << iways            << std::endl;
         std::cout << "    * isets            : " << isets            << std::endl;
@@ -180,5 +207,6 @@
 	maptabp.add(Segment("mc_r"     , MC_R_BASE     , MC_R_SIZE     , IntTab(2), false, true, IntTab(0)));
 	maptabp.add(Segment("mc_m"     , MC_M_BASE     , MC_M_SIZE     , IntTab(2), true));
-	// maptabp.add(Segment("ptba"     , PTD_ADDR      , TAB_SIZE      , IntTab(2), true));
+	// maptabp.add(Segment("mc_u"     , MC_U_BASE     , MC_U_SIZE     , IntTab(2), false));
+      //maptabp.add(Segment("ptba"     , PTD_ADDR      , TAB_SIZE      , IntTab(2), true));
 	maptabp.add(Segment("xicu"     , XICU_BASE     , XICU_SIZE     , IntTab(3), false));
 	maptabp.add(Segment("simhelper", SIMHELPER_BASE, SIMHELPER_SIZE, IntTab(4), false));
@@ -187,4 +215,11 @@
 
         soclib::common::MappingTable maptabc(32, IntTab(8), IntTab(8), 0x00300000);
+        // for (uint32_t i=0; i<nb_proc; ++i)
+        //   for (uint32_t j=0; j<nb_cpu_by_cache; ++j)
+        //   {
+        //     std::ostringstream str;
+        //     str << "c_proc_" << i << "_" << j;
+        //     maptabc.add(Segment(str.str().c_str(), C_PROC_BASE+(i*nb_cpu_by_cache+j)*C_PROC_SPAN, C_PROC_SIZE , IntTab(i), false, true, IntTab(i)));
+        //   }
         for (uint32_t i=0; i<nb_proc; ++i)
         {
@@ -195,8 +230,9 @@
 	maptabc.add(Segment("mc_r"    , MC_R_BASE  , MC_R_SIZE   , IntTab(nb_proc), false, false));
 	maptabc.add(Segment("mc_m"    , MC_M_BASE  , MC_M_SIZE   , IntTab(nb_proc), false, false));
+	// maptabc.add(Segment("mc_u"    , MC_U_BASE  , MC_U_SIZE   , IntTab(nb_proc), false, false));
 	maptabc.add(Segment("reset"   , RESET_BASE , RESET_SIZE  , IntTab(nb_proc), false, false));
 	maptabc.add(Segment("excep"   , EXCEP_BASE , EXCEP_SIZE  , IntTab(nb_proc), false, false));
 	maptabc.add(Segment("text"    , TEXT_BASE  , TEXT_SIZE   , IntTab(nb_proc), false, false));
-	// maptabc.add(Segment("ptba"    , PTD_ADDR   , TAB_SIZE    , IntTab(nb_proc), false, false));
+      //maptabc.add(Segment("ptba"    , PTD_ADDR   , TAB_SIZE    , IntTab(nb_proc), false, false));
 
 	std::cout << maptabc << std::endl;
@@ -204,4 +240,5 @@
 	soclib::common::MappingTable maptabx(32, IntTab(8), IntTab(8), 0x00300000);
 	maptabx.add(Segment("xram" , MC_M_BASE , MC_M_SIZE , IntTab(0), false));
+	// maptabx.add(Segment("uram" , MC_U_BASE , MC_U_SIZE , IntTab(0), false));
 	maptabx.add(Segment("reset", RESET_BASE, RESET_SIZE, IntTab(0), false));
 	maptabx.add(Segment("excep", EXCEP_BASE, EXCEP_SIZE, IntTab(0), false));
@@ -215,5 +252,5 @@
 	sc_signal<bool> signal_resetn("resetn");
    
-	sc_signal<bool> ** signal_proc_it = soclib::common::alloc_elems<sc_signal<bool> >("proc_it", nb_proc, 6);
+	sc_signal<bool> *** signal_proc_it = soclib::common::alloc_elems<sc_signal<bool> >("proc_it", nb_proc, nb_cpu_by_cache, 6);
 
 	soclib::caba::VciSignals<vci_param> * signal_vci_ini_rw_proc = soclib::common::alloc_elems<soclib::caba::VciSignals<vci_param> >("vci_ini_rw_proc", nb_proc);
@@ -236,5 +273,5 @@
 	soclib::caba::VciSignals<vci_param> signal_vci_tgt_cleanup_memc("vci_tgt_cleanup_memc");
 
-	sc_signal<bool> * signal_tty_irq = soclib::common::alloc_elems<sc_signal<bool> >("signal_tty_irq", nb_proc);
+	sc_signal<bool> ** signal_tty_irq = soclib::common::alloc_elems<sc_signal<bool> >("signal_tty_irq", nb_proc, nb_cpu_by_cache);
 
 	soclib::common::Loader loader(soft);
@@ -245,11 +282,20 @@
         for (uint32_t i=0; i<nb_proc; ++i)
           {
+            uint32_t num_cpu = i*nb_cpu_by_cache;
+
             std::ostringstream str;
-            str << "proc_" << i;
-
-            proc[i] = new soclib::caba::VciCcXCacheWrapperV4<vci_param, proc_iss > (str.str().c_str(), i, maptabp, maptabc, IntTab(i),IntTab(i),IntTab(i)
+            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)
+#if USE_OLD_XCACHE
                                                                                     ,iways, isets, iwords
                                                                                     ,dways, dsets, dwords
-                                                                                    ,wnwords, wnlines, wtimeout
+#else
+                                                                                    ,nb_cpu_by_cache   
+                                                                                    ,nb_dcache
+                                                                                    ,iways*nb_cpu_by_cache, isets, iwords
+                                                                                    ,dways*nb_cpu_by_cache, dsets, dwords
+                                                                                    ,wnwords, wnlines*nb_cpu_by_cache, wtimeout
+#endif
                                                                                     );
 
@@ -267,8 +313,8 @@
         //                                  x_init    c_init          p_tgt     c_tgt
 	soclib::caba::VciMemCacheV4<vci_param> 
-          memc("memc",maptabp,maptabc,maptabx,IntTab(0),IntTab(nb_proc),IntTab(2),IntTab(nb_proc), memc_nways, memc_nsets, memc_words, memc_heap_size);
+        memc("memc",maptabp,maptabc,maptabx,IntTab(0),IntTab(nb_proc),IntTab(2),IntTab(nb_proc), memc_nways, memc_nsets, memc_words, memc_heap_size);
 
         std::vector<std::string> tty_name;
-        for (uint32_t i=0; i<nb_proc; ++i)
+        for (uint32_t i=0; i<nb_proc*nb_cpu_by_cache; ++i)
           {
             std::ostringstream str;
@@ -308,11 +354,14 @@
           {
             proc[i]->p_clk(signal_clk);  
-            proc[i]->p_resetn(signal_resetn);  
-            proc[i]->p_irq[0](signal_proc_it[i][0]); 
-            proc[i]->p_irq[1](signal_proc_it[i][1]); 
-            proc[i]->p_irq[2](signal_proc_it[i][2]); 
-            proc[i]->p_irq[3](signal_proc_it[i][3]); 
-            proc[i]->p_irq[4](signal_proc_it[i][4]); 
-            proc[i]->p_irq[5](signal_proc_it[i][5]); 
+            proc[i]->p_resetn(signal_resetn);
+            for (uint32_t j=0; j<nb_cpu_by_cache; ++j)
+              {
+                proc[i]->p_irq[j][0](signal_proc_it[i][j][0]);
+                proc[i]->p_irq[j][1](signal_proc_it[i][j][1]);
+                proc[i]->p_irq[j][2](signal_proc_it[i][j][2]);
+                proc[i]->p_irq[j][3](signal_proc_it[i][j][3]);
+                proc[i]->p_irq[j][4](signal_proc_it[i][j][4]);
+                proc[i]->p_irq[j][5](signal_proc_it[i][j][5]);
+              }
             proc[i]->p_vci_ini_rw(signal_vci_ini_rw_proc[i]);
             proc[i]->p_vci_ini_c(signal_vci_ini_c_proc[i]);
@@ -328,5 +377,6 @@
 	tty.p_vci(signal_vci_tgt_tty);
         for (uint32_t i=0; i<nb_proc; ++i)
-          tty.p_irq[i](signal_tty_irq[i]); 
+          for (uint32_t j=0; j<nb_cpu_by_cache; ++j)
+            tty.p_irq[i*nb_cpu_by_cache+j](signal_tty_irq[i][j]); 
 
         xicu.p_clk(signal_clk);
@@ -334,8 +384,9 @@
         xicu.p_vci(signal_vci_tgt_xicu);
         for (uint32_t i=0; i<nb_proc; ++i)
-        {
-          xicu.p_hwi[i](signal_tty_irq[i]);
-          xicu.p_irq[i](signal_proc_it[i][0]); 
-        }
+          for (uint32_t j=0; j<nb_cpu_by_cache; ++j)
+          {
+            xicu.p_hwi[i*nb_cpu_by_cache+j](signal_tty_irq[i][j]);
+            xicu.p_irq[i*nb_cpu_by_cache+j](signal_proc_it[i][j][0]);
+          }
 
         simhelper.p_clk(signal_clk);
@@ -392,8 +443,10 @@
 	debug();
 #elif DEBUG_TOP
-        for (int32_t i=0; i<ncycles; ++i)
+
+        uint32_t num_cycle=0;
+        while(1)
           {
             std::cout << std::endl
-                      << std::dec << "===== [ cycle " << i << " ]======" << std::endl
+                      << std::dec << "===== [ cycle " << num_cycle << " ]======" << std::endl
                       << std::endl;
             
@@ -402,4 +455,5 @@
             // for (uint32_t i=0; i<nb_proc; ++i)
             //   proc[i]->print_trace(1);
+            num_cycle ++;
           }
 #else
@@ -418,9 +472,9 @@
           proc[i]->print_stats();
 
-        soclib::common::dealloc_elems<sc_signal<bool>                     >(signal_tty_irq         , nb_proc);
+        soclib::common::dealloc_elems<sc_signal<bool>                     >(signal_tty_irq         , nb_proc, nb_cpu_by_cache);
 	soclib::common::dealloc_elems<soclib::caba::VciSignals<vci_param> >(signal_vci_tgt_proc    , nb_proc);
 	soclib::common::dealloc_elems<soclib::caba::VciSignals<vci_param> >(signal_vci_ini_c_proc  , nb_proc);
 	soclib::common::dealloc_elems<soclib::caba::VciSignals<vci_param> >(signal_vci_ini_rw_proc , nb_proc);
-	soclib::common::dealloc_elems<sc_signal<bool>                     >(signal_proc_it         , nb_proc, 6);
+	soclib::common::dealloc_elems<sc_signal<bool>                     >(signal_proc_it         , nb_proc, nb_cpu_by_cache, 6);
 
         for (uint32_t i=0; i<nb_proc; ++i)
Index: trunk/platforms/tsarv4_dspin_generic_32/tsarv4_dspin_generic_32_top.cpp
===================================================================
--- trunk/platforms/tsarv4_dspin_generic_32/tsarv4_dspin_generic_32_top.cpp	(revision 139)
+++ trunk/platforms/tsarv4_dspin_generic_32/tsarv4_dspin_generic_32_top.cpp	(revision 140)
@@ -370,6 +370,6 @@
     // IRQ signals (one signal per proc)
 
-    sc_signal<bool>*** 	signal_proc_it =
-        alloc_elems<sc_signal<bool> >("signal_proc_it", xmax, ymax, nprocs);
+    sc_signal<bool>****	signal_proc_it =
+      alloc_elems<sc_signal<bool> >("signal_proc_it", 1,xmax, ymax, nprocs);
 
     sc_signal<bool>*    signal_irq_mtty =
@@ -548,4 +548,5 @@
                     IntTab(cluster(x,y),PROC_SRCID+p),	// SRCID_C
                     IntTab(cluster(x,y),PROC_SRCID+p),	// TGTID_C
+                    1,1,
                     4,64,16,4,64,16, 			// Icache and Dcache sizes
                     4,8,16);
@@ -743,8 +744,8 @@
                 proc[x][y][p]->p_vci_ini_c		(signal_vci_ini_c_proc[x][y][p]);
                 proc[x][y][p]->p_vci_tgt		(signal_vci_tgt_c_proc[x][y][p]);
-                proc[x][y][p]->p_irq[0]		        (signal_proc_it[x][y][p]);
+                proc[x][y][p]->p_irq[0][0]		        (signal_proc_it[0][x][y][p]);
                 for ( size_t j = 1 ; j < 6 ; j++ )
                 {
-                    proc[x][y][p]->p_irq[j]		(signal_false); 
+                    proc[x][y][p]->p_irq[0][j]		(signal_false); 
                 }
 	    }
@@ -756,5 +757,5 @@
 	    for ( size_t p = 0 ; p < nprocs ; p++ )
             {
-                xicu[x][y]->p_irq[p]			(signal_proc_it[x][y][p]);
+                xicu[x][y]->p_irq[p]			(signal_proc_it[0][x][y][p]);
             }
 
Index: trunk/platforms/tsarv4_vgmn_generic_32/tsarv4_vgmn_generic_32_top.cpp
===================================================================
--- trunk/platforms/tsarv4_vgmn_generic_32/tsarv4_vgmn_generic_32_top.cpp	(revision 139)
+++ trunk/platforms/tsarv4_vgmn_generic_32/tsarv4_vgmn_generic_32_top.cpp	(revision 140)
@@ -372,6 +372,6 @@
    
     // IRQ signals (one signal per proc)
-    sc_signal<bool>*** 	signal_proc_it =
-        alloc_elems<sc_signal<bool> >("signal_proc_it", xmax, ymax, nprocs);
+    sc_signal<bool>****	signal_proc_it =
+      alloc_elems<sc_signal<bool> >("signal_proc_it", 1,xmax, ymax, nprocs);
 
     sc_signal<bool>*	signal_irq_mtty = 
@@ -539,4 +539,5 @@
                     IntTab(cluster(x,y), PROC_SRCID+p),		// SRCID_C
                     IntTab(cluster(x,y), PROC_SRCID+p),		// TGTID_C
+                    1,1,
                     4,64,16,4,64,16 				// Icache and Dcache sizes
                     ,4,8,16
@@ -715,8 +716,8 @@
                 proc[x][y][p]->p_vci_ini_c		(signal_vci_ini_c_proc[x][y][p]);
                 proc[x][y][p]->p_vci_tgt		(signal_vci_tgt_c_proc[x][y][p]);
-                proc[x][y][p]->p_irq[0]		        (signal_proc_it[x][y][p]);
+                proc[x][y][p]->p_irq[0][0]	        (signal_proc_it[0][x][y][p]);
                 for ( size_t j = 1 ; j < 6 ; j++ )
                 {
-                    proc[x][y][p]->p_irq[j]		(signal_false); 
+                    proc[x][y][p]->p_irq[0][j]		(signal_false); 
                 }
 	    }
@@ -728,5 +729,5 @@
 	    for ( size_t p = 0 ; p < nprocs ; p++ )
             {
-                xicu[x][y]->p_irq[p]			(signal_proc_it[x][y][p]);
+                xicu[x][y]->p_irq[p]			(signal_proc_it[0][x][y][p]);
             }
 
