Index: branches/RWT/modules/vci_cc_vcache_wrapper/caba/source/include/vci_cc_vcache_wrapper.h
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper/caba/source/include/vci_cc_vcache_wrapper.h	(revision 468)
+++ branches/RWT/modules/vci_cc_vcache_wrapper/caba/source/include/vci_cc_vcache_wrapper.h	(revision 477)
@@ -115,4 +115,5 @@
         DCACHE_XTN_IT_INVAL,
         DCACHE_XTN_DC_FLUSH,
+        DCACHE_XTN_DC_FLUSH_DATA,
         DCACHE_XTN_DC_FLUSH_GO,
         DCACHE_XTN_DC_INVAL_VA,
@@ -120,4 +121,5 @@
         DCACHE_XTN_DC_INVAL_END,
         DCACHE_XTN_DC_INVAL_GO,
+        DCACHE_XTN_DC_INVAL_DATA,
         DCACHE_XTN_DT_INVAL,
         //handling dirty bit update
@@ -127,4 +129,5 @@
         DCACHE_MISS_SELECT,
         DCACHE_MISS_CLEAN,
+        DCACHE_MISS_DATA,
         DCACHE_MISS_WAIT,
         DCACHE_MISS_DATA_UPDT,
@@ -138,4 +141,5 @@
         DCACHE_CC_UPDT,
         DCACHE_CC_INVAL,
+        DCACHE_CC_INVAL_DATA,
         // handling TLB inval (after a coherence or XTN request)
         DCACHE_INVAL_TLB_SCAN,
@@ -188,4 +192,5 @@
         CC_SEND_CLEANUP_1,
         CC_SEND_CLEANUP_2,
+        CC_SEND_CLEANUP_DATA_UPDT,
         CC_SEND_MULTI_ACK,
     };
@@ -283,4 +288,14 @@
         TYPE_INS_MISS     = 0x3,
     };
+
+    //////////////////MODIFIED////////////////
+    enum content_line_cache_status_e
+    {
+        LINE_CACHE_DATA_NOT_DIRTY,
+        LINE_CACHE_DATA_DIRTY,
+        LINE_CACHE_IN_TLB,
+        LINE_CACHE_CONTAINS_PTD,
+    };
+    //////////////////////////////////////////
 
 public:
@@ -390,5 +405,5 @@
     // communication between ICACHE FSM and CC_SEND FSM
     sc_signal<bool>         r_icache_cc_send_req;           // ICACHE cc_send request
-    sc_signal<cc_send_t>    r_icache_cc_send_type;          // ICACHE cc_send request type
+    sc_signal<int>          r_icache_cc_send_type;          // ICACHE cc_send request type
     sc_signal<paddr_t>      r_icache_cc_send_nline;         // ICACHE cc_send nline
     sc_signal<size_t>       r_icache_cc_send_way;           // ICACHE cc_send way
@@ -429,4 +444,10 @@
     sc_signal<uint32_t>     r_dcache_vci_sc_data;       // SC data (command)
 
+    //RWT: local cas
+    sc_signal<bool>         r_cas_islocal;
+    sc_signal<size_t>       r_cas_local_way;
+    sc_signal<size_t>       r_cas_local_set;
+    sc_signal<size_t>       r_cas_local_word;
+
     // register used for XTN inval
     sc_signal<size_t>       r_dcache_xtn_way;		    // selected way (from dcache)
@@ -447,6 +468,9 @@
     sc_signal<size_t>       r_dcache_cc_way;		    // selected way for cc update/inval
     sc_signal<size_t>       r_dcache_cc_set;		    // selected set for cc update/inval
+    sc_signal<int>          r_dcache_cc_state;          // state of selected cache slot
     sc_signal<size_t>       r_dcache_cc_word;		    // word counter for cc update
     sc_signal<bool>         r_dcache_cc_need_write;     // activate the cache for writing
+    sc_signal<paddr_t>      r_dcache_cc_inval_addr;     // address for a cleanup transaction
+    sc_signal<uint32_t>     r_dcache_cc_inval_data_cpt;  
 
     // coherence clack handling
@@ -483,13 +507,35 @@
     // communication between DCACHE FSM and CC_SEND FSM
     sc_signal<bool>         r_dcache_cc_send_req;           // DCACHE cc_send request
-    sc_signal<cc_send_t>    r_dcache_cc_send_type;          // DCACHE cc_send request type
+    sc_signal<int>          r_dcache_cc_send_type;          // DCACHE cc_send request type
     sc_signal<paddr_t>      r_dcache_cc_send_nline;         // DCACHE cc_send nline
     sc_signal<size_t>       r_dcache_cc_send_way;           // DCACHE cc_send way
     sc_signal<size_t>       r_dcache_cc_send_updt_tab_idx;  // DCACHE cc_send update table index
-
+    
+    // special registers for ODCCP/RWT
+    sc_signal<bool>         r_dcache_cc_cleanup_updt_data;          // Register for cleanup with data (wb updt)
+    sc_signal<bool>         r_dcache_cc_cleanup_line_ncc;          // Register for cleanup with data (wb updt)
+    sc_signal<bool>         r_dcache_miss_victim_no_coherence;      // Register for victim in no coherence mode
+    sc_signal<bool>         r_dcache_line_no_coherence;             // Register for line current in no coherence mode
+    sc_signal<bool>         r_dcache_dirty_save;             
+    sc_signal<uint32_t>     r_cc_send_cpt_word;
+    sc_signal<uint32_t>     r_dcache_miss_data_cpt;
+    sc_signal<paddr_t>      r_dcache_miss_data_addr;
+    sc_signal<uint32_t>     r_dcache_xtn_flush_data_cpt;
+    sc_signal<paddr_t>      r_dcache_xtn_flush_addr_data;
+    sc_signal<int>          r_dcache_xtn_state;
+    sc_signal<paddr_t>      r_dcache_xtn_data_addr;
+    sc_signal<uint32_t>     r_dcache_xtn_data_cpt;
     // dcache directory extension
-    bool                    *r_dcache_in_tlb;               // copy exist in dtlb or itlb
-    bool                    *r_dcache_contains_ptd;         // cache line contains a PTD
-
+    ///////////////////////////MODIFIED///////////////////////////////////////////////////
+    //bool                    *r_dcache_in_tlb;           // copy exist in dtlb or itlb
+    //bool                    *r_dcache_contains_ptd;     // cache line contains a PTD
+    int                     *r_dcache_content_state;    // content state of one cache line
+    int                     *r_dcache_dirty_word;    // content state of one cache line
+    //////////////////////////////////////////////////////////////////////////////////////
+
+    //RWT
+    sc_signal<bool>         r_dcache_read_state;
+   
+     ///////////////////////////////////
     // Physical address extension for data access
     sc_signal<uint32_t>     r_dcache_paddr_ext;             // CP2 register (if vci_address > 32)
@@ -513,4 +559,10 @@
     GenericFifo<uint32_t>   r_vci_rsp_fifo_icache;	        // response FIFO to ICACHE FSM
     GenericFifo<uint32_t>   r_vci_rsp_fifo_dcache;	        // response FIFO to DCACHE FSM
+    
+
+    //RWT
+    GenericFifo<bool>       r_vci_rsp_fifo_rpktid;
+
+    GenericFifo<uint32_t>   r_cc_send_data_fifo;   
 
     ///////////////////////////////////
@@ -534,5 +586,5 @@
     // communication between CC_RECEIVE FSM and ICACHE FSM
     sc_signal<bool>         r_cc_receive_icache_req;        // cc_receive to icache request
-    sc_signal<cc_receive_t> r_cc_receive_icache_type;       // cc_receive type of request
+    sc_signal<int>          r_cc_receive_icache_type;       // cc_receive type of request
     sc_signal<size_t>       r_cc_receive_icache_way;        // cc_receive to icache way
     sc_signal<size_t>       r_cc_receive_icache_set;        // cc_receive to icache set
@@ -542,5 +594,5 @@
     // communication between CC_RECEIVE FSM and DCACHE FSM
     sc_signal<bool>         r_cc_receive_dcache_req;        // cc_receive to dcache request
-    sc_signal<cc_receive_t> r_cc_receive_dcache_type;       // cc_receive type of request
+    sc_signal<int>          r_cc_receive_dcache_type;       // cc_receive type of request
     sc_signal<size_t>       r_cc_receive_dcache_way;        // cc_receive to dcache way
     sc_signal<size_t>       r_cc_receive_dcache_set;        // cc_receive to dcache set
@@ -593,4 +645,7 @@
     uint32_t m_cpt_data_read;               // total number of read data
     uint32_t m_cpt_data_write;              // total number of write data
+    uint32_t m_cpt_data_write_back;
+    uint32_t m_cpt_data_cleanup;
+    uint32_t m_cpt_data_sc;
     uint32_t m_cpt_data_miss;               // number of read miss
     uint32_t m_cpt_ins_miss;                // number of instruction miss
@@ -608,4 +663,6 @@
     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_dunc_transaction;         // number of VCI uncached read transactions
+    uint32_t m_cpt_ll_transaction;         // number of VCI uncached read transactions
     uint32_t m_cpt_write_transaction;       // number of VCI write transactions
     uint32_t m_cpt_icache_unc_transaction;
@@ -673,4 +730,6 @@
     uint32_t m_cpt_cc_cleanup_ins;              // number of coherence cleanup packets
     uint32_t m_cpt_cc_cleanup_data;             // number of coherence cleanup packets
+    uint32_t m_cpt_cleanup_data_not_dirty;
+    uint32_t m_cpt_cleanup_data_dirty_word;
 
     uint32_t m_cpt_icleanup_transaction;        // number of instruction cleanup transactions
Index: branches/RWT/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp	(revision 468)
+++ branches/RWT/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp	(revision 477)
@@ -35,4 +35,5 @@
 #define DEBUG_ICACHE		1
 #define DEBUG_CMD   		0
+#define INSTRUMENTATION     1
 
 namespace soclib {
@@ -87,4 +88,5 @@
         "DCACHE_XTN_IT_INVAL",
         "DCACHE_XTN_DC_FLUSH",
+        "DCACHE_XTN_DC_FLUSH_DATA",
         "DCACHE_XTN_DC_FLUSH_GO",
         "DCACHE_XTN_DC_INVAL_VA",
@@ -92,4 +94,5 @@
         "DCACHE_XTN_DC_INVAL_END",
         "DCACHE_XTN_DC_INVAL_GO",
+        "DCACHE_XTN_DC_INVAL_DATA",
         "DCACHE_XTN_DT_INVAL",
 
@@ -99,4 +102,5 @@
         "DCACHE_MISS_SELECT",
         "DCACHE_MISS_CLEAN",
+        "DCACHE_MISS_DATA",
         "DCACHE_MISS_WAIT",
         "DCACHE_MISS_DATA_UPDT",
@@ -110,4 +114,5 @@
         "DCACHE_CC_UPDT",
         "DCACHE_CC_INVAL",
+        "DCACHE_CC_INVAL_DATA",
 
         "DCACHE_INVAL_TLB_SCAN",
@@ -174,4 +179,5 @@
         "CC_SEND_CLEANUP_1",
         "CC_SEND_CLEANUP_2",
+        "CC_SEND_CLEANUP_DATA_UPDT",
         "CC_SEND_MULTI_ACK",
     };
@@ -367,4 +373,6 @@
       r_vci_rsp_fifo_icache("r_vci_rsp_fifo_icache", 2),	// 2 words depth
       r_vci_rsp_fifo_dcache("r_vci_rsp_fifo_dcache", 2),	// 2 words depth
+      r_vci_rsp_fifo_rpktid("r_vci_rsp_fifo_rpktid", 2),    // 2 words depth
+      r_cc_send_data_fifo("r_cc_send_data_fifo", 2),
 
       r_cc_send_fsm("r_cc_send_fsm"),
@@ -424,6 +432,11 @@
     r_mmu_release = (uint32_t)(1 << 16) | 0x1;
 
-    r_dcache_in_tlb       = new bool[dcache_ways*dcache_sets];
-    r_dcache_contains_ptd = new bool[dcache_ways*dcache_sets];
+    ////////////////////MODIFIED///////////////////////////////
+    //r_dcache_in_tlb        = new bool[dcache_ways*dcache_sets];
+    //r_dcache_contains_ptd  = new bool[dcache_ways*dcache_sets];
+    r_dcache_content_state = new int [dcache_ways*dcache_sets];
+    r_dcache_dirty_word    = new int [dcache_ways*dcache_sets*dcache_words];
+    ///////////////////////////////////////////////////////////
+
 
     SC_METHOD(transition);
@@ -450,6 +463,10 @@
 /////////////////////////////////////
 {
-    delete [] r_dcache_in_tlb;
-    delete [] r_dcache_contains_ptd;
+    ////////////MODIFIED/////////////
+    //delete [] r_dcache_in_tlb;
+    //delete [] r_dcache_contains_ptd;
+    delete [] r_dcache_content_state;
+    delete [] r_dcache_dirty_word;
+    /////////////////////////////////
 }
 
@@ -472,5 +489,4 @@
     // b4 : dtlb trace
     // b5 : itlb trace
-
     std::cout << std::dec << "PROC " << name() << std::endl;
 
@@ -479,4 +495,6 @@
     std::cout << "  " << m_dreq << std::endl;
     std::cout << "  " << m_drsp << std::endl;
+
+    /**/std::cout << r_iss << std::endl;
 
     std::cout << "  " << icache_fsm_state_str[r_icache_fsm.read()]
@@ -562,5 +580,5 @@
 }
 
-/*
+
 ////////////////////////
 tmpl(void)::print_stats()
@@ -569,43 +587,55 @@
     float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
     std::cout << name() << std::endl
-        << "- CPI                    = " << (float)m_cpt_total_cycles/run_cycles << std::endl
-        << "- READ RATE              = " << (float)m_cpt_read/run_cycles << std::endl
-        << "- WRITE RATE             = " << (float)m_cpt_write/run_cycles << std::endl
-        << "- IMISS_RATE             = " << (float)m_cpt_ins_miss/m_cpt_ins_read << std::endl
-        << "- DMISS RATE             = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl
-        << "- INS MISS COST          = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl
-        << "- DATA MISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl
-        << "- WRITE COST             = " << (float)m_cost_write_frz/m_cpt_write << std::endl
-        << "- UNC COST               = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl
-        << "- UNCACHED READ RATE     = " << (float)m_cpt_unc_read/m_cpt_read << std::endl
-        << "- CACHED WRITE RATE      = " << (float)m_cpt_write_cached/m_cpt_write << std::endl
-        << "- INS TLB MISS RATE      = " << (float)m_cpt_ins_tlb_miss/m_cpt_ins_tlb_read << std::endl
-        << "- DATA TLB MISS RATE     = " << (float)m_cpt_data_tlb_miss/m_cpt_data_tlb_read << std::endl
-        << "- ITLB MISS COST         = " << (float)m_cost_ins_tlb_miss_frz/m_cpt_ins_tlb_miss << std::endl
-        << "- DTLB MISS COST         = " << (float)m_cost_data_tlb_miss_frz/m_cpt_data_tlb_miss << std::endl
-        << "- ITLB UPDATE ACC COST   = " << (float)m_cost_ins_tlb_update_acc_frz/m_cpt_ins_tlb_update_acc << std::endl
-        << "- DTLB UPDATE ACC COST   = " << (float)m_cost_data_tlb_update_acc_frz/m_cpt_data_tlb_update_acc << std::endl
-        << "- DTLB UPDATE DIRTY COST = " << (float)m_cost_data_tlb_update_dirty_frz/m_cpt_data_tlb_update_dirty << std::endl
-        << "- ITLB HIT IN DCACHE RATE= " << (float)m_cpt_ins_tlb_hit_dcache/m_cpt_ins_tlb_miss << std::endl
-        << "- DTLB HIT IN DCACHE RATE= " << (float)m_cpt_data_tlb_hit_dcache/m_cpt_data_tlb_miss << std::endl
-        << "- DCACHE FROZEN BY ITLB  = " << (float)m_cost_ins_tlb_occup_cache_frz/m_cpt_dcache_frz_cycles << std::endl
-        << "- DCACHE FOR TLB %       = " << (float)m_cpt_tlb_occup_dcache/(m_dcache_ways*m_dcache_sets) << std::endl
-        << "- NB CC BROADCAST        = " << m_cpt_cc_broadcast << std::endl
-        << "- NB CC UPDATE DATA      = " << m_cpt_cc_update_data << std::endl
-        << "- NB CC INVAL DATA       = " << m_cpt_cc_inval_data << std::endl
-        << "- NB CC INVAL INS        = " << m_cpt_cc_inval_ins << std::endl
-        << "- CC BROADCAST COST      = " << (float)m_cost_broadcast_frz/m_cpt_cc_broadcast << std::endl
-        << "- CC UPDATE DATA COST    = " << (float)m_cost_updt_data_frz/m_cpt_cc_update_data << std::endl
-        << "- CC INVAL DATA COST     = " << (float)m_cost_inval_data_frz/m_cpt_cc_inval_data << std::endl
-        << "- CC INVAL INS COST      = " << (float)m_cost_inval_ins_frz/m_cpt_cc_inval_ins << std::endl
-        << "- NB CC CLEANUP DATA     = " << m_cpt_cc_cleanup_data << std::endl
-        << "- NB CC CLEANUP INS      = " << m_cpt_cc_cleanup_ins << std::endl
-        << "- IMISS TRANSACTION      = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl
-        << "- DMISS TRANSACTION      = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl
-        << "- UNC TRANSACTION        = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl
-        << "- WRITE TRANSACTION      = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl
-        << "- WRITE LENGTH           = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl
-        << "- ITLB MISS TRANSACTION  = " << (float)m_cost_itlbmiss_transaction/m_cpt_itlbmiss_transaction << std::endl
-        << "- DTLB MISS TRANSACTION  = " << (float)m_cost_dtlbmiss_transaction/m_cpt_dtlbmiss_transaction << std::endl;
+        << "- CPI                     = " << std::dec <<(float)m_cpt_total_cycles/run_cycles << std::endl
+        << "- READ RATE               = " << (float)m_cpt_data_read/run_cycles << std::endl
+        << "- WRITE RATE              = " << (float)m_cpt_data_write/run_cycles << std::endl
+        << "- IMISS_RATE              = " << (float)m_cpt_ins_miss/m_cpt_ins_read << std::endl
+        << "- DMISS RATE              = " << (float)m_cpt_data_miss/(m_cpt_data_read-m_cpt_unc_read) << std::endl
+        << "- INS MISS COST           = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl
+        << "- DATA MISS COST          = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl
+        << "- WRITE COST              = " << (float)m_cost_write_frz/m_cpt_data_write << std::endl
+        << "- UNC COST                = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl
+        << "- UNCACHED READ RATE      = " << (float)m_cpt_unc_read/m_cpt_data_read << std::endl
+        << "- CACHED WRITE RATE       = " << (float)m_cpt_write_cached/m_cpt_data_write << std::endl
+        << "- INS TLB MISS RATE       = " << (float)m_cpt_ins_tlb_miss/m_cpt_ins_tlb_read << std::endl
+        << "- DATA TLB MISS RATE      = " << (float)m_cpt_data_tlb_miss/m_cpt_data_tlb_read << std::endl
+        << "- ITLB MISS COST          = " << (float)m_cost_ins_tlb_miss_frz/m_cpt_ins_tlb_miss << std::endl
+        << "- DTLB MISS COST          = " << (float)m_cost_data_tlb_miss_frz/m_cpt_data_tlb_miss << std::endl
+        << "- ITLB UPDATE ACC COST    = " << (float)m_cost_ins_tlb_update_acc_frz/m_cpt_ins_tlb_update_acc << std::endl
+        << "- DTLB UPDATE ACC COST    = " << (float)m_cost_data_tlb_update_acc_frz/m_cpt_data_tlb_update_acc << std::endl
+        << "- DTLB UPDATE DIRTY COST  = " << (float)m_cost_data_tlb_update_dirty_frz/m_cpt_data_tlb_update_dirty << std::endl
+        << "- ITLB HIT IN DCACHE RATE = " << (float)m_cpt_ins_tlb_hit_dcache/m_cpt_ins_tlb_miss << std::endl
+        << "- DTLB HIT IN DCACHE RATE = " << (float)m_cpt_data_tlb_hit_dcache/m_cpt_data_tlb_miss << std::endl
+        //<< "- DCACHE FROZEN BY ITLB   = " << (float)m_cost_ins_tlb_occup_cache_frz/m_cpt_dcache_frz_cycles << std::endl
+        << "- DCACHE FOR TLB %        = " << (float)m_cpt_tlb_occup_dcache/(m_dcache_ways*m_dcache_sets) << std::endl
+        << "- NB CC BROADCAST         = " << m_cpt_cc_broadcast << std::endl
+        << "- NB CC UPDATE DATA       = " << m_cpt_cc_update_dcache << std::endl
+        << "- NB CC INVAL DATA        = " << m_cpt_cc_inval_dcache << std::endl
+        << "- NB CC INVAL INS         = " << m_cpt_cc_inval_icache << std::endl
+        << "- CC BROADCAST COST       = " << (float)m_cost_broadcast_frz/m_cpt_cc_broadcast << std::endl
+        << "- CC UPDATE DATA COST     = " << (float)m_cost_updt_data_frz/m_cpt_cc_update_dcache << std::endl
+        << "- CC INVAL DATA COST      = " << (float)m_cost_inval_data_frz/m_cpt_cc_inval_dcache << std::endl
+        << "- CC INVAL INS COST       = " << (float)m_cost_inval_ins_frz/m_cpt_cc_inval_icache << std::endl
+        << "- NB CC CLEANUP DATA      = " << m_cpt_cc_cleanup_data << std::endl
+        << "- NB CC CLEANUP INS       = " << m_cpt_cc_cleanup_ins << std::endl
+        << "- IMISS TRANSACTION       = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl
+        << "- DMISS TRANSACTION       = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl
+        << "- UNC TRANSACTION         = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl
+        << "- WRITE TRANSACTION       = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl
+        << "- NB WRITE TRANSACTION    = " << m_cpt_write_transaction << std::endl
+        << "- NB WRITE WORDS VCI      = " << m_length_write_transaction << std::endl
+        << "- NB WRITE PROC           = " << m_cpt_data_write << std::endl
+        << "- NB WRITE BACK           = " << m_cpt_data_write_back << std::endl
+        << "- NB WRITE BACK COHERENCE = " << m_cpt_data_cleanup << std::endl
+        << "- NB DATA SC              = " << m_cpt_data_sc << std::endl
+        << "- WRITE LENGTH            = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl
+        << "- ITLB MISS TRANSACTION   = " << (float)m_cost_itlbmiss_transaction/m_cpt_itlbmiss_transaction << std::endl
+        << "- DTLB MISS TRANSACTION   = " << (float)m_cost_dtlbmiss_transaction/m_cpt_dtlbmiss_transaction << std::endl
+
+        << "- DMISS TRANSACTION       = " << m_cpt_dmiss_transaction << std::endl
+        << "- DUNC TRANSACTION        = " << m_cpt_dunc_transaction << std::endl
+        << "- LL TRANSACTION          = " << m_cpt_ll_transaction << std::endl
+        << "- CLEANUP DATA NOT DIRTY  = " << m_cpt_cleanup_data_not_dirty << std::endl
+        << "- CLEANUP DATA DIRTY WORD = " << m_cpt_cleanup_data_dirty_word << std::endl;
 }
 
@@ -624,9 +654,9 @@
 
     m_cpt_frz_cycles        = 0;
-    m_cpt_dcache_frz_cycles = 0;
+//    m_cpt_dcache_frz_cycles = 0;
     m_cpt_total_cycles      = 0;
 
-    m_cpt_read         = 0;
-    m_cpt_write        = 0;
+//    m_cpt_read         = 0;
+//    m_cpt_write        = 0;
     m_cpt_data_miss    = 0;
     m_cpt_ins_miss     = 0;
@@ -692,7 +722,7 @@
     m_cost_dtlb_sc_dirty_transaction = 0;
 
-    m_cpt_cc_update_data = 0;
-    m_cpt_cc_inval_ins   = 0;
-    m_cpt_cc_inval_data  = 0;
+//    m_cpt_cc_update_data = 0;
+//    m_cpt_cc_inval_ins   = 0;
+//    m_cpt_cc_inval_data  = 0;
     m_cpt_cc_broadcast   = 0;
 
@@ -704,7 +734,11 @@
     m_cpt_cc_cleanup_data = 0;
     m_cpt_cc_cleanup_ins  = 0;
+
+    m_cpt_cleanup_data_not_dirty  = 0;
+    m_cpt_cleanup_data_dirty_word = 0;
+
 }
 
-*/
+
 
 /////////////////////////
@@ -734,6 +768,9 @@
         for (size_t i=0 ; i< m_dcache_ways*m_dcache_sets ; i++)
         {
-            r_dcache_in_tlb[i]       = false;
-            r_dcache_contains_ptd[i] = false;
+            // MODIFIED
+            //r_dcache_in_tlb[i]        = false;
+            //r_dcache_contains_ptd[i]  = false;
+            r_dcache_content_state[i] = LINE_CACHE_DATA_NOT_DIRTY;
+            r_dcache_dirty_word[i] = 0;
         }
 
@@ -741,4 +778,5 @@
         r_vci_rsp_fifo_icache.init();
         r_vci_rsp_fifo_dcache.init();
+        r_cc_send_data_fifo.init();
 
         // ICACHE & DCACHE activated
@@ -805,4 +843,13 @@
         m_debug_previous_d_hit     = false;
         m_debug_activated	       = false;
+
+        // SPECIAL REGISTERS ODCCP
+        r_dcache_cc_cleanup_updt_data = false;
+        r_dcache_cc_cleanup_line_ncc  = false;
+        r_dcache_miss_victim_no_coherence = false;
+        r_dcache_line_no_coherence = false;
+        r_cc_send_cpt_word = 0;
+        r_dcache_miss_data_cpt = 0;
+        r_dcache_miss_data_addr = 0;
 
         // activity counters
@@ -821,4 +868,9 @@
 
         m_cpt_data_miss         = 0;
+        m_cpt_data_write        = 0;
+        m_cpt_data_sc           = 0;
+        m_cpt_data_write_back   = 0;
+        m_cpt_data_cleanup      = 0;
+        m_cpt_cleanup_data_not_dirty = 0; 
         m_cpt_ins_miss          = 0;
         m_cpt_unc_read          = 0;
@@ -879,4 +931,7 @@
    	    m_cpt_cc_cleanup_data = 0;
    	    m_cpt_cc_cleanup_ins  = 0;
+
+        m_cpt_cleanup_data_not_dirty  = 0;
+        m_cpt_cleanup_data_dirty_word = 0;
 
         m_cpt_itlbmiss_transaction      = 0;
@@ -926,4 +981,12 @@
     bool       vci_rsp_fifo_dcache_put   = false;
     uint32_t   vci_rsp_fifo_dcache_data  = 0;
+    bool       vci_rsp_fifo_rpktid_get   = false;
+    bool       vci_rsp_fifo_rpktid_put   = false;
+    bool       vci_rsp_fifo_rpktid       = false;
+
+    // FIFO for cleanup data updt
+    bool       cleanup_data_updt_fifo_dcache_get   = false;
+    bool       cleanup_data_updt_fifo_dcache_put   = false;
+    uint32_t   cleanup_data_updt_fifo_dcache_data  = 0;
 
     // updt fifo
@@ -935,10 +998,10 @@
 
 #ifdef INSTRUMENTATION
-    m_cpt_fsm_dcache  [r_dcache_fsm.read() ] ++;
-    m_cpt_fsm_icache  [r_icache_fsm.read() ] ++;
-    m_cpt_fsm_cmd     [r_vci_cmd_fsm.read()] ++;
-    m_cpt_fsm_rsp     [r_vci_rsp_fsm.read()] ++;
-    m_cpt_fsm_tgt     [r_tgt_fsm.read()    ] ++;
-    m_cpt_fsm_cleanup [r_cleanup_cmd_fsm.read()] ++;
+    m_cpt_fsm_dcache     [r_dcache_fsm.read()    ] ++;
+    m_cpt_fsm_icache     [r_icache_fsm.read()    ] ++;
+    m_cpt_fsm_cmd        [r_vci_cmd_fsm.read()   ] ++;
+    m_cpt_fsm_rsp        [r_vci_rsp_fsm.read()   ] ++;
+    m_cpt_fsm_cc_send    [r_cc_send_fsm.read()   ] ++;
+    m_cpt_fsm_cc_receive [r_cc_receive_fsm.read()] ++;
 #endif
 
@@ -1069,5 +1132,5 @@
                 else
                 {
-			        r_icache_vci_paddr = (paddr_t)r_mmu_word_hi.read() << 32 |
+			        r_icache_vci_paddr = (uint64_t)r_mmu_word_hi.read() << 32 |
 				                         (paddr_t)r_mmu_word_lo.read();
 		        }
@@ -1106,5 +1169,5 @@
 
 #ifdef INSTRUMENTATION
-m_cpt_itlb_read++;
+m_cpt_ins_tlb_read++;
 #endif
                 tlb_hit = r_itlb.translate( m_ireq.addr,
@@ -1181,5 +1244,5 @@
 
 #ifdef INSTRUMENTATION
-m_cpt_itlb_miss++;
+m_cpt_ins_tlb_miss++;
 #endif
                     r_icache_fsm          = ICACHE_TLB_WAIT;
@@ -1199,5 +1262,5 @@
 
 #ifdef INSTRUMENTATION
-m_cpt_icache_miss++;
+m_cpt_ins_miss++;
 #endif
                     // we request a VCI transaction
@@ -1340,5 +1403,5 @@
                                &state );
 
-            if ( state == CACHE_SLOT_STATE_VALID )    // inval required
+            if ( state == CACHE_SLOT_STATE_VALID_CC )    // inval required
             {
                 // request cleanup
@@ -1421,5 +1484,5 @@
 
 #ifdef INSTRUMENTATION
-m_cpt_itlb_read++;
+m_cpt_ins_tlb_read++;
 #endif
             hit = r_itlb.translate(r_dcache_save_wdata.read(),
@@ -1441,5 +1504,5 @@
 
 #ifdef INSTRUMENTATION
-m_cpt_itlb_miss++;
+m_cpt_ins_tlb_miss++;
 #endif
             r_icache_tlb_miss_req = true;
@@ -1468,5 +1531,5 @@
                           &word);
 
-        if ( state == CACHE_SLOT_STATE_VALID )	// inval to be done
+        if ( state == CACHE_SLOT_STATE_VALID_CC )	// inval to be done
         {
             r_icache_miss_way = way;
@@ -1751,5 +1814,5 @@
                                     r_icache_miss_way.read(),
                                     r_icache_miss_set.read(),
-                                    CACHE_SLOT_STATE_VALID );
+                                    CACHE_SLOT_STATE_VALID_CC );
 #if DEBUG_ICACHE
 if ( m_debug_activated )
@@ -1924,5 +1987,5 @@
         r_icache_cc_set = set;
 
-        if ( state == CACHE_SLOT_STATE_VALID)            // hit
+        if ( state == CACHE_SLOT_STATE_VALID_CC)            // hit
         {
             // need to update the cache state
@@ -2136,4 +2199,5 @@
     m_drsp.error = false;
     m_drsp.rdata = 0;
+    //if(m_cpt_total_cycles % 1000000 == 0 ) r_dcache.printTrace();
 
     switch ( r_dcache_fsm.read() )
@@ -2191,4 +2255,5 @@
         bool        wbuf_request       = false;     // request WBUF write in P1 stage
 
+
         // physical address computation : systematic DTLB access if activated)
         if ( m_dreq.valid )
@@ -2203,5 +2268,5 @@
                                             &tlb_set );
 #ifdef INSTRUMENTATION
-m_cpt_dtlb_read++;
+m_cpt_data_tlb_read++;
 #endif
             }
@@ -2211,5 +2276,5 @@
                 // we take into account the paddr extension
                 if (vci_param::N > 32) 
-                    paddr = paddr | ((paddr_t)(r_dcache_paddr_ext.read()) << 32);
+                    paddr = paddr | ((uint64_t)(r_dcache_paddr_ext.read()) << 32);
             }
         } // end physical address computation
@@ -2268,6 +2333,8 @@
             size_t way = r_dcache_save_cache_way.read();
             size_t set = r_dcache_save_cache_set.read();
-
-            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
+            // MODIFIED
+            //if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
+            //{
+            if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
             {
                 tlb_inval_required       = true;
@@ -2275,11 +2342,18 @@
 	            r_dcache_tlb_inval_line  = r_dcache_save_paddr.read()>>
                                            (uint32_log2(m_dcache_words<<2));
-	            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
-            }
-            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
+                // MODIFIED RWT: DIRTY
+	            //r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
+            }
+            // MODIFIED
+            //else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
+            //{
+            else if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
             {
                 r_itlb.reset();
                 r_dtlb.reset();
-	            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+                // MODIFIED
+	            //r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
             }
 
@@ -2312,7 +2386,7 @@
                                          r_dcache_save_wdata.read(),
                                          r_dcache_save_cacheable.read() );
-#ifdef INSTRUMENTATION
+/*#ifdef INSTRUMENTATION
 m_cpt_wbuf_write++;
-#endif
+#endif*/
                 if ( not wok ) // miss if write buffer full
                 {
@@ -2526,5 +2600,5 @@
                         else
                         {
-                            r_dcache_save_paddr = (paddr_t)r_mmu_word_hi.read() << 32 |
+                            r_dcache_save_paddr = (uint64_t)r_mmu_word_hi.read() << 32 |
                                                   (paddr_t)r_mmu_word_lo.read();
                         }
@@ -2623,5 +2697,4 @@
                         if ( not (r_mmu_mode.read() & DATA_CACHE_MASK) ) cacheable = false;
                         else cacheable = tlb_flags.c;
-
                         // access rights checking
                         if ( not tlb_flags.u and (m_dreq.mode == iss_t::MODE_USER))
@@ -2693,6 +2766,8 @@
                             {
 #ifdef INSTRUMENTATION
-m_cpt_dcache_miss++;
-#endif
+m_cpt_data_miss++;
+#endif
+                                /*ODCCP*/
+                                //std::cout << "\t\t\t\t\tCACHE MISS NEED READ for : " << name() << std::endl;
                                 // request a VCI DMISS transaction
                                 r_dcache_vci_paddr    = paddr;
@@ -2723,4 +2798,12 @@
 m_cpt_data_read++;
 #endif
+                                /*if ((tlb_flags.s == 0) and (r_mmu_mode.read() & DATA_TLB_MASK) and (cache_state == CACHE_SLOT_STATE_VALID_CC))
+                                {
+                                    //ODCCP
+                                    std::cout << "READ NO COHERENCE on " << name() << " | paddr = " << std::hex << paddr << std::dec << " | way = " << cache_way << " | set = " << cache_set << " | at cycle : "<< m_cpt_total_cycles << std::endl;
+                                    r_dcache.write_dir(cache_way,
+                                                       cache_set,
+                                                       CACHE_SLOT_STATE_VALID_NCC);
+                                }*/
                                 // returns data to processor
                                 m_drsp.valid   = true;
@@ -2765,4 +2848,6 @@
                         r_dcache_ll_rsp_count = 0;
                         r_dcache_fsm          = DCACHE_LL_WAIT;
+                        /*ODCCP*/
+                        //std::cout << "LL on " << name() << " | paddr = " << std::hex << paddr << std::dec << " | at cycle : " << m_cpt_total_cycles << std::endl;
 
                     }// end LL
@@ -2806,8 +2891,24 @@
                             // response to processor
                             m_drsp.valid        = true;
-
                             // activating P1 stage
-                            wbuf_request = true;
-                            updt_request = (cache_state == CACHE_SLOT_STATE_VALID);
+                            if( (cache_state != CACHE_SLOT_STATE_ZOMBI )&&(cache_state != CACHE_SLOT_STATE_EMPTY )&&(cacheable) )
+                            {
+                                wbuf_request = (cache_state == CACHE_SLOT_STATE_VALID_CC); //write to L2 only if CC
+                                updt_request = true;
+                                if (cache_state == CACHE_SLOT_STATE_VALID_NCC) 
+                                {
+                                    if (r_dcache_content_state[cache_way*m_dcache_sets+cache_set] == LINE_CACHE_DATA_NOT_DIRTY)
+                                    {
+                                        r_dcache_content_state[cache_way*m_dcache_sets+cache_set] = LINE_CACHE_DATA_DIRTY;
+                                    }
+                                    r_dcache_dirty_word[(cache_way*m_dcache_sets +cache_set)*m_dcache_words+cache_word] = 1;//dirty bit with word granularity (only for stats)
+                                    m_cpt_data_write_back ++;
+                                }
+                            }
+                            else
+                            {
+                               wbuf_request = true;
+                               updt_request = false;
+                            }
                         }
                     } // end WRITE
@@ -2978,5 +3079,8 @@
 m_cpt_dcache_dir_read++;
 #endif
-        if ( cache_state == CACHE_SLOT_STATE_VALID )   // hit in dcache
+        /*ODCCP*/
+//        assert((cache_state != CACHE_SLOT_STATE_VALID_NCC) and "DCACHE_TLB_PTE1_GET : IMPOSSIBLE NCC HERE");
+//        if ( cache_state == CACHE_SLOT_STATE_VALID_CC )   // hit in dcache
+        if (( cache_state == CACHE_SLOT_STATE_VALID_NCC ) or ( cache_state == CACHE_SLOT_STATE_VALID_CC ))
         {
             if ( not (entry & PTE_V_MASK) )	// unmapped
@@ -3015,5 +3119,7 @@
             {
                 // mark the cache line ac containing a PTD
-                r_dcache_contains_ptd[m_dcache_sets*way+set] = true;
+                //MODIFIED
+                //r_dcache_contains_ptd[m_dcache_sets*way+set] = true;
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_CONTAINS_PTD;
 
                 // register bypass
@@ -3050,5 +3156,7 @@
             else			//  PTE1 :  we must update the TLB
             {
-                r_dcache_in_tlb[m_icache_sets*way+set] = true;
+                // MODIFIED
+                //r_dcache_in_tlb[m_icache_sets*way+set] = true;
+                r_dcache_content_state[m_icache_sets*way+set] = LINE_CACHE_IN_TLB;
                 r_dcache_tlb_pte_flags  = entry;
                 r_dcache_tlb_cache_way  = way;
@@ -3108,5 +3216,5 @@
                            &set );
 #ifdef INSTRUMENTATION
-m_cpt_itlb_read++;
+m_cpt_ins_tlb_read++;
 #endif
         }
@@ -3118,5 +3226,5 @@
                            &set );
 #ifdef INSTRUMENTATION
-m_cpt_dtlb_read++;
+m_cpt_data_tlb_read++;
 #endif
         }
@@ -3194,5 +3302,5 @@
                               nline );
 #ifdef INSTRUMENTATION
-m_cpt_itlb_write++;
+m_cpt_ins_tlb_update_acc++;
 #endif
 
@@ -3218,5 +3326,5 @@
                               nline );
 #ifdef INSTRUMENTATION
-m_cpt_dtlb_write++;
+m_cpt_data_tlb_update_acc++;
 #endif
 
@@ -3268,10 +3376,10 @@
         }
 
-        uint32_t 	pte_flags;
-        uint32_t 	pte_ppn;
-        size_t   	way;
-        size_t   	set;
-        size_t		word;
-        int         cache_state;
+        uint32_t 	pte_flags     = 0;
+        uint32_t 	pte_ppn       = 0;
+        size_t   	way           = 0;
+        size_t   	set           = 0;
+        size_t		word          = 0;
+        int         cache_state   = 0;
 
         r_dcache.read( r_dcache_tlb_paddr.read(),
@@ -3286,5 +3394,8 @@
 m_cpt_dcache_dir_read++;
 #endif
-        if ( cache_state == CACHE_SLOT_STATE_VALID )   // hit in dcache
+        /*ODCCP*/
+//        assert((cache_state != CACHE_SLOT_STATE_VALID_NCC) and "DCACHE_TLB_PTE2_GET : IMPOSSIBLE NCC HERE");
+//        if (cache_state == CACHE_SLOT_STATE_VALID_CC)    // hit in dcache
+        if ((cache_state == CACHE_SLOT_STATE_VALID_CC) or (cache_state == CACHE_SLOT_STATE_VALID_NCC))
         {
             if ( not (pte_flags & PTE_V_MASK) )	// unmapped
@@ -3318,5 +3429,7 @@
             else				// mapped : we must update the TLB
             {
-                r_dcache_in_tlb[m_dcache_sets*way+set] = true;
+                // MODIFIED
+                //r_dcache_in_tlb[m_dcache_sets*way+set] = true;
+                r_dcache_content_state[m_dcache_sets*way+set] = LINE_CACHE_IN_TLB;
                 r_dcache_tlb_pte_flags  = pte_flags;
                 r_dcache_tlb_pte_ppn    = pte_ppn;
@@ -3383,5 +3496,5 @@
                            &set );
 #ifdef INSTRUMENTATION
-m_cpt_itlb_read++;
+m_cpt_ins_tlb_read++;
 #endif
         }
@@ -3393,5 +3506,5 @@
                            &set );
 #ifdef INSTRUMENTATION
-m_cpt_dtlb_read++;
+m_cpt_data_tlb_read++;
 #endif
         }
@@ -3435,4 +3548,18 @@
         // As long as this computation is not done, all access are local.
 
+        int  state;
+        size_t way;
+        size_t set;
+        size_t word;
+        r_dcache.read_dir(r_dcache_tlb_paddr.read(),
+                          &state,
+                          &way,
+                          &set,
+                          &word);
+        r_cas_islocal = (state == CACHE_SLOT_STATE_VALID_NCC);//do not check L2 if NCC: the CAS is necessarily a success
+        r_cas_local_way = way;
+        r_cas_local_set = set;
+        r_cas_local_word = word;
+
         if ( local )						// local access
         {
@@ -3470,5 +3597,5 @@
                               nline );
 #ifdef INSTRUMENTATION
-m_cpt_itlb_write++;
+m_cpt_ins_tlb_update_acc++;
 #endif
 
@@ -3494,5 +3621,5 @@
                               nline );
 #ifdef INSTRUMENTATION
-m_cpt_dtlb_write++;
+m_cpt_data_tlb_update_acc++;
 #endif
 
@@ -3528,4 +3655,8 @@
     case DCACHE_TLB_LR_UPDT:        // request a CAS transaction to update L/R bit
     {
+        uint32_t way  = r_cas_local_way.read();
+        uint32_t set  = r_cas_local_set.read();
+        uint32_t word = r_cas_local_word.read();
+        paddr_t nline = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);
 #if DEBUG_DCACHE
 if ( m_debug_activated )
@@ -3535,14 +3666,54 @@
 }
 #endif
-        // r_dcache_vci_cas_old & r_dcache_vci_cas_new registers are already set
-        r_dcache_vci_paddr = r_dcache_tlb_paddr.read();
-
-        // checking llsc reservation buffer
-        if ( r_dcache_llsc_paddr.read() == r_dcache_tlb_paddr.read() )
-            r_dcache_llsc_valid = false;
-
-        // request a CAS CMD and go to DCACHE_TLB_LR_WAIT state
-        r_dcache_vci_cas_req = true;
-        r_dcache_fsm         = DCACHE_TLB_LR_WAIT;
+
+        if (r_cas_islocal.read())
+        {
+            r_dcache.write(way,
+                           set,
+                           word,
+                           r_dcache_vci_cas_new.read());
+            //compteur dirty
+            r_dcache_dirty_word[(way*m_dcache_sets +set)*m_dcache_words+word] = 1;
+
+            if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
+            {
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
+                r_dcache_tlb_inval_line  = nline;
+                r_dcache_tlb_inval_set   = 0;
+                r_dcache_fsm_scan_save   = DCACHE_TLB_RETURN;
+                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+                break;
+            }
+
+            if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
+            {
+                r_itlb.reset();
+                r_dtlb.reset();
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
+
+#if DEBUG_DCACHE
+                if ( m_debug_activated )
+                {
+                    std::cout << "  <PROC " << name()
+                        << " DCACHE_TLB_LR_UPDT> Flush DTLB & ITLB" << std::endl;
+                }
+#endif
+            }
+
+            r_dcache_fsm = DCACHE_TLB_RETURN; 
+        }
+        else
+        {
+            // r_dcache_vci_cas_old & r_dcache_vci_cas_new registers are already set
+          r_dcache_vci_paddr = r_dcache_tlb_paddr.read();
+
+            // checking llsc reservation buffer
+            if ( r_dcache_llsc_paddr.read() == r_dcache_tlb_paddr.read() )
+                r_dcache_llsc_valid = false;
+
+            // request a CAS CMD and go to DCACHE_TLB_LR_WAIT state
+            r_dcache_vci_cas_req = true;
+            r_dcache_fsm         = DCACHE_TLB_LR_WAIT;
+        }
         break;
     }
@@ -3739,6 +3910,7 @@
                                &tag,
                                &state );
-
-            if ( state == CACHE_SLOT_STATE_VALID )         // inval required
+            /*ODCCP*/
+
+            if ( state == CACHE_SLOT_STATE_VALID_CC )         // inval required
             {
                 // request cleanup
@@ -3751,5 +3923,37 @@
                 r_dcache_miss_way     = way;
                 r_dcache_miss_set     = set;
+                r_dcache_cc_cleanup_line_ncc = false;
+                r_dcache_cc_cleanup_updt_data = false;
                 r_dcache_fsm          = DCACHE_XTN_DC_FLUSH_GO;
+            }
+            else if ( state == CACHE_SLOT_STATE_VALID_NCC)
+            {
+                // request cleanup
+                r_dcache_cc_send_req   = true;
+                r_dcache_cc_send_nline = tag * m_dcache_sets + set;
+                r_dcache_cc_send_way   = way;
+                r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
+
+                // goes to DCACHE_XTN_DC_FLUSH_GO to inval directory
+                r_dcache_miss_way     = way;
+                r_dcache_miss_set     = set;
+                r_dcache_cc_cleanup_line_ncc = true;
+                //if (r_dcache_content_state[m_dcache_sets*way+set] != LINE_CACHE_DATA_NOT_DIRTY)//Must send data in the cleanup
+                if (true)//Must send data in the cleanup
+                {
+                    r_dcache_xtn_flush_addr_data = (tag * m_dcache_sets + set) * m_dcache_words * 4;
+                    r_dcache_xtn_flush_data_cpt = 0;
+                    r_dcache_cc_cleanup_updt_data = true;
+                    for (size_t w = 0; w< m_dcache_words; w++)
+                    {
+                        m_cpt_cleanup_data_dirty_word += r_dcache_dirty_word[(m_dcache_sets*way+set)*m_dcache_words + w];
+                    }
+                    r_dcache_fsm          = DCACHE_XTN_DC_FLUSH_DATA;
+                }
+                else
+                {
+                    r_dcache_cc_cleanup_updt_data = false;
+                    r_dcache_fsm          = DCACHE_XTN_DC_FLUSH_GO;
+                }
             }
             else if ( r_dcache_flush_count.read() ==
@@ -3768,4 +3972,34 @@
         break;
     }
+
+    ////////////////////////////
+    case DCACHE_XTN_DC_FLUSH_DATA:
+    {
+        uint32_t rdata;
+        size_t   way;
+        size_t   set;
+        size_t   word;
+        r_dcache.read_neutral(r_dcache_xtn_flush_addr_data.read(),
+                              &rdata,
+                              &way,
+                              &set,
+                              &word);
+        if(r_cc_send_data_fifo.wok())
+        {
+            r_dcache_xtn_flush_addr_data = r_dcache_xtn_flush_addr_data.read() + 4;
+
+            cleanup_data_updt_fifo_dcache_put   = true;
+            cleanup_data_updt_fifo_dcache_data  = rdata;
+
+            r_dcache_xtn_flush_data_cpt = r_dcache_xtn_flush_data_cpt + 1;
+            if(r_dcache_xtn_flush_data_cpt.read() == (m_dcache_words - 1))
+            {
+                r_dcache_xtn_flush_data_cpt = 0;
+                r_dcache_fsm = DCACHE_XTN_DC_FLUSH_GO;
+            }
+        }
+        break;
+    }
+
     ////////////////////////////
     case DCACHE_XTN_DC_FLUSH_GO:    // Switch the cache slot to ZOMBI state
@@ -3776,6 +4010,8 @@
         size_t set = r_dcache_miss_set.read();
 
-        r_dcache_in_tlb[m_dcache_sets*way+set]       = false;
-        r_dcache_contains_ptd[m_dcache_sets*way+set] = false;
+        // MODIFIED
+        //r_dcache_in_tlb[m_dcache_sets*way+set]       = false;
+        //r_dcache_contains_ptd[m_dcache_sets*way+set] = false;
+        r_dcache_content_state[m_dcache_sets*way+set]  = LINE_CACHE_DATA_DIRTY;
 
 #ifdef INSTRUMENTATION
@@ -3820,5 +4056,5 @@
 
 #ifdef INSTRUMENTATION
-m_cpt_dtlb_read++;
+m_cpt_data_tlb_read++;
 #endif
             hit = r_dtlb.translate( r_dcache_save_wdata.read(),
@@ -3840,5 +4076,5 @@
 
 #ifdef INSTRUMENTATION
-m_cpt_dtlb_miss++;
+m_cpt_data_tlb_miss++;
 #endif
             r_dcache_tlb_ins    = false;		// dtlb
@@ -3877,10 +4113,19 @@
                            &set,
                            &word );
-
-        if ( state == CACHE_SLOT_STATE_VALID )	// inval to be done
-        {
-            r_dcache_xtn_way = way;
-            r_dcache_xtn_set = set;
-            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_GO;
+        /*ODCCP*/
+        //assert((state != CACHE_SLOT_STATE_VALID_NCC) and "NOT YET DONE");
+        if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC))	// inval to be done
+        {
+            r_dcache_xtn_way       = way;
+            r_dcache_xtn_set       = set;
+            r_dcache_xtn_state     = state;
+            r_dcache_xtn_data_addr = r_dcache_save_paddr.read()&~0x3F;
+            
+            if( (state == CACHE_SLOT_STATE_VALID_NCC) and (r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_DATA_NOT_DIRTY) )
+            {
+                m_cpt_cleanup_data_not_dirty ++;
+            }
+            r_dcache_fsm = DCACHE_XTN_DC_INVAL_GO;
+            
         }
         else		// miss : nothing to do
@@ -3896,7 +4141,8 @@
               << " DCACHE_XTN_DC_INVAL_PA> Test hit in dcache" << std::hex
               << " / PADDR = " << r_dcache_save_paddr.read() << std::dec
-              << " / HIT = " << (state == CACHE_SLOT_STATE_VALID)
+              << " / HIT = " << ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC))
               << " / SET = " << set
               << " / WAY = " << way << std::endl;
+    //r_dcache.printTrace();
 }
 #endif
@@ -3910,4 +4156,5 @@
         if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
         {
+            int     state      = r_dcache_xtn_state.read();
             size_t	way        = r_dcache_xtn_way.read();
             size_t	set        = r_dcache_xtn_set.read();
@@ -3917,16 +4164,50 @@
 m_cpt_dcache_dir_write++;
 #endif
-            r_dcache.write_dir( way,
-                                set,
-                                CACHE_SLOT_STATE_ZOMBI );
-
-            // request cleanup
-            r_dcache_cc_send_req   = true;
-            r_dcache_cc_send_nline = nline;
-            r_dcache_cc_send_way   = way;
-            r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
+            // MODIFIER POUR DIRTY BIT //
+            if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC))// request cleanup
+            {
+                r_dcache_cc_send_req   = true;
+                r_dcache_cc_send_nline = nline;
+                r_dcache_cc_send_way   = way;
+                r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
+                if (state == CACHE_SLOT_STATE_VALID_CC)
+                {
+                    r_dcache_cc_cleanup_line_ncc = false;
+                    r_dcache.write_dir( way,
+                            set,
+                            CACHE_SLOT_STATE_ZOMBI );
+                }
+                else
+                {
+                    r_dcache_cc_cleanup_line_ncc = true;
+                    //if ((r_dcache_content_state[way*m_dcache_sets+set] != LINE_CACHE_DATA_NOT_DIRTY)) //must send data
+                    if (true) //must send data
+                    {
+                        r_dcache_cc_cleanup_updt_data = true;
+                        for (size_t w = 0; w< m_dcache_words; w++)
+                        {
+                            m_cpt_cleanup_data_dirty_word += r_dcache_dirty_word[(m_dcache_sets*way+set)*m_dcache_words + w];
+                        }
+                        r_dcache_fsm = DCACHE_XTN_DC_INVAL_DATA;
+                        break;
+                    }
+                    else
+                    {
+                        r_dcache_cc_cleanup_updt_data = false;
+                        r_dcache.write_dir( way,
+                                            set,
+                                            CACHE_SLOT_STATE_ZOMBI );
+                    }
+                    if( (state == CACHE_SLOT_STATE_VALID_NCC) and (r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_DATA_NOT_DIRTY) )
+                        m_cpt_cleanup_data_not_dirty ++;
+                }
+            }
+            /*ODCCP*/
 
             // possible itlb & dtlb invalidate
-            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
+            // MODIFIED
+            //if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
+            //{
+            if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
             {
                 r_dcache_tlb_inval_line = nline;
@@ -3934,11 +4215,18 @@
                 r_dcache_fsm_scan_save  = DCACHE_XTN_DC_INVAL_END;
                 r_dcache_fsm            = DCACHE_INVAL_TLB_SCAN;
-                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
-            }
-            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
+                // MODIFIED
+                //r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
+            }
+            // MODIFIED
+            //else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
+            //{
+            else if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD)
             {
                 r_itlb.reset();
                 r_dtlb.reset();
-                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+                // MODIFIED
+                //r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
                 r_dcache_fsm = DCACHE_IDLE;
                 m_drsp.valid = true;
@@ -3961,4 +4249,40 @@
         break;
     }
+
+    /*ODCCP*/
+    //////////////////////////////
+    case DCACHE_XTN_DC_INVAL_DATA:  	//A verifier
+    {
+
+        uint32_t rdata;
+        size_t   way;
+        size_t   set;
+        size_t   word;
+        r_dcache.read_neutral(r_dcache_xtn_data_addr.read(),
+                              &rdata,
+                              &way,
+                              &set,
+                              &word);
+        if(r_cc_send_data_fifo.wok())
+        {
+            r_dcache_xtn_data_addr = r_dcache_xtn_data_addr.read() + 4;
+
+            cleanup_data_updt_fifo_dcache_put   = true;
+            cleanup_data_updt_fifo_dcache_data  = rdata;
+
+            r_dcache_xtn_data_cpt = r_dcache_xtn_data_cpt.read() + 1;
+            if(r_dcache_xtn_data_cpt.read() == (m_dcache_words - 1))
+            {
+                r_dcache_xtn_state = CACHE_SLOT_STATE_ZOMBI;
+                r_dcache_xtn_data_cpt = 0;
+                r_dcache_fsm = DCACHE_XTN_DC_INVAL_GO;
+                r_dcache.write_dir( way,
+                                    set,
+                                    CACHE_SLOT_STATE_ZOMBI );
+            }
+        }
+        break;
+    }
+
     //////////////////////////////
     case DCACHE_XTN_DC_INVAL_END:  	// send response to processor XTN request
@@ -4001,4 +4325,5 @@
             size_t   set = 0;
             paddr_t  victim = 0;
+            int state;
 
 #ifdef INSTRUMENTATION
@@ -4011,4 +4336,5 @@
                                   &found,
                                   &cleanup );
+            state = r_dcache.get_cache_state(way,set);
 
             if ( found )
@@ -4026,4 +4352,33 @@
                     r_dcache_cc_send_way   = way;
                     r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
+                    if( (state == CACHE_SLOT_STATE_VALID_NCC) )//and (r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_DATA_DIRTY) )
+                    {
+                        //MODIFIER POUR DIRTY BIT //
+                        r_dcache_cc_cleanup_line_ncc = true;
+                        r_dcache_miss_data_addr = (victim*m_dcache_words)*4;
+                        //if ((r_dcache_content_state[way*m_dcache_sets+set] != LINE_CACHE_DATA_NOT_DIRTY))//must send data
+                        if (true)//must send data
+                        {
+                            r_dcache_cc_cleanup_updt_data = true;
+                            for (size_t w = 0; w< m_dcache_words; w++)
+                            {
+                                m_cpt_cleanup_data_dirty_word += r_dcache_dirty_word[(m_dcache_sets*way+set)*m_dcache_words + w];
+                            }
+                            r_dcache_fsm = DCACHE_MISS_DATA;
+                        }
+                        else
+                        {
+                            r_dcache_cc_cleanup_updt_data = false;
+                        }
+
+                        if (r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_DATA_NOT_DIRTY)
+                            m_cpt_cleanup_data_not_dirty ++;
+                    }
+                        
+                    else
+                    {
+                        r_dcache_cc_cleanup_line_ncc  = false;
+                        r_dcache_cc_cleanup_updt_data = false;
+                    }
                 }
                 else
@@ -4049,4 +4404,33 @@
     }
     ///////////////////////
+    case DCACHE_MISS_DATA:
+    {
+        uint32_t rdata;
+        size_t way;
+        size_t set;
+        size_t word;
+
+        r_dcache.read_neutral(r_dcache_miss_data_addr,
+                              &rdata,
+                              &way,
+                              &set,
+                              &word);
+        if(r_cc_send_data_fifo.wok())
+        {
+            r_dcache_miss_data_addr = r_dcache_miss_data_addr.read() + 4;
+
+            cleanup_data_updt_fifo_dcache_put   = true;
+            cleanup_data_updt_fifo_dcache_data  = rdata;
+
+            r_dcache_miss_data_cpt = r_dcache_miss_data_cpt.read() + 1;
+            if (r_dcache_miss_data_cpt.read() == m_dcache_words-1 )
+            {
+                r_dcache_miss_data_cpt = 0;
+                r_dcache_fsm = DCACHE_MISS_CLEAN;
+            }
+        }
+        break;
+    }
+    ///////////////////////
     case DCACHE_MISS_CLEAN:		// switch the slot to ZOMBI state
                                 // and possibly request itlb or dtlb invalidate
@@ -4074,7 +4458,12 @@
         // if selective itlb & dtlb invalidate are required
         // the miss response is not handled before invalidate completed
-        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
-        {
-            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+        // MODIFIED
+        //if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
+        //{
+        if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
+        {
+            //MODIFIED
+            //r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+            r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
             r_dcache_tlb_inval_line  = r_dcache_cc_send_nline;
             r_dcache_tlb_inval_set   = 0;
@@ -4082,9 +4471,14 @@
             r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
         }
-        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
+        // MODIFIED
+        //else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
+        //{
+        else if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
         {
             r_itlb.reset();
             r_dtlb.reset();
-            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+            // MODIFIED
+            //r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+            r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
             r_dcache_fsm = DCACHE_MISS_WAIT;
         }
@@ -4101,5 +4495,4 @@
     {
         if ( m_dreq.valid) m_cost_data_miss_frz++;
-
         // coherence clack request (from DSPIN CLACK)
         if ( r_dcache_clack_req.read() )
@@ -4184,5 +4577,5 @@
         if ( m_dreq.valid) m_cost_data_miss_frz++;
 
-        if ( r_vci_rsp_fifo_dcache.rok() )	// one word available
+        if ( r_vci_rsp_fifo_dcache.rok() && r_vci_rsp_fifo_rpktid.rok())	// one word available
         {
 #ifdef INSTRUMENTATION
@@ -4205,4 +4598,9 @@
 #endif
             vci_rsp_fifo_dcache_get = true;
+
+            r_dcache_read_state = !r_vci_rsp_fifo_rpktid.read();//deduce the state (CC or NCC) from msb of pktid
+            vci_rsp_fifo_rpktid_get = true;
+
+
             r_dcache_miss_word = r_dcache_miss_word.read() + 1;
 
@@ -4253,4 +4651,6 @@
                     r_dcache_cc_send_way   = r_dcache_miss_way.read();
                     r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
+                    r_dcache_cc_cleanup_updt_data = false; //the line is evicted at the very moment it arives, so it is not dirty
+                    r_dcache_cc_cleanup_line_ncc = !r_dcache_read_state.read();
 
 #ifdef INSTRUMENTATION
@@ -4279,8 +4679,28 @@
 m_cpt_dcache_dir_write++;
 #endif
-                r_dcache.write_dir( r_dcache_save_paddr.read(),
-                                    r_dcache_miss_way.read(),
-                                    r_dcache_miss_set.read(),
-                                    CACHE_SLOT_STATE_VALID );
+
+                size_t way = r_dcache_miss_way.read();
+                size_t set = r_dcache_miss_set.read();
+                if (r_dcache_read_state.read())
+                {
+                  r_dcache.write_dir( r_dcache_save_paddr.read(),
+                                        r_dcache_miss_way.read(),
+                                        r_dcache_miss_set.read(),
+                                        CACHE_SLOT_STATE_VALID_CC );
+
+                    r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
+                }
+                else
+                {
+                  r_dcache.write_dir( r_dcache_save_paddr.read(),
+                                        r_dcache_miss_way.read(),
+                                        r_dcache_miss_set.read(),
+                                        CACHE_SLOT_STATE_VALID_NCC );
+                    r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
+                    for (size_t word =0; word < m_dcache_words ; word++)
+                    {
+                        r_dcache_dirty_word[(way*m_dcache_sets +set)*m_dcache_words+word] = 0;
+                    }
+                }
 
 #if DEBUG_DCACHE
@@ -4293,8 +4713,8 @@
 #endif
                 // reset directory extension
-                size_t way = r_dcache_miss_way.read();
-                size_t set = r_dcache_miss_set.read();
-                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
-                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+
+                // MODIFIED
+                //r_dcache_in_tlb[way*m_dcache_sets+set] = false;
+                //r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
             }
             if      (r_dcache_miss_type.read()==PTE1_MISS) r_dcache_fsm = DCACHE_TLB_PTE1_GET;
@@ -4467,5 +4887,5 @@
                        &state );
 
-        assert( (state == CACHE_SLOT_STATE_VALID) and
+        assert( (state == CACHE_SLOT_STATE_VALID_CC or state == CACHE_SLOT_STATE_VALID_NCC) and
         "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
 
@@ -4479,9 +4899,23 @@
 
         // request a CAS CMD and go to DCACHE_DIRTY_WAIT state
-        r_dcache_vci_cas_req = true;
-        r_dcache_vci_paddr   = r_dcache_dirty_paddr.read();
-        r_dcache_vci_cas_old = pte;
-        r_dcache_vci_cas_new = pte | PTE_D_MASK;
-        r_dcache_fsm         = DCACHE_DIRTY_WAIT;
+        if (state == CACHE_SLOT_STATE_VALID_CC)
+        {
+            r_dcache_vci_cas_req = true;
+            r_dcache_vci_paddr   = r_dcache_dirty_paddr.read();
+            r_dcache_vci_cas_old = pte;
+            r_dcache_vci_cas_new = pte | PTE_D_MASK;
+            r_cas_islocal        = false;
+        }
+        else
+        {
+            r_cas_islocal = true;
+            r_cas_local_way = way;
+            r_cas_local_set = set;
+            r_cas_local_word = word;
+            r_dcache_vci_cas_new = pte | PTE_D_MASK;
+        }
+
+
+            r_dcache_fsm         = DCACHE_DIRTY_WAIT;
 
 #if DEBUG_DCACHE
@@ -4506,4 +4940,9 @@
                                     // - if the CAS is a failure, we just retry the write.
     {
+        uint32_t way  = r_cas_local_way.read();
+        uint32_t set  = r_cas_local_set.read();
+        uint32_t word = r_cas_local_word.read();
+        paddr_t nline = r_dcache_dirty_paddr.read() / (m_dcache_words<<2);
+
         // coherence clack request (from DSPIN CLACK)
         if ( r_dcache_clack_req.read() )
@@ -4522,15 +4961,16 @@
         }
 
-        if ( r_vci_rsp_data_error.read() )      // bus error
-        {
-            std::cout << "BUS ERROR in DCACHE_DIRTY_WAIT state" << std::endl;
-            std::cout << "This should not happen in this state" << std::endl;
-            exit(0);
-        }
-        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
-        {
-            vci_rsp_fifo_dcache_get = true;
-            r_dcache_fsm            = DCACHE_IDLE;
-
+        if (!r_cas_islocal.read())
+        {
+            if ( r_vci_rsp_data_error.read() )	// bus error
+            {
+                std::cout << "BUS ERROR in DCACHE_DIRTY_WAIT state" << std::endl;
+                std::cout << "This should not happen in this state" << std::endl;
+                exit(0);
+            }
+            else if ( r_vci_rsp_fifo_dcache.rok() )	// response available
+            {
+                vci_rsp_fifo_dcache_get = true;
+                r_dcache_fsm            = DCACHE_IDLE;
 #if DEBUG_DCACHE
 if ( m_debug_activated )
@@ -4540,4 +4980,38 @@
 }
 #endif
+            }
+        }
+        else
+        {
+            r_dcache.write(way,
+                           set,
+                           word,
+                           r_dcache_vci_cas_new.read());
+            //std::cout << "CAS local" << std::endl;
+            if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
+            {
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
+                r_dcache_tlb_inval_line  = nline;
+                r_dcache_tlb_inval_set   = 0;
+                r_dcache_fsm_scan_save   = DCACHE_IDLE;
+                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+                break;
+            }
+
+            if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
+            {
+                r_itlb.reset();
+                r_dtlb.reset();
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_DIRTY;
+
+#if DEBUG_DCACHE
+                if ( m_debug_activated )
+                {
+                    std::cout << "  <PROC " << name()
+                        << " DCACHE_DIRTY_WAIT> Flush DTLB & ITLB" << std::endl;
+                }
+#endif
+            }
+            r_dcache_fsm            = DCACHE_IDLE;
         }
         break;
@@ -4674,19 +5148,27 @@
                            &word ); // unused
 
+        r_dcache_cc_state = state;
         r_dcache_cc_way = way;
         r_dcache_cc_set = set;
-
-        if ( state == CACHE_SLOT_STATE_VALID) // hit
-        {
-            // need to update the cache state
-            if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT) // hit update
-            {
-                r_dcache_cc_need_write = true;
-                r_dcache_fsm           = DCACHE_CC_UPDT;
-                r_dcache_cc_word       = r_cc_receive_word_idx.read();
-            }
-            else if ( r_cc_receive_dcache_type.read() == CC_TYPE_INVAL ) // hit inval
-            {
-                r_dcache_fsm           = DCACHE_CC_INVAL;
+            /*RWT / ODCCP*/
+        if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC))             // hit
+        {
+          // need to update the cache state
+            r_dcache_cc_need_write = true;
+            r_dcache_cc_cleanup_line_ncc = false;
+            if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)  // hit update
+            {
+                r_dcache_fsm          = DCACHE_CC_UPDT;
+                r_dcache_cc_word      = r_cc_receive_word_idx.read();
+            }
+            else if (r_cc_receive_dcache_type.read() == CC_TYPE_INVAL)   // hit inval
+            {
+                if (state == CACHE_SLOT_STATE_VALID_NCC)
+                {
+                    r_dcache_cc_inval_addr = (paddr &~0x3F);
+                    r_dcache_cc_inval_data_cpt = 0;
+                }
+                r_dcache_fsm          = DCACHE_CC_INVAL;
+                r_dcache_dirty_save   = false;
             }
         }
@@ -4716,5 +5198,5 @@
               << " PADDR = " << std::hex << paddr
               << " / TYPE = " << std::dec << r_cc_receive_dcache_type.read()
-              << " / HIT = " << (state == CACHE_SLOT_STATE_VALID) << std::endl;
+              << " / HIT = " << ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC)) << std::endl;
 }
 #endif
@@ -4722,4 +5204,5 @@
         break;
     }
+
     /////////////////////
     case DCACHE_CC_INVAL: // hit inval: switch slot to ZOMBI state and send a
@@ -4729,21 +5212,29 @@
         size_t way    = r_dcache_cc_way.read();
         size_t set    = r_dcache_cc_set.read();
-
-        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )       // selective TLB inval
-        {
-            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
-            r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
-            r_dcache_tlb_inval_set   = 0;
-            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
-            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
-            break;
-        }
-
-        if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) // TLB flush
-        {
-            r_itlb.reset();
-            r_dtlb.reset();
-            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
-
+        int      cache_state = r_dcache_cc_state.read();
+        bool     dirty_save = false;
+
+        if (r_dcache_cc_need_write.read())
+        {
+            if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
+            {
+                r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;//need to remember it was dirty for cleanup
+                dirty_save = true;
+                r_dcache_dirty_save = true;
+                r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
+                r_dcache_tlb_inval_set   = 0;
+                r_dcache_fsm_scan_save   = r_dcache_fsm.read();
+                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+                break;
+            }
+            else
+            {
+                if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
+                {
+                    r_itlb.reset();
+                    r_dtlb.reset();
+                    r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
+                    dirty_save = true;
+                    r_dcache_dirty_save = true;
 #if DEBUG_DCACHE
 if ( m_debug_activated )
@@ -4753,33 +5244,85 @@
 }
 #endif
-        }
-
-        assert (not r_dcache_cc_send_req.read() &&
-                "ERROR in DCACHE_CC_INVAL: the r_dcache_cc_send_req "
-                "must not be set");
-
-        // Switch slot state to ZOMBI and send CLEANUP command 
-        r_dcache.write_dir( 0,
-                            way,
-                            set,
-                            CACHE_SLOT_STATE_ZOMBI );
-
-        // coherence request completed
-        r_cc_receive_dcache_req = false;
-        r_dcache_cc_send_req    = true;
-        r_dcache_cc_send_nline  = r_cc_receive_dcache_nline.read();
-        r_dcache_cc_send_way    = r_dcache_cc_way.read();
-        r_dcache_cc_send_type   = CC_TYPE_CLEANUP;
-        r_dcache_fsm            = r_dcache_fsm_cc_save.read();
-
-#if DEBUG_DCACHE
-if ( m_debug_activated )
-{
-    std::cout << "  <PROC " << name()
-        << " DCACHE_CC_INVAL> Switch slot to EMPTY state:" << std::dec
-        << " / WAY = " << way
-        << " / SET = " << set << std::endl;
-}
-#endif
+                }
+
+                if (cache_state == CACHE_SLOT_STATE_VALID_CC) 
+                {
+                    r_dcache.write_dir( way,
+                                        set,
+                                        CACHE_SLOT_STATE_ZOMBI );
+                }
+
+                r_dcache_cc_need_write = false;
+            }
+        }
+            assert (not r_dcache_cc_send_req.read() &&
+                    "ERROR in DCACHE_CC_INVAL: the r_dcache_cc_send_req "
+                    "must not be set");
+            // coherence request completed
+                r_cc_receive_dcache_req = false;
+            // request multicast acknowledgement
+                r_dcache_cc_send_req = true;
+                r_dcache_cc_send_way = way;
+                r_dcache_cc_send_nline = r_cc_receive_dcache_nline.read();
+                r_dcache_cc_send_type = CC_TYPE_CLEANUP;
+                // MODIFIER POUR DIRTY BIT //
+                if (cache_state == CACHE_SLOT_STATE_VALID_NCC)
+                {
+                    r_dcache_cc_cleanup_line_ncc = true; 
+                    //if ((r_dcache_content_state[way*m_dcache_sets+set] != LINE_CACHE_DATA_NOT_DIRTY) or r_dcache_dirty_save.read() or dirty_save) //must send data
+                    if (true) //must send data
+                    {
+                        r_dcache_cc_cleanup_updt_data = true;
+                        for (size_t w = 0; w< m_dcache_words; w++)
+                        {
+                            m_cpt_cleanup_data_dirty_word += r_dcache_dirty_word[(m_dcache_sets*way+set)*m_dcache_words + w];
+                        }
+                        r_dcache_fsm          = DCACHE_CC_INVAL_DATA;
+                    }
+                    else
+                    {
+                        r_dcache_cc_cleanup_updt_data = false;
+                        r_dcache_fsm = r_dcache_fsm_cc_save.read();
+                    }
+                }
+                else
+                {
+                    r_dcache_cc_cleanup_updt_data = false;
+                    r_dcache_fsm = r_dcache_fsm_cc_save.read();
+                }
+
+        break;
+    }
+    
+    /////////////////////
+    case DCACHE_CC_INVAL_DATA:
+    {
+
+        uint32_t rdata;
+        size_t   way;
+        size_t   set;
+        size_t   word;
+        r_dcache.read_neutral(r_dcache_cc_inval_addr.read(),
+                              &rdata,
+                              &way,
+                              &set,
+                              &word);
+        if(r_cc_send_data_fifo.wok())
+        {
+            r_dcache_cc_inval_addr = r_dcache_cc_inval_addr.read() + 4;
+
+            cleanup_data_updt_fifo_dcache_put   = true;
+            cleanup_data_updt_fifo_dcache_data  = rdata;
+
+            r_dcache_cc_inval_data_cpt = r_dcache_cc_inval_data_cpt.read() + 1;
+            if(r_dcache_cc_inval_data_cpt.read() == (m_dcache_words - 1))
+            {
+                r_dcache_cc_inval_data_cpt = 0;
+                r_dcache_fsm          = r_dcache_fsm_cc_save.read();
+                r_dcache.write_dir( way,
+                                    set,
+                                    CACHE_SLOT_STATE_ZOMBI );
+            }
+        }
         break;
     }
@@ -4792,20 +5335,20 @@
         size_t set        = r_dcache_cc_set.read();
 
-        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )       // selective TLB inval
-        {
-            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
-            r_dcache_tlb_inval_line = r_cc_receive_dcache_nline.read();
-            r_dcache_tlb_inval_set  = 0;
-            r_dcache_fsm_scan_save  = r_dcache_fsm.read();
-            r_dcache_fsm            = DCACHE_INVAL_TLB_SCAN;
-
-            break;
-        }
-
-        if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) // TLB flush
-        {
-            r_itlb.reset();
-            r_dtlb.reset();
-            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
+            if (r_dcache_cc_need_write.read())
+            {
+                if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_IN_TLB )
+                {
+                    r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
+                    r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
+                    r_dcache_tlb_inval_set   = 0;
+                    r_dcache_fsm_scan_save   = r_dcache_fsm.read();
+                    r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
+                    break;
+                }
+                if ( r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_CONTAINS_PTD )
+                {
+                    r_itlb.reset();
+                    r_dtlb.reset();
+                    r_dcache_content_state[way*m_dcache_sets+set] = LINE_CACHE_DATA_NOT_DIRTY;
 
 #if DEBUG_DCACHE
@@ -4816,15 +5359,12 @@
 }
 #endif
-        }
-
-        assert (not r_dcache_cc_send_req.read() &&
-                "ERROR in DCACHE_CC_INVAL: the r_dcache_cc_send_req "
-                "must not be set");
+                }
+
+                assert (not r_dcache_cc_send_req.read() &&
+                        "ERROR in DCACHE_CC_INVAL: the r_dcache_cc_send_req "
+                        "must not be set");
         
-        if ( not r_cc_receive_updt_fifo_be.rok() ) break;
-
-        if (r_dcache_cc_need_write.read())
-        {
-        
+                if ( not r_cc_receive_updt_fifo_be.rok() ) break;
+
 #ifdef INSTRUMENTATION
 m_cpt_dcache_data_write++;
@@ -4855,5 +5395,4 @@
             // no need to write in the cache anymore
             r_dcache_cc_need_write = false;
-
             // coherence request completed
             r_cc_receive_dcache_req = false;
@@ -5041,5 +5580,4 @@
                         r_dcache_vci_unc_req.read())
                      or r_vci_cmd_imiss_prio.read() );
-
             // 1 - Data Read Miss
             if ( dcache_miss_req and r_wbuf.miss(r_dcache_vci_paddr.read()) )
@@ -5048,5 +5586,5 @@
                 r_dcache_vci_miss_req = false;
                 r_vci_cmd_imiss_prio  = true;
-//                m_cpt_dmiss_transaction++;
+                m_cpt_dmiss_transaction++;
             }
             // 2 - Data Read Uncachable
@@ -5055,5 +5593,5 @@
                 r_vci_cmd_fsm        = CMD_DATA_UNC;
                 r_dcache_vci_unc_req = false;
-//                m_cpt_dunc_transaction++;
+                m_cpt_dunc_transaction++;
             }
             // 3 - Data Linked Load
@@ -5062,5 +5600,5 @@
                 r_dcache_vci_ll_req = false;
                 r_vci_cmd_fsm       = CMD_DATA_LL;
-//              m_cpt_ll_transaction++;
+                m_cpt_ll_transaction++;
             }
             // 4 - Instruction Miss
@@ -5070,5 +5608,5 @@
                 r_icache_miss_req    = false;
                 r_vci_cmd_imiss_prio = false;
-//                m_cpt_imiss_transaction++;
+                m_cpt_imiss_transaction++;
             }
             // 5 - Instruction Uncachable
@@ -5077,5 +5615,5 @@
                 r_vci_cmd_fsm       = CMD_INS_UNC;
                 r_icache_unc_req    = false;
-//                m_cpt_iunc_transaction++;
+                //m_cpt_iunc_transaction++;
             }
             // 6 - Data Write
@@ -5086,6 +5624,6 @@
                 r_vci_cmd_min       = wbuf_min;
                 r_vci_cmd_max       = wbuf_max;
-//                m_cpt_write_transaction++;
-//                m_length_write_transaction += (wbuf_max-wbuf_min+1);
+                m_cpt_write_transaction++;
+                m_length_write_transaction += (wbuf_max-wbuf_min+1);
             }
             // 7 - Data Store Conditionnal
@@ -5095,5 +5633,5 @@
                 r_vci_cmd_cpt  = 0;
                 r_vci_cmd_fsm  = CMD_DATA_SC;
-//              m_cpt_sc_transaction++;
+                //m_cpt_sc_transaction++;
             }
             // 8 - Compare And Swap
@@ -5103,5 +5641,5 @@
                 r_dcache_vci_cas_req = false;
                 r_vci_cmd_cpt        = 0;
-//              m_cpt_cas_transaction++;
+                //m_cpt_cas_transaction++;
             }
 
@@ -5194,5 +5732,5 @@
         {
             r_vci_rsp_cpt = 0;
-
+            if (r_dcache_vci_paddr.read() == 0x1f624) std::cout << "Tansaction on barrier, pktid = " <<  p_vci.rpktid.read() << std::endl;
             if      ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_DATA_UNC  )
             {
@@ -5248,7 +5786,11 @@
                     if ( r_vci_rsp_fifo_icache.wok() )
                     {
-                        assert( (r_vci_rsp_cpt.read() < m_icache_words) and
-                        "The VCI response packet for instruction miss is too long" );
-
+                        if ( r_vci_rsp_cpt.read() >= m_icache_words )
+                        {
+                            std::cout << "ERROR in VCI_CC_VCACHE " << name()
+                                      << " VCI response packet too long "
+                                      << " for instruction miss" << std::endl;
+                            exit(0);
+                        }
                         r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
                         vci_rsp_fifo_icache_put       = true,
@@ -5256,7 +5798,11 @@
                         if ( p_vci.reop.read() )
                         {
-                            assert( (r_vci_rsp_cpt.read() == m_icache_words - 1) and
-                            "The VCI response packet for instruction miss is too short");
-
+                            if ( r_vci_rsp_cpt.read() != (m_icache_words - 1) )
+                            {
+                                std::cout << "ERROR in VCI_CC_VCACHE " << name()
+                                          << " VCI response packet too short" 
+                                          << " for instruction miss" << std::endl;
+                                exit(0);
+                            }
                             r_vci_rsp_fsm    = RSP_IDLE;
                         }
@@ -5303,5 +5849,7 @@
                 else                                        // no error reported
                 {
-                    if ( r_vci_rsp_fifo_dcache.wok() )
+
+
+                    if ( r_vci_rsp_fifo_dcache.wok() && r_vci_rsp_fifo_rpktid.wok())
                     {
                         assert( (r_vci_rsp_cpt.read() < m_dcache_words) and
@@ -5311,6 +5859,10 @@
                         vci_rsp_fifo_dcache_put       = true,
                         vci_rsp_fifo_dcache_data      = p_vci.rdata.read();
+                        vci_rsp_fifo_rpktid          = (p_vci.rpktid.read() == 0x9);//RWT: interpretation of pktid for state (NCC or CC)
+                        vci_rsp_fifo_rpktid_put      = true;//RWT
+
                         if ( p_vci.reop.read() )
                         {
+                            if (r_vci_rsp_cpt.read() != m_dcache_words - 1) std::cout << "assert on proc " << name() << std::endl;
                             assert( (r_vci_rsp_cpt.read() == m_dcache_words - 1) and
                             "The VCI response packet for data miss is too short");
@@ -5472,11 +6024,47 @@
             if (p_dspin_p2m.read.read())
             {
-                if (r_cc_send_last_client.read() == 0) // dcache active request
-                    r_dcache_cc_send_req = false; // reset dcache request
-                else // icache active request
-                    r_icache_cc_send_req = false; // reset icache request
-
-                // go back to idle state
-                r_cc_send_fsm = CC_SEND_IDLE;
+                //std::cout << "CLEANUP send on line " << r_dcache_cc_send_nline.read() << std::endl;
+                if(r_dcache_cc_cleanup_updt_data.read() and (r_cc_send_last_client.read() == 0))//dcache request with data
+               {
+                    r_cc_send_fsm = CC_SEND_CLEANUP_DATA_UPDT;
+                }
+                else
+                {
+                    if (r_cc_send_last_client.read() == 0) // dcache active request
+                    {
+                        r_dcache_cc_send_req = false; // reset dcache request
+                    }
+                    else // icache active request
+                    {
+                        r_icache_cc_send_req = false; // reset icache request
+                    }
+                    // go back to idle state
+                    r_cc_send_fsm = CC_SEND_IDLE;
+                }
+            }
+            break;
+        }
+        ///////////////////////////
+        case CC_SEND_CLEANUP_DATA_UPDT:
+        {
+            if (p_dspin_p2m.read.read())
+            {
+                if(r_cc_send_data_fifo.rok())
+                {
+                    /*ODCCP*///std::cout<<"CLEANUP_DATA_UPDT" << std::endl;
+                    m_cpt_data_cleanup++;
+                    cleanup_data_updt_fifo_dcache_get = true;
+                    r_cc_send_cpt_word = r_cc_send_cpt_word.read() + 1;
+                    if (r_cc_send_cpt_word.read() == m_dcache_words-1)
+                    {
+                        //std::cout << "L1 paddr CLEANUP DATA | paddr = " << std::hex << (r_dcache_cc_send_nline.read()*m_dcache_words)*4 << std::dec << std::endl;
+                        /*ODCCP*/
+                        //std::cout << "CLEANUP with DATA finished by " << name() << std::endl;
+                        r_dcache_cc_send_req = false;
+                        r_dcache_cc_cleanup_updt_data = false;
+                        r_cc_send_cpt_word = 0;
+                        r_cc_send_fsm = CC_SEND_IDLE;
+                    }
+                }
             }
             break;
@@ -5793,4 +6381,12 @@
                                  vci_rsp_fifo_dcache_put,
                                  vci_rsp_fifo_dcache_data);
+    //BUG pktid
+    r_vci_rsp_fifo_rpktid.update(vci_rsp_fifo_rpktid_get,
+                                 vci_rsp_fifo_rpktid_put,
+                                 vci_rsp_fifo_rpktid);
+
+    r_cc_send_data_fifo.update(cleanup_data_updt_fifo_dcache_get,
+                               cleanup_data_updt_fifo_dcache_put,
+                               cleanup_data_updt_fifo_dcache_data);
 
     ///////////////// updt FIFO update  //////////////////////
@@ -6003,5 +6599,4 @@
                                 >> (m_nline_width - m_x_width - m_y_width) 
                                 << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
- 
                 DspinDhccpParam::dspin_set(dspin_send_data,
                                            dest,
@@ -6019,4 +6614,8 @@
                                            DspinDhccpParam::TYPE_CLEANUP_DATA,
                                            DspinDhccpParam::P2M_TYPE);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           (r_dcache_cc_cleanup_line_ncc.read() and (r_cc_send_last_client.read() == 0)),
+                                           DspinDhccpParam::CLEANUP_NCC);
             }
             else                                // icache active request
@@ -6041,4 +6640,10 @@
                                            DspinDhccpParam::TYPE_CLEANUP_INST,
                                            DspinDhccpParam::P2M_TYPE);
+
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           0,
+                                           DspinDhccpParam::CLEANUP_NCC);
+
+
             }
             // send flit
@@ -6052,8 +6657,4 @@
         {
             // initialize dspin send data
-//            DspinDhccpParam::dspin_set(dspin_send_data,
-//                                       1,
-//                                       DspinDhccpParam::P2M_EOP);
-
             if(r_cc_send_last_client.read() == 0) // dcache active request
             {
@@ -6071,5 +6672,31 @@
             p_dspin_p2m.data  = dspin_send_data;
             p_dspin_p2m.write = true;
-            p_dspin_p2m.eop   = true;
+            p_dspin_p2m.eop   = ! (r_dcache_cc_cleanup_updt_data.read() and (r_cc_send_last_client.read() == 0));
+            break;
+        }
+        ///////////////////////
+        case CC_SEND_CLEANUP_DATA_UPDT:
+        {
+            /*if (r_cc_send_cpt_word.read() == m_dcache_words-1)
+            {
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           1,
+                                           DspinDhccpParam::FROM_L1_EOP);
+            }
+            else
+            {
+                DspinDhccpParam::dspin_set(dspin_send_data,
+                                           0,
+                                           DspinDhccpParam::FROM_L1_EOP);
+            }*/
+
+            DspinDhccpParam::dspin_set(dspin_send_data,
+                                       r_cc_send_data_fifo.read(),
+                                       DspinDhccpParam::CLEANUP_DATA_UPDT);
+            
+            p_dspin_p2m.data = dspin_send_data;
+            //std::cout << "genmoore CLEANUP DATA UPDT : dspin_send_data = " << std::hex << dspin_send_data << std::dec << std::endl;
+            p_dspin_p2m.write = true;
+            p_dspin_p2m.eop = (r_cc_send_cpt_word.read() == m_dcache_words-1);
             break;
         }
