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 340)
+++ trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp	(revision 361)
@@ -80,11 +80,11 @@
     "INIT_CMD_INVAL_NLINE",
     "INIT_CMD_XRAM_BRDCAST",
+    "INIT_CMD_WRITE_BRDCAST",
+    "INIT_CMD_CAS_BRDCAST",
     "INIT_CMD_UPDT_IDLE",
-    "INIT_CMD_WRITE_BRDCAST",
     "INIT_CMD_UPDT_NLINE",
     "INIT_CMD_UPDT_INDEX",
     "INIT_CMD_UPDT_DATA",
     "INIT_CMD_CAS_UPDT_IDLE",
-    "INIT_CMD_CAS_BRDCAST",
     "INIT_CMD_CAS_UPDT_NLINE",
     "INIT_CMD_CAS_UPDT_INDEX",
@@ -175,4 +175,5 @@
     "CAS_DIR_LOCK",
     "CAS_DIR_HIT_READ",
+    "CAS_DIR_HIT_COMPARE",
     "CAS_DIR_HIT_WRITE",
     "CAS_UPT_LOCK",
@@ -372,4 +373,23 @@
     r_alloc_heap_fsm("r_alloc_heap_fsm"),
     r_alloc_heap_reset_cpt("r_alloc_heap_reset_cpt")
+
+#if MONITOR_MEMCACHE_FSM
+    ,
+    p_read_fsm       ("p_read_fsm"), 
+    p_write_fsm      ("p_write_fsm"), 
+    p_xram_rsp_fsm   ("p_xram_rsp_fsm"), 
+    p_cas_fsm        ("p_cas_fsm"), 
+    p_cleanup_fsm    ("p_cleanup_fsm"), 
+    p_alloc_heap_fsm ("p_alloc_heap_fsm"), 
+    p_alloc_dir_fsm  ("p_alloc_dir_fsm"), 
+    p_alloc_trt_fsm  ("p_alloc_trt_fsm"), 
+    p_alloc_upt_fsm  ("p_alloc_upt_fsm"), 
+    p_tgt_cmd_fsm    ("p_tgt_cmd_fsm"), 
+    p_tgt_rsp_fsm    ("p_tgt_rsp_fsm"), 
+    p_ixr_cmd_fsm    ("p_ixr_cmd_fsm"), 
+    p_ixr_rsp_fsm    ("p_ixr_rsp_fsm"), 
+    p_init_cmd_fsm   ("p_init_cmd_fsm"), 
+    p_init_rsp_fsm   ("p_init_rsp_fsm") 
+#endif
     {
       assert(IS_POW_OF_2(nsets));
@@ -434,6 +454,7 @@
 
       // Allocation for CAS FSM
-      r_cas_to_ixr_cmd_data        = new sc_signal<data_t>[nwords];
-      r_cas_rdata                  = new sc_signal<data_t>[2];
+      r_cas_to_ixr_cmd_data       = new sc_signal<data_t>[nwords];
+      r_cas_data                  = new sc_signal<data_t>[nwords];
+      r_cas_rdata                 = new sc_signal<data_t>[2];
 
 
@@ -684,4 +705,6 @@
 
     r_copies_limit         = 3;
+
+    r_tgt_rsp_key_sent     = false;
 
     // Activity counters
@@ -4359,6 +4382,6 @@
                 r_cas_count      = entry.count;
 
-                if ( entry.valid )  r_cas_fsm = CAS_DIR_HIT_READ;
-                else          r_cas_fsm = CAS_MISS_TRT_LOCK;
+                if ( entry.valid ) r_cas_fsm = CAS_DIR_HIT_READ;
+                else               r_cas_fsm = CAS_MISS_TRT_LOCK;
 
 #if DEBUG_MEMC_CAS
@@ -4387,9 +4410,8 @@
         /////////////////////
         case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
-                               // and check data change in cache
+                                // and check data change in cache
         {
             size_t way  = r_cas_way.read();
             size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
-            size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
 
             // update directory (lock & dirty bits)
@@ -4399,5 +4421,5 @@
             entry.dirty          = true;
             entry.lock           = true;
-            entry.tag          = r_cas_tag.read();
+            entry.tag            = r_cas_tag.read();
             entry.owner.srcid    = r_cas_copy.read();
 #if L1_MULTI_CACHE
@@ -4410,18 +4432,42 @@
             m_cache_directory.write(set, way, entry);
 
-            // read data in cache & check data change
-            bool ok = ( r_cas_rdata[0].read() == m_cache_data.read(way, set, word) );
-            if ( r_cas_cpt.read()==4 )  // 64 bits CAS
-                ok &= ( r_cas_rdata[1] == m_cache_data.read(way, set, word+1));
+            // Stored data from cache in buffer to do the comparison in next state
+            m_cache_data.read_line(way, set, r_cas_data);
+
+            r_cas_fsm = CAS_DIR_HIT_COMPARE;
+
+#if DEBUG_MEMC_CAS
+            if(m_debug_cas_fsm)
+            {
+                std::cout
+                    << "  <MEMC " << name() << ".CAS_DIR_HIT_READ> Read data from "
+                    << " cache and store it in buffer"
+                    << std::endl;
+            }
+#endif
+            break;
+        }
+
+        case CAS_DIR_HIT_COMPARE:
+        {
+            size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
+
+            // Read data in buffer & check data change
+            bool ok = (r_cas_rdata[0].read() == r_cas_data[word].read());
+
+            if(r_cas_cpt.read() == 4)     // 64 bits CAS
+                ok &= (r_cas_rdata[1] == r_cas_data[word+1]);
 
             // to avoid livelock, force the atomic access to fail pseudo-randomly
-            bool forced_fail = ( (r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS );
-            r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((-(r_cas_lfsr & 1)) & 0xd0000001);
-
-            if( ok and not forced_fail )  // no data change
+            bool forced_fail = ((r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS);
+            r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((- (r_cas_lfsr & 1)) & 0xd0000001);
+
+            // cas success
+            if(ok and not forced_fail)
             {
                 r_cas_fsm = CAS_DIR_HIT_WRITE;
             }
-            else                            // return failure
+            // cas failure
+            else
             {
                 r_cas_fsm = CAS_RSP_FAIL;
@@ -4429,11 +4475,13 @@
 
 #if DEBUG_MEMC_CAS
-if( m_debug_cas_fsm )
-{
-    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_READ> Test if CAS success:"
-              << " / expected value = " << r_cas_rdata[0].read()
-              << " / actual value = " << m_cache_data.read(way, set, word)
-              << " / forced_fail = " << forced_fail << std::endl;
-}
+            if(m_debug_cas_fsm)
+            {
+                std::cout
+                    << "  <MEMC " << name() << ".CAS_DIR_HIT_COMPARE> Compare the old"
+                    << " and the new data"
+                    << " / expected value = " << r_cas_rdata[0].read()
+                    << " / actual value = "   << r_cas_data[word].read()
+                    << " / forced_fail = "    << forced_fail << std::endl;
+            }
 #endif
             break;
@@ -5493,12 +5541,24 @@
 }
 #endif
-                if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) )
+        
+                uint32_t last_word_idx = r_read_to_tgt_rsp_word.read() + r_read_to_tgt_rsp_length.read() - 1;
+                bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
+                bool     is_ll         = ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
+
+                if ( (is_last_word and not is_ll) or (r_tgt_rsp_key_sent.read() and is_ll))
                 {
-                    r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
+                    // Last word in case of READ or second flit in case if LL
+                    r_tgt_rsp_key_sent    = false;
                     r_read_to_tgt_rsp_req = false;
+                    r_tgt_rsp_fsm         = TGT_RSP_READ_IDLE;
                 }
                 else
                 {
-                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+                    if (is_ll) {
+                      r_tgt_rsp_key_sent = true;                // Send second flit of ll
+                    }
+                    else {
+                      r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1; // Send next word of read
+                    }
                 }
             }
@@ -5583,14 +5643,27 @@
 }
 #endif
-                if ( (r_tgt_rsp_cpt.read() ==
-                     (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
-                   || r_xram_rsp_to_tgt_rsp_rerror.read() )
+                uint32_t last_word_idx = r_xram_rsp_to_tgt_rsp_word.read() + r_xram_rsp_to_tgt_rsp_length.read() - 1;
+                bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
+                bool     is_ll         = ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
+                bool     is_error      = r_xram_rsp_to_tgt_rsp_rerror.read();
+
+                if (((is_last_word or is_error) and not is_ll) or
+                     (r_tgt_rsp_key_sent.read() and     is_ll))
                 {
-                    r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
+                    // Last word sent in case of READ or second flit sent in case if LL
+                    r_tgt_rsp_key_sent        = false;
                     r_xram_rsp_to_tgt_rsp_req = false;
+                    r_tgt_rsp_fsm             = TGT_RSP_XRAM_IDLE;
                 }
                 else
                 {
-                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+                    if (is_ll)
+                    {
+                      r_tgt_rsp_key_sent = true;                     // Send second flit of ll
+                    }                                                                            
+                    else
+                    {                                                                       
+                      r_tgt_rsp_cpt      = r_tgt_rsp_cpt.read() + 1; // Send next word of read
+                    }
                 }
             }
@@ -5819,19 +5892,20 @@
         ////////////////////
         case ALLOC_DIR_CAS:
-        if ((( r_cas_fsm.read()        != CAS_DIR_REQ       )  &&
-             ( r_cas_fsm.read()        != CAS_DIR_LOCK      )  &&
-             ( r_cas_fsm.read()        != CAS_DIR_HIT_READ  )  &&
-             ( r_cas_fsm.read()        != CAS_DIR_HIT_WRITE )  &&
-             ( r_cas_fsm.read()        != CAS_BC_TRT_LOCK   )  &&
-             ( r_cas_fsm.read()        != CAS_BC_UPT_LOCK   )  &&
-             ( r_cas_fsm.read()        != CAS_MISS_TRT_LOCK )  &&
-             ( r_cas_fsm.read()        != CAS_UPT_LOCK      )  &&
-             ( r_cas_fsm.read()        != CAS_UPT_HEAP_LOCK ))
+        if ((( r_cas_fsm.read()        != CAS_DIR_REQ        )  &&
+             ( r_cas_fsm.read()        != CAS_DIR_LOCK       )  &&
+             ( r_cas_fsm.read()        != CAS_DIR_HIT_READ   )  &&
+             ( r_cas_fsm.read()        != CAS_DIR_HIT_COMPARE)  &&
+             ( r_cas_fsm.read()        != CAS_DIR_HIT_WRITE  )  &&
+             ( r_cas_fsm.read()        != CAS_BC_TRT_LOCK    )  &&
+             ( r_cas_fsm.read()        != CAS_BC_UPT_LOCK    )  &&
+             ( r_cas_fsm.read()        != CAS_MISS_TRT_LOCK  )  &&
+             ( r_cas_fsm.read()        != CAS_UPT_LOCK       )  &&
+             ( r_cas_fsm.read()        != CAS_UPT_HEAP_LOCK  ))
             ||
-            (( r_cas_fsm.read()        == CAS_UPT_HEAP_LOCK )  &&
-             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS    ))
+            (( r_cas_fsm.read()        == CAS_UPT_HEAP_LOCK  )  &&
+             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS     ))
             ||
-            (( r_cas_fsm.read()        == CAS_MISS_TRT_LOCK )  &&
-             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_CAS     )))
+            (( r_cas_fsm.read()        == CAS_MISS_TRT_LOCK  )  &&
+             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_CAS      )))
         {
           if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
@@ -6328,4 +6402,21 @@
 /////////////////////////////
 {
+#if MONITOR_MEMCACHE_FSM
+    p_read_fsm.write      (r_read_fsm.read());
+    p_write_fsm.write     (r_write_fsm.read());
+    p_xram_rsp_fsm.write  (r_xram_rsp_fsm.read());
+    p_cas_fsm.write       (r_cas_fsm.read());
+    p_cleanup_fsm.write   (r_cleanup_fsm.read());
+    p_alloc_heap_fsm.write(r_alloc_heap_fsm.read());
+    p_alloc_dir_fsm.write (r_alloc_dir_fsm.read());
+    p_alloc_trt_fsm.write (r_alloc_trt_fsm.read());
+    p_alloc_upt_fsm.write (r_alloc_upt_fsm.read());
+    p_tgt_cmd_fsm.write   (r_tgt_cmd_fsm.read());
+    p_tgt_rsp_fsm.write   (r_tgt_rsp_fsm.read());
+    p_ixr_cmd_fsm.write   (r_ixr_cmd_fsm.read());
+    p_ixr_rsp_fsm.write   (r_ixr_rsp_fsm.read());
+    p_init_cmd_fsm.write  (r_init_cmd_fsm.read());
+    p_init_rsp_fsm.write  (r_init_rsp_fsm.read());
+#endif
     ////////////////////////////////////////////////////////////
     // Command signals on the p_vci_ixr port
@@ -6455,19 +6546,32 @@
         p_vci_tgt.reop    = false;
         break;
+
       case TGT_RSP_READ:
-        p_vci_tgt.rspval   = true;
-        if( ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
-            && (r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1)) )
-          p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()-1].read();
-        else if ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
-          p_vci_tgt.rdata  = r_read_to_tgt_rsp_ll_key.read();
+      {
+        uint32_t last_word_idx = r_read_to_tgt_rsp_word.read() + r_read_to_tgt_rsp_length - 1;
+        bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
+        bool     is_ll         = ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
+
+        p_vci_tgt.rspval  = true;
+
+        if ( is_ll and not r_tgt_rsp_key_sent.read() )
+        {
+          // LL response first flit
+          p_vci_tgt.rdata = r_read_to_tgt_rsp_ll_key.read();
+        }
         else
-          p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
-        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
-        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
-        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
-        p_vci_tgt.rerror   = 0;
-        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
+        {
+          // LL response second flit or READ response
+          p_vci_tgt.rdata = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
+        }
+
+        p_vci_tgt.rsrcid  = r_read_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid  = r_read_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid  = r_read_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = (is_last_word and not is_ll) or (r_tgt_rsp_key_sent.read() and is_ll);
         break;
+      }
+
       case TGT_RSP_WRITE:
         /*if( ((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) )
@@ -6487,4 +6591,5 @@
         p_vci_tgt.reop     = true;
         break;
+
       case TGT_RSP_CLEANUP:
         p_vci_tgt.rspval   = true;
@@ -6496,4 +6601,5 @@
         p_vci_tgt.reop     = true;
         break;
+
       case TGT_RSP_CAS:
         p_vci_tgt.rspval   = true;
@@ -6505,19 +6611,32 @@
         p_vci_tgt.reop     = true;
         break;
+
       case TGT_RSP_XRAM:
-        p_vci_tgt.rspval   = true;
-        if( ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
-            && (r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length-1)) )
-          p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_ll_key.read();
-        else
-          p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
-        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
-        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
-        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
-        p_vci_tgt.rerror   = r_xram_rsp_to_tgt_rsp_rerror.read();
-        p_vci_tgt.reop     = (( r_tgt_rsp_cpt.read()
-              == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
-            || r_xram_rsp_to_tgt_rsp_rerror.read());
+      {
+        uint32_t last_word_idx = r_xram_rsp_to_tgt_rsp_word.read() + r_xram_rsp_to_tgt_rsp_length.read() - 1;
+        bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
+        bool     is_ll         = ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
+        bool     is_error      = r_xram_rsp_to_tgt_rsp_rerror.read();
+
+        p_vci_tgt.rspval  = true;
+
+        if( is_ll and not r_tgt_rsp_key_sent.read() ) {
+          // LL response first flit
+          p_vci_tgt.rdata = r_xram_rsp_to_tgt_rsp_ll_key.read();
+        }
+        else {
+          // LL response second flit or READ response
+          p_vci_tgt.rdata = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
+        }
+
+        p_vci_tgt.rsrcid  = r_xram_rsp_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid  = r_xram_rsp_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid  = r_xram_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror  = is_error;
+        p_vci_tgt.reop    = (((is_last_word or is_error) and not is_ll) or
+                              (r_tgt_rsp_key_sent.read() and     is_ll));
         break;
+      }
+
       case TGT_RSP_INIT:
         p_vci_tgt.rspval   = true;
