Index: /branches/RWT/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp
===================================================================
--- /branches/RWT/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 539)
+++ /branches/RWT/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 540)
@@ -2252,10 +2252,8 @@
         if(((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL) and not r_read_ll_done.read())   // access the global table ONLY when we have an LL cmd
         {
-          addr_t      nline      = m_nline[(addr_t)(m_cmd_read_addr_fifo.read())];
-          r_read_ll_key   = m_llsc_table.ll(nline);
-          //r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
+          r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
           /**//*std::cout << "MEMCACHE : from proc " << m_cmd_read_srcid_fifo.read()
-                        << " | @ " << std::hex << m_cmd_read_addr_fifo.read()
-                        << " | LL" << std::endl;*/
+                    << " | @ " << std::hex << m_cmd_read_addr_fifo.read()
+                    << " | LL" << std::endl;*/
           r_read_ll_done  = true;
         }
@@ -2275,5 +2273,4 @@
         // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
         bool cached_read = (m_cmd_read_pktid_fifo.read() & 0x1);
-
 
         if(entry.valid)    // hit
@@ -2870,10 +2867,18 @@
         r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
         r_write_word_index  = index;
-        r_write_word_count  = 1;
+        r_write_word_count  = 0;
         r_write_data[index] = m_cmd_write_data_fifo.read();
         r_write_srcid       = m_cmd_write_srcid_fifo.read();
         r_write_trdid       = m_cmd_write_trdid_fifo.read();
         r_write_pktid       = m_cmd_write_pktid_fifo.read();
-        r_write_pending_sc  = false;
+
+        if ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
+        {
+            assert( not m_cmd_write_eop_fifo.read() &&
+                    "MEMC ERROR in WRITE_IDLE state: "
+                    "invalid packet format for SC command");
+
+            r_write_sc_key = m_cmd_write_data_fifo.read();
+        }
 
         // initialize the be field for all words
@@ -2884,5 +2889,5 @@
         }
 
-        if (m_cmd_write_eop_fifo.read() or ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC))
+        if (m_cmd_write_eop_fifo.read())
         {
           r_write_fsm = WRITE_DIR_REQ;
@@ -2898,5 +2903,7 @@
           << " srcid = " << std::hex << m_cmd_write_srcid_fifo.read()
           << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
-          << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
+          << " / data = " << m_cmd_write_data_fifo.read() 
+          << " / pktid = " << m_cmd_write_pktid_fifo.read() 
+          << std::endl;
 #endif
       }
@@ -2910,29 +2917,44 @@
       {
 
-#if DEBUG_MEMC_WRITE
-if(m_debug)
-std::cout << "  <MEMC " << name()
-          << " WRITE_NEXT> Write another word in local buffer"
-          << std::endl;
-#endif
         m_cpt_write_cells++;
 
         // check that the next word is in the same cache line
-        assert( (m_nline[(addr_t)(r_write_address.read())] == 
-               m_nline[(addr_t)(m_cmd_write_addr_fifo.read())]) and
-        "MEMC ERROR in WRITE_NEXT state: Illegal write burst");
-
+        assert((m_nline[(addr_t)(r_write_address.read())] == 
+                m_nline[(addr_t)(m_cmd_write_addr_fifo.read())]) &&
+                "MEMC ERROR in WRITE_NEXT state: Illegal write burst");
+
+        size_t index = m_x[(addr_t)(m_cmd_write_addr_fifo.read())];
+        bool   is_sc = ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC);
+
+        // check that SC command has constant address
+        assert((not is_sc or (index == r_write_word_index)) &&
+                "MEMC ERROR in WRITE_NEXT state: "
+                "the address must be constant on a SC command");
+
+        // check that SC command has two flits
+        assert((not is_sc or m_cmd_write_eop_fifo.read()) &&
+                 "MEMC ERROR in WRITE_NEXT state: "
+                            "invalid packet format for SC command");
         // consume a word in the FIFO & write it in the local buffer
         cmd_write_fifo_get  = true;
-        size_t index        = r_write_word_index.read() + r_write_word_count.read();
 
         r_write_be[index]   = m_cmd_write_be_fifo.read();
         r_write_data[index] = m_cmd_write_data_fifo.read();
-        r_write_word_count  = r_write_word_count.read() + 1;
-
-        if(m_cmd_write_eop_fifo.read())
-        {
-          r_write_fsm = WRITE_DIR_REQ;
-        }
+
+        // the first flit of a SC command is the reservation key and
+        // therefore it must not be counted as a data to write
+        if (not is_sc)
+        {
+            r_write_word_count = r_write_word_count.read() + 1;
+        }
+
+        if (m_cmd_write_eop_fifo.read()) r_write_fsm = WRITE_DIR_REQ;
+
+#if DEBUG_MEMC_WRITE
+            if (m_debug)
+                std::cout << "  <MEMC " << name()
+                    << " WRITE_NEXT> Write another word in local buffer"
+                    << std::endl;
+#endif
       }
       break;
@@ -2946,37 +2968,26 @@
       if(r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE)
       {
-        ///////////////////////////////////////////////////////////////////////
-        // SC command handling
-        // We test the r_write_pending_sc register to know if we are returning
-        // from the WAIT state.
-        // In this case, the SC has already succeed and we cannot consume
-        // another time from the FIFO. Also, we don't have to test another
-        // time if the SC has succeed
-
-        addr_t nline = m_nline[(addr_t)(r_write_address.read())];
-        if(((r_write_pktid.read() & 0x7) == TYPE_SC) and not r_write_pending_sc.read())
-        {
-          if(not m_cmd_write_addr_fifo.rok()) break;
-  
-          assert(m_cmd_write_eop_fifo.read() and
-                 "Error in VCI_MEM_CACHE : "
-                 "invalid packet format for SC command");
-          //BUG LLSC
-          size_t index    = r_write_word_index.read();
-          bool sc_success = m_llsc_table.sc(nline    ,
-                                            r_write_data[index].read());
-  
-          //bool sc_success = m_llsc_table.sc(r_write_address.read()    ,
-          //                                  r_write_data[index].read());
-          // consume a word in the FIFO & write it in the local buffer
-          cmd_write_fifo_get  = true;
-          r_write_data[index] = m_cmd_write_data_fifo.read();
+
+        if( (r_write_pktid.read() & 0x7) == TYPE_SC ) 
+        {
+           // test address and key match of the SC command on the
+           // LL/SC table without removing reservation. The reservation
+           // will be erased after in this FSM. 
+          bool sc_success = m_llsc_table.check(r_write_address.read(),
+                                               r_write_sc_key.read());
+ 
           r_write_sc_fail     = not sc_success;
-          //WARNING: if the SC is a success, it might still fail at next cycle if the line is NCC
-          r_write_pending_sc  = true;
   
           if(not sc_success) r_write_fsm = WRITE_RSP;
           else               r_write_fsm = WRITE_DIR_LOCK;
-  
+
+
+         //std::cout << "  <MEMC " << name()
+         //          << " WRITE_DIR_REQ>  sc fail = " << not sc_success
+         //          << " / addr" << std::hex << r_write_address.read()
+         //          << " / key"  << std::hex << r_write_sc_key.read()
+         //          << " / srcid"  << std::hex << r_write_srcid.read()
+         //          << std::endl;
+
           break;
         }
@@ -2990,5 +3001,5 @@
         addr_t min = r_write_address.read();
         addr_t max = r_write_address.read() +
-                   ((r_write_word_count.read()-1) << L2(vci_param_int::B));
+                   ((r_write_word_count.read()) << L2(vci_param_int::B));
 #undef L2
         m_llsc_table.sw(min, max);
@@ -3039,5 +3050,5 @@
             else
             {
-             r_write_fsm = WRITE_DIR_HIT;
+              r_write_fsm = WRITE_DIR_HIT;
             }
           }
@@ -3051,8 +3062,8 @@
             {
               r_write_fsm = WRITE_IVT_LOCK_HIT_WB;
-              if(r_write_pktid.read() == TYPE_SC)
-              {
-                r_write_sc_fail = true;
-              }
+//            if(r_write_pktid.read() == TYPE_SC)
+//            {
+//              r_write_sc_fail = true;
+//            }
             }
           }
@@ -3067,8 +3078,8 @@
 {
 std::cout << "  <MEMC " << name() << " WRITE_DIR_LOCK> Check the directory: "
-          << " address = " << std::hex << r_write_address.read()
-          << " / hit = " << std::dec << entry.valid
-          << " / count = " << entry.count
-          << " / is_cnt = " << entry.is_cnt ;
+        << " address = " << std::hex << r_write_address.read()
+        << " / hit = " << std::dec << entry.valid
+        << " / count = " << entry.count
+        << " / is_cnt = " << entry.is_cnt ;
 if((r_write_pktid.read() & 0x7) == TYPE_SC)
 std::cout << " / SC access" << std::endl;
@@ -3079,61 +3090,61 @@
       break;
     }
-    ////////////////////
-    case WRITE_IVT_LOCK_HIT_WB:
-    {
-      if(r_alloc_ivt_fsm.read() == ALLOC_IVT_WRITE)
-      {
-
-        size_t index = 0;
-        bool   match_inval;
-        addr_t nline = m_nline[(addr_t)(r_write_address.read())];
-
-        //std::cout << "WRITE on NCC on line" << std::hex << nline << std::dec << std::endl;
-        //if there is a matched updt req, we should wait until it is over. Because 
-        //we need the lastest updt data.
-        match_inval = m_ivt.search_inval(nline, index);
-        
-        assert ((r_write_count.read() == 1) and "NCC to CC req without copy");
-        if(!match_inval and !r_write_to_cc_send_req.read())
-        {
-          r_write_to_cc_send_req = true;
-          r_write_to_cc_send_dest = r_write_copy;
-          r_write_to_cc_send_nline = nline;
-          r_write_to_cleanup_req = true;
-          r_write_to_cleanup_nline = nline;
-
-          m_ivt.set(false,  // it's an inval transaction
-                    false,     // it's not a broadcast
-                    true,      // it needs no read response
-                    false,     // no acknowledge required
-                    m_cmd_write_srcid_fifo.read(), //never read, used for debug
-                    m_cmd_write_trdid_fifo.read(), //never read, used for debug
-                    m_cmd_write_pktid_fifo.read(), //never read, used for debug
-                    nline,
-                    0x1, //Expect only one answer
-                    index);
-        }
-        r_write_fsm = WRITE_WAIT;
+  ////////////////////
+  case WRITE_IVT_LOCK_HIT_WB:
+  {
+    if(r_alloc_ivt_fsm.read() == ALLOC_IVT_WRITE)
+    {
+
+      size_t index = 0;
+      bool   match_inval;
+      addr_t nline = m_nline[(addr_t)(r_write_address.read())];
+
+      //std::cout << "WRITE on NCC on line" << std::hex << nline << std::dec << std::endl;
+      //if there is a matched updt req, we should wait until it is over. Because 
+      //we need the lastest updt data.
+      match_inval = m_ivt.search_inval(nline, index);
+      
+      assert ((r_write_count.read() == 1) and "NCC to CC req without copy");
+      if(!match_inval and !r_write_to_cc_send_req.read())
+      {
+        r_write_to_cc_send_req = true;
+        r_write_to_cc_send_dest = r_write_copy;
+        r_write_to_cc_send_nline = nline;
+        r_write_to_cleanup_req = true;
+        r_write_to_cleanup_nline = nline;
+
+        m_ivt.set(false,  // it's an inval transaction
+                  false,     // it's not a broadcast
+                  true,      // it needs no read response
+                  false,     // no acknowledge required
+                  m_cmd_write_srcid_fifo.read(), //never read, used for debug
+                  m_cmd_write_trdid_fifo.read(), //never read, used for debug
+                  m_cmd_write_pktid_fifo.read(), //never read, used for debug
+                  nline,
+                  0x1, //Expect only one answer
+                  index);
+      }
+      r_write_fsm = WRITE_WAIT;
 #if DEBUG_MEMC_WRITE
-        if(m_debug)
-        {
-          std::cout << "  <MEMC " << name() << " WRITE_IVT_LOCK_HIT_WB> get access to the UPT: "
-                    << " Inval requested =  " << (!match_inval and !r_write_to_cc_send_req.read())
-                    << std::endl;
-        }
-#endif
-      }
+      if(m_debug)
+      {
+        std::cout << "  <MEMC " << name() << " WRITE_IVT_LOCK_HIT_WB> get access to the UPT: "
+                  << " Inval requested =  " << (!match_inval and !r_write_to_cc_send_req.read())
+                  << std::endl;
+      }
+#endif
+    }
 #if DEBUG_MEMC_WRITE
-        if(m_debug)
-        {
-          std::cout << "  <MEMC " << name() << " WRITE_IVT_LOCK_HIT_WB> failed to access to the UPT: "
-                    << std::endl;
-        }
-#endif
-      break;
-    }
-
-    ///////////////////
-    case WRITE_DIR_HIT:
+      if(m_debug)
+      {
+        std::cout << "  <MEMC " << name() << " WRITE_IVT_LOCK_HIT_WB> failed to access to the UPT: "
+                  << std::endl;
+      }
+#endif
+    break;
+  }
+
+  ///////////////////
+  case WRITE_DIR_HIT:
     {
       assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE) and
@@ -3167,10 +3178,17 @@
       // (tests for sc requests)
       bool no_update = ((r_write_count.read() ==0) || //no need for coherency
-                        (owner && (r_write_count.read() ==1) && (r_write_pktid.read() != TYPE_SC)) || //writer is owner
-                        ((r_write_pktid.read() == TYPE_SC) && r_write_sc_fail.read())); //SC failed: no data update
+                        (owner && (r_write_count.read() ==1) && (r_write_pktid.read() != TYPE_SC))); //|| //writer is owner
+                       // ((r_write_pktid.read() == TYPE_SC) && r_write_sc_fail.read())); //SC failed: no data update
 
       // write data in the cache if no coherence transaction
-      if(no_update and ((r_write_pktid.read() != TYPE_SC) or !r_write_sc_fail.read()))
-      {
+      if(no_update)
+      {
+         // SC command but zero copies 
+         if ((r_write_pktid.read() & 0x7) == TYPE_SC)
+         {
+             m_llsc_table.sc(r_write_address.read(),
+                             r_write_sc_key.read());
+         }
+
         for(size_t word=0 ; word<m_words ; word++)
         {
@@ -3252,4 +3270,11 @@
         if(wok)       // write data in cache
         {
+
+          if ((r_write_pktid.read() & 0x7) == TYPE_SC)
+          {
+             m_llsc_table.sc(r_write_address.read(),
+                             r_write_sc_key.read());
+          }
+
           for(size_t word=0 ; word<m_words ; word++)
           {
@@ -3328,5 +3353,5 @@
       size_t min = r_write_word_index.read();
       size_t max = r_write_word_index.read() + r_write_word_count.read();
-      for(size_t i=min ; i<max ; i++) r_write_to_cc_send_data[i] = r_write_data[i];
+      for(size_t i=min ; i<=max ; i++) r_write_to_cc_send_data[i] = r_write_data[i];
 
       if((r_write_copy.read() != r_write_srcid.read()) or(r_write_pktid.read() == TYPE_SC) or r_write_copy_inst.read())
@@ -3494,10 +3519,19 @@
           r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
           r_write_word_index  = index;
-          r_write_word_count  = 1;
+          r_write_word_count  = 0;
           r_write_data[index] = m_cmd_write_data_fifo.read();
           r_write_srcid       = m_cmd_write_srcid_fifo.read();
           r_write_trdid       = m_cmd_write_trdid_fifo.read();
           r_write_pktid       = m_cmd_write_pktid_fifo.read();
-          r_write_pending_sc  = false;
+
+          if ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
+          {
+              assert( not m_cmd_write_eop_fifo.read() &&
+                      "MEMC ERROR in WRITE_RSP state: "
+                      "invalid packet format for SC command");
+      
+              r_write_sc_key = m_cmd_write_data_fifo.read();
+          } 
+
 
           // initialize the be field for all words
@@ -3505,8 +3539,8 @@
           {
             if(word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
-            else                 r_write_be[word] = 0x0;
+            else              r_write_be[word] = 0x0;
           }
 
-          if(m_cmd_write_eop_fifo.read() or ((m_cmd_write_pktid_fifo.read() & 0x7)  == TYPE_SC))
+          if( m_cmd_write_eop_fifo.read())
           {
             r_write_fsm = WRITE_DIR_REQ;
@@ -3526,5 +3560,8 @@
 {
     std::cout << "  <MEMC " << name() << " WRITE_RSP> Post a request to TGT_RSP FSM"
-              << " : rsrcid = " << std::hex << r_write_srcid.read() << std::endl;
+              << " : rsrcid = " << std::hex << r_write_srcid.read() 
+              << " : rpktid = " << std::hex << r_write_pktid.read() 
+              << " : sc_fail= " << std::hex << r_write_sc_fail.read()
+              << std::endl;
     if(m_cmd_write_addr_fifo.rok())
     {
@@ -3532,5 +3569,7 @@
                   << " srcid = " << std::hex << m_cmd_write_srcid_fifo.read()
                   << " / address = " << m_cmd_write_addr_fifo.read()
-                  << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
+                  << " / data = " << m_cmd_write_data_fifo.read() 
+                  << " / pktid = " << m_cmd_write_pktid_fifo.read() 
+                  << std::endl;
     }
 }
@@ -3573,4 +3612,19 @@
         bool    hit_write = m_trt.hit_write(m_nline[addr]);
         bool    wok       = not m_trt.full(wok_index);
+
+        // wait an empty entry in TRT
+        if(not hit_read and (not wok or hit_write))
+        {
+            r_write_fsm       = WRITE_WAIT;
+            m_cpt_trt_full++;
+            break;
+        }
+
+        if ((r_write_pktid.read() & 0x7) == TYPE_SC)
+        {
+            m_llsc_table.sc(r_write_address.read(),
+                            r_write_sc_key.read());
+        }
+
         //std::cout << "MEMCACHE : WRITE MISS at " << std::hex << (uint32_t)addr << std::dec << std::endl;
         if(hit_read)      // register the modified data in TRT
@@ -3579,16 +3633,15 @@
           r_write_fsm       = WRITE_MISS_TRT_DATA;
           m_cpt_write_miss++;
-        }
-        else if(wok and !hit_write)      // set a new entry in TRT
+          break;
+        }
+
+        if(wok and not hit_write)      // set a new entry in TRT
         {
           r_write_trt_index = wok_index;
           r_write_fsm       = WRITE_MISS_TRT_SET;
           m_cpt_write_miss++;
-        }
-        else    // wait an empty entry in TRT
-        {
-          r_write_fsm       = WRITE_WAIT;
-          m_cpt_trt_full++;
-        }
+          break;
+        }
+        assert(false && "VCI_MEM_CACHE ERROR: this part must not be reached");
         m_cpt_write_fsm_n_trt_lock++;
       }
@@ -3849,4 +3902,11 @@
 
       m_cache_directory.write(set, way, entry);
+
+      if ((r_write_pktid.read() & 0x7) == TYPE_SC)
+      {
+          m_llsc_table.sc(r_write_address.read(),
+                          r_write_sc_key.read());
+      }
+
 
 #if DEBUG_MEMC_WRITE
@@ -7309,5 +7369,5 @@
       {
         if(not p_dspin_m2p.read) break;
-        if(r_cc_send_cpt.read() == (r_write_to_cc_send_count.read()-1))
+        if(r_cc_send_cpt.read() == r_write_to_cc_send_count.read())
         {
           write_to_cc_send_fifo_get = true;
@@ -8693,5 +8753,5 @@
           r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
 
-         else if( r_config_fsm.read() == CONFIG_TRT_LOCK ) 
+        else if( r_config_fsm.read() == CONFIG_TRT_LOCK ) 
           r_alloc_trt_fsm = ALLOC_TRT_CONFIG;
         
@@ -9021,5 +9081,5 @@
           r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
 
-        if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
+        else if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
           r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
 
@@ -9820,5 +9880,5 @@
 
         p_dspin_m2p.write = true;
-        p_dspin_m2p.eop   = (r_cc_send_cpt.read() == (r_write_to_cc_send_count.read()-1));
+        p_dspin_m2p.eop   = (r_cc_send_cpt.read() == r_write_to_cc_send_count.read());
         p_dspin_m2p.data  = flit;
 
