Index: trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp
===================================================================
--- trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 524)
+++ trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 527)
@@ -2654,43 +2654,51 @@
             case WRITE_IDLE:  // copy first word of a write burst in local buffer
                 {
-                    if (m_cmd_write_addr_fifo.rok())
-                    {
-                        // consume a word in the FIFO & write it in the local buffer
-                        cmd_write_fifo_get  = true;
-                        size_t index        = m_x[(addr_t)(m_cmd_write_addr_fifo.read())];
-
-                        r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
-                        r_write_word_index  = index;
-                        r_write_word_count  = 1;
-                        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;
-
-                        // initialize the be field for all words
-                        for(size_t word=0 ; word<m_words ; word++)
-                        {
-                            if (word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
-                            else              r_write_be[word] = 0x0;
-                        }
-
-                        if (m_cmd_write_eop_fifo.read() or ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC))
-                        {
-                            r_write_fsm = WRITE_DIR_REQ;
-                        }
-                        else
-                        {
-                            r_write_fsm = WRITE_NEXT;
-                        }
+                    if (not m_cmd_write_addr_fifo.rok()) break;
+
+                    // consume a word in the FIFO & write it in the local buffer
+                    cmd_write_fifo_get  = true;
+                    size_t index        = m_x[(addr_t)(m_cmd_write_addr_fifo.read())];
+
+                    r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
+                    r_write_word_index  = index;
+                    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();
+
+                    // if SC command, get the SC key
+                    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
+                    for(size_t word=0 ; word<m_words ; word++)
+                    {
+                        if (word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
+                        else               r_write_be[word] = 0x0;
+                    }
+
+                    if (m_cmd_write_eop_fifo.read())
+                    {
+                        r_write_fsm = WRITE_DIR_REQ;
+                    }
+                    else
+                    {
+                        r_write_fsm = WRITE_NEXT;
+                    }
 
 #if DEBUG_MEMC_WRITE
-                        if (m_debug)
-                            std::cout << "  <MEMC " << name() << " WRITE_IDLE> Write request "
-                                << " 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;
-#endif
-                    }
+                    if (m_debug)
+                        std::cout << "  <MEMC " << name() << " WRITE_IDLE> Write request "
+                            << " 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;
+#endif
                     break;
                 }
@@ -2698,80 +2706,79 @@
             case WRITE_NEXT:  // copy next word of a write burst in local buffer
                 {
-                    if (m_cmd_write_addr_fifo.rok())
-                    {
+                    if (not m_cmd_write_addr_fifo.rok()) break;
+
+                    // 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())]) &&
+                            "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;
+
+                    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;
 
 #if DEBUG_MEMC_WRITE
-                        if (m_debug)
-                            std::cout << "  <MEMC " << name()
-                                << " WRITE_NEXT> Write another word in local buffer"
-                                << std::endl;
-#endif
-
-                        // 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");
-
-                        // 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;
-                    }
+                    if (m_debug)
+                        std::cout << "  <MEMC " << name()
+                            << " WRITE_NEXT> Write another word in local buffer"
+                            << std::endl;
+#endif
                     break;
                 }
                 ///////////////////
-            case WRITE_DIR_REQ:    // Get the lock to the directory
-                // and access the llsc_global_table
-                {
-                    if (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE )
-                    {
-                        if (((r_write_pktid.read() & 0x7) == TYPE_SC) and not r_write_pending_sc.read())
-                        {
-                            // We enter here if it is a new SC command
-                            // If r_write_pending_sc is set the SC is not new and has already been tested
-
-                            if (not m_cmd_write_addr_fifo.rok()) break;
-
-                            assert( m_cmd_write_eop_fifo.read() and
-                                    "MEMC ERROR in WRITE_DIR_REQ state: invalid packet format for SC command");
-
-                            size_t index    = r_write_word_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();
-                            r_write_sc_fail     = not sc_success;
-                            r_write_pending_sc  = true;
-
-                            if (not sc_success) r_write_fsm = WRITE_RSP;
-                            else                r_write_fsm = WRITE_DIR_LOCK;
-                        }
-                        else
-                        {
-                            // We enter here if it is a SW command or an already tested SC command 
+            case WRITE_DIR_REQ: // Get the lock to the directory
+                                // and access the llsc_global_table
+                {
+                    if (r_alloc_dir_fsm.read() != ALLOC_DIR_WRITE ) break;
+
+                    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;
+
+                        if (not sc_success) r_write_fsm = WRITE_RSP;
+                        else                r_write_fsm = WRITE_DIR_LOCK;
+                    }
+                    else
+                    {
+                        // write burst 
 #define L2 soclib::common::uint32_log2
-                            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));
+                        addr_t min = r_write_address.read();
+                        addr_t max = r_write_address.read() +
+                                    (r_write_word_count.read() << L2(vci_param_int::B));
 #undef L2
 
-                            m_llsc_table.sw(min, max);
-
-                            r_write_fsm = WRITE_DIR_LOCK;
-                        }
+                        m_llsc_table.sw(min, max);
+
+                        r_write_fsm = WRITE_DIR_LOCK;
+                    }
 
 #if DEBUG_MEMC_WRITE
-                        if (m_debug)
-                            std::cout << "  <MEMC " << name() << " WRITE_DIR_REQ> Requesting DIR lock "
-                                << std::endl;
-#endif
-                    }
+                    if (m_debug)
+                        std::cout << "  <MEMC " << name() << " WRITE_DIR_REQ> Requesting DIR lock "
+                            << std::endl;
+#endif
                     break;
                 }
@@ -2798,5 +2805,5 @@
 
                         if (entry.is_cnt and entry.count) r_write_fsm = WRITE_BC_DIR_READ;
-                        else                             r_write_fsm = WRITE_DIR_HIT;
+                        else                              r_write_fsm = WRITE_DIR_HIT;
                     }
                     else  // miss
@@ -2851,10 +2858,17 @@
                     // no_update is true when there is no need for coherence transaction
                     bool no_update = ( (r_write_count.read() == 0) or
-                            (owner and (r_write_count.read() ==1) and 
-                             (r_write_pktid.read() != TYPE_SC)));
+                            (owner and (r_write_count.read() == 1) and 
+                             ((r_write_pktid.read() & 0x7) != TYPE_SC)));
 
                     // write data in the cache if no coherence transaction
                     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++)
                         {
@@ -2867,5 +2881,5 @@
                     }
 
-                    if (owner and not no_update and(r_write_pktid.read() != TYPE_SC))
+                    if (owner and not no_update and ((r_write_pktid.read() & 0x7) != TYPE_SC))
                     {
                         r_write_count = r_write_count.read() - 1;
@@ -2936,4 +2950,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++)
                             {
@@ -2999,8 +3020,9 @@
                     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())
+                       ((r_write_pktid.read() & 0x7) == TYPE_SC)      or
+                         r_write_copy_inst.read())
                     {
                         // put the first srcid in the fifo
@@ -3060,5 +3082,6 @@
                     // put the next srcid in the fifo
                     if ((entry.owner.srcid != r_write_srcid.read()) or 
-                            (r_write_pktid.read() == TYPE_SC) or entry.owner.inst)   
+                       ((r_write_pktid.read() & 0x7) == TYPE_SC)    or
+                         entry.owner.inst)
                     {
                         dec_upt_counter                = false;
@@ -3140,5 +3163,5 @@
                 // a new request in the write FIFO
                 {
-                    if (!r_write_to_tgt_rsp_req.read())
+                    if (not r_write_to_tgt_rsp_req.read())
                     {
                         // post the request to TGT_RSP_FSM
@@ -3150,5 +3173,9 @@
 
                         // try to get a new write request from the FIFO
-                        if (m_cmd_write_addr_fifo.rok())
+                        if (not m_cmd_write_addr_fifo.rok())
+                        {
+                            r_write_fsm = WRITE_IDLE;
+                        }
+                        else
                         {
                             // consume a word in the FIFO & write it in the local buffer
@@ -3158,10 +3185,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 SC command, get the SC key
+                            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
@@ -3169,8 +3205,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;
@@ -3180,8 +3216,4 @@
                                 r_write_fsm = WRITE_NEXT;
                             }
-                        }
-                        else
-                        {
-                            r_write_fsm = WRITE_IDLE;
                         }
 
@@ -3221,21 +3253,38 @@
                         bool    wok       = not m_trt.full(wok_index);
 
-                        if (hit_read)      // register the modified data in TRT
+                        // 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());
+                        }
+
+                        // register the modified data in TRT
+                        if (hit_read)
                         {
                             r_write_trt_index = hit_index;
                             r_write_fsm       = WRITE_MISS_TRT_DATA;
                             m_cpt_write_miss++;
-                        }
-                        else if (wok and !hit_write)      // set a new entry in TRT
+                            break;
+                        }
+
+                        // set a new entry in TRT
+                        if (wok and not hit_write)
                         {
                             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");
                     }
                     break;
@@ -3477,4 +3526,10 @@
 
                     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
@@ -6284,5 +6339,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;
@@ -8306,5 +8361,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;
 
