Index: trunk/modules/vci_cc_vcache_wrapper_v4/caba/metadata/vci_cc_vcache_wrapper_v4.sd
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper_v4/caba/metadata/vci_cc_vcache_wrapper_v4.sd	(revision 290)
+++ trunk/modules/vci_cc_vcache_wrapper_v4/caba/metadata/vci_cc_vcache_wrapper_v4.sd	(revision 291)
@@ -16,4 +16,5 @@
 	         Uses('caba:generic_fifo'),
 	         Uses('caba:generic_cam'),
+	         Uses('caba:generic_llsc_local_table'),
 	         Uses('caba:generic_cache', 
                        addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', 
Index: trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/include/vci_cc_vcache_wrapper_v4.h
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/include/vci_cc_vcache_wrapper_v4.h	(revision 290)
+++ trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/include/vci_cc_vcache_wrapper_v4.h	(revision 291)
@@ -37,4 +37,5 @@
 #include "generic_cache.h"
 #include "generic_cam.h"
+#include "generic_llsc_local_table.h"
 #include "vci_initiator.h"
 #include "vci_target.h"
@@ -60,4 +61,5 @@
 
     typedef typename vci_param::addr_t  paddr_t;
+    typedef typename vci_param::data_t  vci_data_t;
     typedef typename vci_param::be_t    vci_be_t;
     typedef typename vci_param::srcid_t vci_srcid_t;
@@ -124,6 +126,7 @@
         DCACHE_MISS_WAIT,           
         DCACHE_MISS_UPDT,           
-        // handling processor unc and sc requests
+        // handling processor unc, ll and sc requests
         DCACHE_UNC_WAIT,            
+        DCACHE_LL_WAIT,            
         DCACHE_SC_WAIT,            
         // handling coherence requests
@@ -142,4 +145,6 @@
         CMD_DATA_UNC,
         CMD_DATA_WRITE,
+        CMD_DATA_LL,
+        CMD_DATA_SC,
         CMD_DATA_CAS, 
     };
@@ -151,4 +156,5 @@
         RSP_DATA_MISS,
         RSP_DATA_UNC,
+        RSP_DATA_LL,
         RSP_DATA_WRITE,
     };
@@ -400,7 +406,10 @@
     sc_signal<bool>         r_dcache_vci_unc_req;       // uncacheable read request
     sc_signal<bool>         r_dcache_vci_unc_be;        // uncacheable read byte enable
-    sc_signal<bool>         r_dcache_vci_sc_req;        // atomic write request (Compare & swap)
-    sc_signal<uint32_t>     r_dcache_vci_sc_old;        // previous data value for an atomic write
-    sc_signal<uint32_t>     r_dcache_vci_sc_new;        // new data value for an atomic write
+    sc_signal<bool>         r_dcache_vci_cas_req;       // atomic write request CAS
+    sc_signal<uint32_t>     r_dcache_vci_cas_old;       // previous data value for an atomic write CAS
+    sc_signal<uint32_t>     r_dcache_vci_cas_new;       // new data value for an atomic write CAS
+    sc_signal<bool>         r_dcache_vci_ll_req;        // atomic read request LL
+    sc_signal<bool>         r_dcache_vci_sc_req;        // atomic write request SC
+    sc_signal<vci_data_t>   r_dcache_vci_sc_data;       // SC data (command)
 
     // register used for XTN inval
@@ -425,4 +434,10 @@
     // dcache flush handling
     sc_signal<size_t>       r_dcache_flush_count;	    // slot counter used for cache flush
+
+    // ll rsp handling
+    sc_signal<size_t>       r_dcache_ll_rsp_count;	    // flit counter used for ll rsp
+
+    // sc cmd handling
+    sc_signal<vci_data_t>   r_sc_key;                   // SC key returned by local table
 
     // used by the TLB miss sub-fsm
@@ -438,9 +453,4 @@
     sc_signal<size_t>       r_dcache_tlb_set;		    // selected set in tlb    
 
-    // LL reservation handling
-    sc_signal<bool>         r_dcache_ll_valid;		    // valid LL reservation
-    sc_signal<uint32_t>     r_dcache_ll_data;		    // LL reserved data
-    sc_signal<paddr_t>      r_dcache_ll_vaddr;		    // LL reserved address 
-                            
     // ITLB and DTLB invalidation
     sc_signal<paddr_t>      r_dcache_tlb_inval_line;	// line index 
@@ -517,4 +527,16 @@
     GenericTlb<paddr_t>       	r_itlb;
     GenericTlb<paddr_t>     	r_dtlb;
+
+    //////////////////////////////////////////////////////////////////
+    // llsc local registration table
+    //////////////////////////////////////////////////////////////////
+
+    #define LLSCLocalTable GenericLLSCLocalTable<8000, 1, paddr_t, vci_trdid_t, vci_data_t>
+    LLSCLocalTable r_llsc_table;                    // The llsc local registration table
+
+    typename LLSCLocalTable::in_t   table_in    ;   // llsc local table input signals
+    typename LLSCLocalTable::out_t  table_out   ;   // llsc local table output signals
+
+    #undef LLSCLocalTable
 
     ////////////////////////////////
Index: trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp	(revision 290)
+++ trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp	(revision 291)
@@ -97,4 +97,5 @@
 
         "DCACHE_UNC_WAIT",   
+        "DCACHE_LL_WAIT",   
         "DCACHE_SC_WAIT",   
 
@@ -112,4 +113,6 @@
         "CMD_DATA_UNC",     
         "CMD_DATA_WRITE", 
+        "CMD_DATA_LL",
+        "CMD_DATA_SC",
         "CMD_DATA_CAS", 
     };
@@ -120,4 +123,5 @@
         "RSP_DATA_MISS",             
         "RSP_DATA_UNC",              
+        "RSP_DATA_LL",
         "RSP_DATA_WRITE",     
     };
@@ -277,7 +281,10 @@
       r_dcache_vci_unc_req("r_dcache_vci_unc_req"),
       r_dcache_vci_unc_be("r_dcache_vci_unc_be"),
+      r_dcache_vci_cas_req("r_dcache_vci_cas_req"),
+      r_dcache_vci_cas_old("r_dcache_vci_cas_old"),
+      r_dcache_vci_cas_new("r_dcache_vci_cas_new"),
+      r_dcache_vci_ll_req("r_dcache_vci_ll_req"),
       r_dcache_vci_sc_req("r_dcache_vci_sc_req"),
-      r_dcache_vci_sc_old("r_dcache_vci_sc_old"),
-      r_dcache_vci_sc_new("r_dcache_vci_sc_new"),
+      r_dcache_vci_sc_data("r_dcache_vci_sc_data"),
 
       r_dcache_xtn_way("r_dcache_xtn_way"),
@@ -307,8 +314,4 @@
       r_dcache_tlb_way("r_dcache_tlb_way"),
       r_dcache_tlb_set("r_dcache_tlb_set"),
-
-      r_dcache_ll_valid("r_dcache_ll_valid"),
-      r_dcache_ll_data("r_dcache_ll_data"),
-      r_dcache_ll_vaddr("r_dcache_ll_vaddr"),
 
       r_dcache_tlb_inval_line("r_dcache_tlb_inval_line"),
@@ -666,4 +669,5 @@
 /////////////////////////
 {
+    #define LLSCLocalTable GenericLLSCLocalTable<8000, 1, paddr_t, vci_trdid_t, vci_data_t>
     if ( not p_resetn.read() ) 
     {
@@ -714,11 +718,10 @@
         r_dcache_vci_miss_req      = false;
         r_dcache_vci_unc_req       = false;
+        r_dcache_vci_cas_req       = false;
+        r_dcache_vci_ll_req        = false;
         r_dcache_vci_sc_req        = false;
 
         // No uncacheable write pending
         r_dcache_pending_unc_write = false;
-
-        // No LL reservation
-	    r_dcache_ll_valid          = false;
 
         // No processor XTN request pending
@@ -854,4 +857,7 @@
         for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_cmd_cleanup [i]   = 0;
         for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_rsp_cleanup [i]   = 0;
+
+        // init the llsc local registration table
+        r_llsc_table.init();
 
         return;
@@ -1936,12 +1942,15 @@
     // 4/ Atomic instructions LL/SC
     //    The LL/SC address can be cacheable or non cacheable.
-    //    The reservation registers (r_dcache_ll_valid, r_dcache_ll_vaddr and
-    //    r_dcache_ll_data are stored in the L1 cache controller, and not in the 
-    //    memory controller. 
-    //    - LL requests from the processor are transmitted as standard VCI
-    //      READ transactions (one word / one line, depending on the cacheability).
+    //    The llsc_local_table holds a registration for an active LL/SC
+    //    operation (with an address, a registration key, an aging counter and a
+    //    valid bit).
+    //    - LL requests from the processor are transmitted as a one flit VCI
+    //      CMD_LOCKED_READ transaction with TYPE_LL as PKTID value. PLEN must
+    //      be 8 as the response is 2 flits long (data and registration key) 
     //    - SC requests from the processor are systematically transmitted to the 
-    //      memory cache as Compare&swap requests (both the data value stored in the
-    //      r_dcache_ll_data register and the new value). 
+    //      memory cache as 2 flits VCI CMD_NOP (or CMD_STORE_COND)
+    //      transactions, with TYPE_SC as PKTID value (the first flit contains
+    //      the registration key, the second flit contains the data to write in
+    //      case of success).
     //      The cache is not updated, as this is done in case of success by the
     //      coherence transaction.
@@ -1974,8 +1983,12 @@
     m_drsp.error = false;
     m_drsp.rdata = 0;
+    
+    // keep track of the local llsc table access and perform a NOP access if
+    // necessary at the end of the DCACHE transition function
+    bool llsc_local_table_access_done = false;
 
     switch ( r_dcache_fsm.read() ) 
     {
-    case DCACHE_IDLE:	// There is 8 conditions to exit the IDLE state :
+    case DCACHE_IDLE:	// There are 9 conditions to exit the IDLE state :
 						// 1) Dirty bit update (processor)    => DCACHE_DIRTY_GET_PTE
 						// 2) Coherence request (TGT FSM)     => DCACHE_CC_CHECK 
@@ -1985,5 +1998,6 @@
 						// 6) Cacheable read miss (processor) => DCACHE_MISS_VICTIM
 						// 7) Uncacheable read (processor)    => DCACHE_UNC_WAIT 
-						// 8) SC access (processor)           => DCACHE_SC_WAIT
+						// 8) LL access (processor)           => DCACHE_LL_WAIT
+						// 9) SC access (processor)           => DCACHE_SC_WAIT
                         //
                         // The dtlb is unconditionally accessed to translate the
@@ -2150,10 +2164,12 @@
         //    dtlb miss. If dtlb is OK, It enters the three stage pipe-line (fully 
         //    handled by the IDLE state), and the processor request is acknowledged.
-        // 2) A processor READ or LL request generate a simultaneouss access to
+        // 2) A processor READ request generate a simultaneouss access to
         //    both dcache data and dcache directoty, using speculative PPN, but
         //    is delayed if the write pipe-line is not empty.
         //    In case of miss, we wait the VCI response in DCACHE_UNC_WAIT or 
         //    DCACHE_MISS_WAIT states.
-        // 3) A processor SC request is delayed until the write pipe-line is empty.
+        // 3) A processor LL request generate a VCI LL transaction. We wait for
+        //    the response in DCACHE_LL_WAIT state.
+        // 4) A processor SC request is delayed until the write pipe-line is empty.
         //    A VCI SC transaction is launched, and we wait the VCI response in
         //    DCACHE_SC_WAIT state. It can be completed by a "long write" if the 
@@ -2535,5 +2551,5 @@
                     r_dcache_p0_cacheable      = cacheable;
 
-                    // READ or LL request
+                    // READ request
                     // The read requests are taken only if the write pipe-line is empty.
                     // If dcache hit, dtlb hit, and speculative PPN OK, data in one cycle.
@@ -2541,7 +2557,5 @@
                     // If dcache miss, we go to DCACHE_MISS_VICTIM state.
                     // If uncacheable, we go to DCACHE_UNC_WAIT state.
-                    // In case of LL, the LL registration is done when the data is returned:
-                    // in DCACHE_IDLE if cacheable / in DCACHE_UNC_WAIT if uncacheable 
-                    if ( ((m_dreq.type == iss_t::DATA_READ) or (m_dreq.type == iss_t::DATA_LL)) 
+                    if ( ((m_dreq.type == iss_t::DATA_READ)) 
                         and not r_dcache_p0_valid.read() and not r_dcache_p1_valid.read() )
                     { 
@@ -2581,12 +2595,4 @@
                                 m_drsp.valid   = true;
                                 m_drsp.rdata   = cache_rdata;
-
-                                // makes reservation in case of LL
-                                if ( m_dreq.type == iss_t::DATA_LL )
-                                {
-                                    r_dcache_ll_valid = true;
-                                    r_dcache_ll_vaddr = m_dreq.addr;
-                                    r_dcache_ll_data  = cache_rdata;
-                                }
 #if DEBUG_DCACHE
 if ( m_debug_dcache_fsm )
@@ -2606,5 +2612,33 @@
 
                         r_dcache_p0_valid = false;
-                    } // end READ or LL
+                    } // end READ
+
+                    // LL request
+                    // The LL requests are taken only if the write pipe-line is empty.
+                    // We request an LL transaction to CMD FSM and go to
+                    // DCACHE_LL_WAIT state, that will return the response to
+                    // the processor.
+                    else if ( ((m_dreq.type == iss_t::DATA_LL))
+                        and not r_dcache_p0_valid.read() and not r_dcache_p1_valid.read() )
+                    {
+                        // prepare llsc local table access
+                        table_in.cmd       = LLSCLocalTable::LL_CMD ;
+                        table_in.address   = paddr;
+                        // access the table
+                        r_llsc_table.exec(table_in, table_out);
+                        llsc_local_table_access_done = true;
+                        // test if the table is done
+                        if(!table_out.done)
+                        {
+                            r_dcache_p0_valid     = false;
+                            break;
+                        }
+                        // request an LL CMD and go to DCACHE_LL_WAIT state
+                        r_dcache_vci_ll_req   = true;
+                        r_dcache_ll_rsp_count = 0;
+                        r_dcache_p0_valid     = false;
+                        r_dcache_vci_paddr    = paddr;
+                        r_dcache_fsm          = DCACHE_LL_WAIT;
+                    }// end LL
 
                     // WRITE request:
@@ -2640,4 +2674,13 @@
 m_cpt_data_write++;
 #endif
+                            table_in.cmd       = LLSCLocalTable::SW_CMD ;
+                            table_in.address   = paddr;
+                            r_llsc_table.exec(table_in, table_out)  ;
+                            llsc_local_table_access_done = true;
+                            if(!table_out.done)
+                            {
+                                r_dcache_p0_valid     = false;
+                                break;
+                            }
                             m_drsp.valid      = true;
                             m_drsp.rdata      = 0;
@@ -2648,59 +2691,63 @@
                     // SC request:
                     // The SC requests are taken only if the write pipe-line is empty.
-                    // - if there is no valid registered LL, we just return rdata = 1 
-                    //   (atomic access failed) and the SC transaction is completed.
-                    // - if a valid LL reservation (with the same address) is registered, 
-                    //   we test if a DIRTY bit update is required.
-                    //   If the TLB is activated and the PTE Dirty bit is not set, we stall 
-                    //   the processor and set the Dirty bit before handling the write request. 
-                    //   If we don't need to set the Dirty bit, we request a SC transaction 
-                    //   to CMD FSM and go to DCACHE_SC_WAIT state, that will return 
-                    //   the response to the processor. 
-                    //   We don't check a possible write hit in dcache, as the cache update 
-                    //   is done by the coherence transaction induced by the SC...
+                    //  We test if a DIRTY bit update is required.
+                    //  If the TLB is activated and the PTE Dirty bit is not set, we stall 
+                    //  the processor and set the Dirty bit before handling the write request. 
+                    //  If we don't need to set the Dirty bit, we request a SC transaction 
+                    //  to CMD FSM and go to DCACHE_SC_WAIT state, that will return 
+                    //  the response to the processor. 
+                    //  We don't check a possible write hit in dcache, as the cache update 
+                    //  is done by the coherence transaction induced by the SC...
                     else if ( ( m_dreq.type == iss_t::DATA_SC )
                         and not r_dcache_p0_valid.read() and not r_dcache_p1_valid.read() )
                     {
-                        if ( (r_dcache_ll_vaddr.read() != m_dreq.addr)
-                             or not r_dcache_ll_valid.read() ) 	// no valid registered LL
-                        { 
+                        if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
+                              and not tlb_flags.d )			// Dirty bit must be set
+                        {
+                            // The PTE physical address is obtained from the nline value (dtlb),
+                            // and the word index (virtual address)
+                            if ( tlb_flags.b )	// PTE1
+                            {
+                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
+                                                       (paddr_t)((m_dreq.addr>>19) & 0x3c);
+                            }
+                            else			// PTE2
+                            {
+                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
+                                                       (paddr_t)((m_dreq.addr>>9) & 0x38);
+                            }
+                            r_dcache_fsm           = DCACHE_DIRTY_GET_PTE;
+                        }
+                        else					// SC request accepted
+                        {
 #ifdef INSTRUMENTATION
 m_cpt_data_sc++;
 #endif
-                            m_drsp.valid        = true;
-                            m_drsp.rdata        = 1;
-                            r_dcache_ll_valid   = false;
-                        }
-                        else					// valid registered LL
-                        {
-                            if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
-                                  and not tlb_flags.d )			// Dirty bit must be set
+                            // prepare llsc local table access
+                            table_in.cmd       = LLSCLocalTable::SC_CMD ;
+                            table_in.address   = paddr;
+                            // access the table
+                            r_llsc_table.exec(table_in, table_out)  ;
+                            llsc_local_table_access_done = true;
+                            // test if the table is done
+                            if(!table_out.done)
                             {
-                                // The PTE physical address is obtained from the nline value (dtlb),
-                                // and the word index (virtual address)
-                                if ( tlb_flags.b )	// PTE1
-                                {
-                                    r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
-                                                           (paddr_t)((m_dreq.addr>>19) & 0x3c);
-                                }
-                                else			// PTE2
-                                {
-                                    r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
-                                                           (paddr_t)((m_dreq.addr>>9) & 0x38);
-                                }
-                                r_dcache_fsm           = DCACHE_DIRTY_GET_PTE;
+                                r_dcache_p0_valid     = false;
+                                break;
                             }
-                            else					// SC request accepted
+                            // test for a local fail
+                            if(table_out.hit)
                             {
-#ifdef INSTRUMENTATION
-m_cpt_data_sc++;
-#endif
-      
-                                r_dcache_vci_paddr  = paddr;
-                                r_dcache_vci_sc_req = true;
-                                r_dcache_vci_sc_old = r_dcache_ll_data.read();
-                                r_dcache_vci_sc_new = m_dreq.wdata;
-                                r_dcache_ll_valid   = false;
-                                r_dcache_fsm        = DCACHE_SC_WAIT;
+                                // request an SC CMD and go to DCACHE_SC_WAIT state
+                                r_sc_key             = table_out.key;
+                                r_dcache_vci_paddr   = paddr;
+                                r_dcache_vci_sc_req  = true;
+                                r_dcache_vci_sc_data = m_dreq.wdata;
+                                r_dcache_fsm         = DCACHE_SC_WAIT;
+                            }
+                            else // local fail
+                            {
+	                            m_drsp.valid = true;
+	                            m_drsp.rdata = 0x1;
                             }
                         }
@@ -2984,6 +3031,6 @@
             {
                 pt_updt                = true;
-                r_dcache_vci_sc_old    = pte;
-                r_dcache_vci_sc_new    = pte | PTE_L_MASK;
+                r_dcache_vci_cas_old    = pte;
+                r_dcache_vci_cas_new    = pte | PTE_L_MASK;
                 pte                    = pte | PTE_L_MASK;
                 r_dcache_tlb_pte_flags = pte;
@@ -2995,6 +3042,6 @@
             {
                 pt_updt                = true;
-                r_dcache_vci_sc_old    = pte;
-                r_dcache_vci_sc_new    = pte | PTE_R_MASK;
+                r_dcache_vci_cas_old    = pte;
+                r_dcache_vci_cas_new    = pte | PTE_R_MASK;
                 pte                    = pte | PTE_R_MASK;
                 r_dcache_tlb_pte_flags = pte;
@@ -3219,6 +3266,6 @@
             {
                 pt_updt                = true;
-                r_dcache_vci_sc_old    = pte_flags;
-                r_dcache_vci_sc_new    = pte_flags | PTE_L_MASK;
+                r_dcache_vci_cas_old    = pte_flags;
+                r_dcache_vci_cas_new    = pte_flags | PTE_L_MASK;
                 pte_flags              = pte_flags | PTE_L_MASK;
 		        r_dcache_tlb_pte_flags = pte_flags;
@@ -3230,6 +3277,6 @@
             {
                 pt_updt                = true;
-                r_dcache_vci_sc_old    = pte_flags;
-                r_dcache_vci_sc_new    = pte_flags | PTE_R_MASK;
+                r_dcache_vci_cas_old    = pte_flags;
+                r_dcache_vci_cas_new    = pte_flags | PTE_R_MASK;
                 pte_flags              = pte_flags | PTE_R_MASK;
 		        r_dcache_tlb_pte_flags = pte_flags;
@@ -3311,7 +3358,17 @@
 }
 #endif
-        // r_dcache_vci_sc_old & r_dcache_vci_sc_new registers are already set
-        r_dcache_vci_paddr   = r_dcache_tlb_paddr.read();
-        r_dcache_vci_sc_req  = true;
+        // r_dcache_vci_cas_old & r_dcache_vci_cas_new registers are already set
+        r_dcache_vci_paddr = r_dcache_tlb_paddr.read();
+        // prepare llsc local table access
+        table_in.cmd       = LLSCLocalTable::SW_CMD;
+        table_in.address   = r_dcache_tlb_paddr.read();
+        // access the table
+        r_llsc_table.exec(table_in, table_out);
+        llsc_local_table_access_done = true;
+        // test if the table is done
+        if(!table_out.done)
+            break;
+        // 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;
@@ -3921,6 +3978,6 @@
             r_mmu_dbvar          = m_dreq.addr;
             r_vci_rsp_data_error = false;
-            m_drsp.error           = true;
-            m_drsp.valid           = true;
+            m_drsp.error         = true;
+            m_drsp.valid         = true;
             r_dcache_fsm         = DCACHE_IDLE;
             break;
@@ -3935,20 +3992,12 @@
             if ( m_dreq.valid and (m_dreq.addr == r_dcache_p0_vaddr.read()) )
             {
-	            m_drsp.valid          = true;
-	            m_drsp.rdata          = r_vci_rsp_fifo_dcache.read();
-
-                // makes reservation in case of LL
-                if ( m_dreq.type == iss_t::DATA_LL )
-                {
-                    r_dcache_ll_valid = true;
-                    r_dcache_ll_data  = r_vci_rsp_fifo_dcache.read();
-                    r_dcache_ll_vaddr = m_dreq.addr;
-                }
+	            m_drsp.valid        = true;
+	            m_drsp.rdata        = r_vci_rsp_fifo_dcache.read();
             }
 	    }	
         break;
     }
-    ////////////////////
-    case DCACHE_SC_WAIT:	// waiting VCI response after a processor SC request
+    /////////////////////
+    case DCACHE_LL_WAIT:
     {
         // external coherence request
@@ -3960,5 +4009,5 @@
         }
 
-        if ( r_vci_rsp_data_error.read() ) 		// bus error
+        if ( r_vci_rsp_data_error.read() ) 	// bus error
         {
             r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
@@ -3970,11 +4019,60 @@
             break;
         }
-	else if ( r_vci_rsp_fifo_dcache.rok() )     	// response available
-	{
-            vci_rsp_fifo_dcache_get = true;     
-	    m_drsp.valid            = true;
+	    else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
+	    {
+            // consume data 
+            vci_rsp_fifo_dcache_get = true;
+            if(r_dcache_ll_rsp_count.read() == 0) //first flit
+            {
+                //access table
+                table_in.cmd    = LLSCLocalTable::LL_RSP    ;
+                table_in.index  = 0;//p_vci_ini_d.rtrdid.read() ; // TODO use this ?
+                table_in.key    = r_vci_rsp_fifo_dcache.read();
+                r_llsc_table.exec(table_in, table_out);
+                llsc_local_table_access_done = true;
+                r_dcache_ll_rsp_count = r_dcache_ll_rsp_count.read() + 1 ;
+            }
+            else //last flit
+            {
+                // acknowledge the processor request if it has not been modified
+                if ( m_dreq.valid and (m_dreq.addr == r_dcache_p0_vaddr.read()) )
+                {
+                    m_drsp.valid        = true;
+                    m_drsp.rdata        = r_vci_rsp_fifo_dcache.read();
+                }
+                r_dcache_fsm = DCACHE_IDLE;
+            }
+	    }
+        break;
+    }
+    ////////////////////
+    case DCACHE_SC_WAIT:	// waiting VCI response after a processor SC request
+    {
+        // external coherence request
+        if ( r_tgt_dcache_req.read() ) 
+        {
+            r_dcache_fsm_cc_save = r_dcache_fsm;
+            r_dcache_fsm         = DCACHE_CC_CHECK;
+            break;
+        }
+
+        if ( r_vci_rsp_data_error.read() ) 		// bus error
+        {
+            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
+            r_mmu_dbvar          = m_dreq.addr;
+            r_vci_rsp_data_error = false;
+            m_drsp.error         = true;
+            m_drsp.valid         = true;
+            r_dcache_fsm         = DCACHE_IDLE;
+            break;
+        }
+	    else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
+	    {
+            // consume response 
+            vci_rsp_fifo_dcache_get = true;
+            m_drsp.valid            = true;
             m_drsp.rdata            = r_vci_rsp_fifo_dcache.read();
             r_dcache_fsm            = DCACHE_IDLE;
-	}	
+	    }	
         break;
     }
@@ -4002,11 +4100,21 @@
         assert( hit and "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
 
-        // request sc transaction to CMD_FSM
+        // request CAS transaction to CMD_FSM
         r_dcache_dirty_way  = way; 
         r_dcache_dirty_set  = set; 
-        r_dcache_vci_sc_req = true;
+        // prepare llsc local table access
+        table_in.cmd       = LLSCLocalTable::SW_CMD;
+        table_in.address   = r_dcache_dirty_paddr.read();
+        // access the table
+        r_llsc_table.exec(table_in, table_out);
+        llsc_local_table_access_done = true;
+        // test if the table is done
+        if(!table_out.done)
+            break;
+        // 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_sc_old = pte;
-        r_dcache_vci_sc_new = pte | PTE_D_MASK;
+        r_dcache_vci_cas_old = pte;
+        r_dcache_vci_cas_new = pte | PTE_D_MASK;
         r_dcache_fsm        = DCACHE_DIRTY_WAIT;
 
@@ -4041,5 +4149,5 @@
         if ( r_vci_rsp_data_error.read() )	// bus error
         {
-            std::cout << "BUS ERROR in DCACHE_DIRTY_SC_WAIT state" << std::endl;
+            std::cout << "BUS ERROR in DCACHE_DIRTY_WAIT state" << std::endl;
             std::cout << "This should not happen in this state" << std::endl;
             exit(0);
@@ -4053,5 +4161,5 @@
 if ( m_debug_dcache_fsm )
 {
-    std::cout << "  <PROC " << name() << ".DCACHE_DIRTY_SC_WAIT> SC completed" << std::endl;
+    std::cout << "  <PROC " << name() << ".DCACHE_DIRTY_WAIT> SC completed" << std::endl;
 }
 #endif
@@ -4303,4 +4411,10 @@
     }   
     } // end switch r_dcache_fsm
+    // perform a NOP access the the local llsc table if necessary
+    if(llsc_local_table_access_done == false)
+    {
+        table_in.cmd = LLSCLocalTable::NOP;
+        r_llsc_table.exec(table_in, table_out);
+    }
 
     ///////////////// wbuf update //////////////////////////////////////////////////////
@@ -4347,8 +4461,10 @@
     // - r_dcache_vci_miss_req (reset)
     // - r_dcache_vci_unc_req (reset)
-    // - r_dcache_vci_sc_req (reset)
+    // - r_dcache_vci_ll_req (reset)
+    // - r_dcache_vci_sc_req (reset in case of local sc fail)
+    // - r_dcache_vci_cas_req (reset)
     //
     // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
-    // There is 6 request types, with the following priorities : 
+    // There are 8 request types, with the following priorities : 
     // 1 - Data Read Miss         : r_dcache_vci_miss_req and miss in the write buffer
     // 2 - Data Read Uncachable   : r_dcache_vci_unc_req  
@@ -4356,5 +4472,7 @@
     // 4 - Instruction Uncachable : r_icache_unc_req 
     // 5 - Data Write             : r_wbuf.rok()      
-    // 6 - Data Store Conditionnal: r_dcache_vci_sc_req
+    // 6 - Data Linked Load       : r_dcache_vci_ll_req
+    // 7 - Data Store Conditionnal: r_dcache_vci_sc_req
+    // 8 - Compare And Swap       : r_dcache_vci_cas_req
     //
     // As we want to support several simultaneous VCI transactions, the VCI_CMD_FSM 
@@ -4430,11 +4548,30 @@
 //                m_length_write_transaction += (wbuf_max-wbuf_min+1);
             }
-            // 6 - Data Store Conditionnal
+            // 6 - Data Linked Load
+            // must check that all write transaction are completed
+            else if ( r_dcache_vci_ll_req.read() && r_wbuf.miss(r_dcache_vci_paddr.read()))
+            {
+                r_dcache_vci_ll_req = false;
+                r_vci_cmd_fsm       = CMD_DATA_LL;
+//              r_vci_cmd_cpt       = 0;
+//              m_cpt_sc_transaction++;
+            }
+            // 7 - Data Store Conditionnal
+            // should check that all write transaction are completed ?
             else if ( r_dcache_vci_sc_req.read() )
             {
-                r_vci_cmd_fsm       = CMD_DATA_CAS;
                 r_dcache_vci_sc_req = false;
-                r_vci_cmd_cpt       = 0;
-//                m_cpt_sc_transaction++;
+                r_vci_cmd_cpt  = 0;
+                r_vci_cmd_fsm  = CMD_DATA_SC;
+//              m_cpt_sc_transaction++;
+            }
+            // 8 - Compare And Swap
+            // should check that all write transaction are completed ?
+            else if ( r_dcache_vci_cas_req.read() )
+            {
+                r_vci_cmd_fsm        = CMD_DATA_CAS;
+                r_dcache_vci_cas_req = false;
+                r_vci_cmd_cpt        = 0;
+//              m_cpt_sc_transaction++;
             }
             break;
@@ -4456,7 +4593,8 @@
         }
         /////////////////
+        case CMD_DATA_SC:
         case CMD_DATA_CAS:
         {
-            // The SC VCI command contains two flits
+            // The CAS and SC VCI commands contain two flits
             if ( p_vci_ini_d.cmdack.read() )
             {
@@ -4471,4 +4609,5 @@
         case CMD_DATA_MISS:
         case CMD_DATA_UNC:
+        case CMD_DATA_LL:
         {
             // all read VCI commands contain one single flit
@@ -4487,4 +4626,5 @@
     // - r_vci_rsp_ins_error (set)
     // - r_vci_rsp_cpt
+    // - r_dcache_vci_sc_req (reset when SC response recieved)
     //
     // As the VCI_RSP and VCI_CMD are fully desynchronized to support several
@@ -4540,11 +4680,9 @@
             else if ( (p_vci_ini_d.rpktid.read() & 0x7) ==  TYPE_LL             ) 
             {
-                assert(false and "TODO ! LL NOT IMPLEMENTED YET"); //TODO
-                //r_vci_rsp_fsm = RSP_DATA_UNC;
+                r_vci_rsp_fsm = RSP_DATA_LL;
             }
             else if ( (p_vci_ini_d.rpktid.read() & 0x7) == TYPE_SC             ) 
             {
-                assert(false and "TODO ! SC NOT IMPLEMENTED YET"); //TODO
-                //r_vci_rsp_fsm = RSP_DATA_UNC;
+                r_vci_rsp_fsm = RSP_DATA_UNC;
             }
             else
@@ -4670,4 +4808,41 @@
         }
         ////////////////////
+        case RSP_DATA_LL:
+        {
+            if ( p_vci_ini_d.rspval.read() )
+            {
+                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
+                {
+                    r_vci_rsp_data_error = true;
+                    r_vci_rsp_fsm = RSP_IDLE;
+                }
+                if (r_vci_rsp_cpt.read() == 0) //first flit
+                {
+                    if(r_vci_rsp_fifo_dcache.wok())
+                    {
+                        assert(!p_vci_ini_d.reop.read() &&
+                            "illegal VCI response packet for LL");
+                        vci_rsp_fifo_dcache_put  = true;
+                        vci_rsp_fifo_dcache_data = p_vci_ini_d.rdata.read();
+                        r_vci_rsp_cpt            = r_vci_rsp_cpt.read() + 1;
+                    }
+                    break;
+                }
+                else // last flit
+                {
+                    if(r_vci_rsp_fifo_dcache.wok())
+                    {
+                        assert(p_vci_ini_d.reop.read() &&
+                            "illegal VCI response packet for LL");
+                        vci_rsp_fifo_dcache_put  = true;
+                        vci_rsp_fifo_dcache_data = p_vci_ini_d.rdata.read();
+                        r_vci_rsp_fsm            = RSP_IDLE;
+                    }
+                    break;
+                }
+            }
+            break;
+        }
+        ////////////////////
         case RSP_DATA_WRITE:
         {
@@ -4678,5 +4853,5 @@
 
                 r_vci_rsp_fsm = RSP_IDLE;
-                uint32_t   wbuf_index = p_vci_ini_d.rtrdid.read() - (1<<(vci_param::T-1));
+                uint32_t   wbuf_index = p_vci_ini_d.rtrdid.read();
                 bool       cacheable  = r_wbuf.completed(wbuf_index);
                 if ( not cacheable ) r_dcache_pending_unc_write = false;
@@ -4814,4 +4989,6 @@
                                  vci_rsp_fifo_dcache_put,
                                  vci_rsp_fifo_dcache_data);
+
+    #undef LLSCLocalTable
 } // end transition()
 
@@ -4951,5 +5128,5 @@
         p_vci_ini_d.wdata   = r_wbuf.getData(r_vci_cmd_cpt.read());
         p_vci_ini_d.be      = r_wbuf.getBe(r_vci_cmd_cpt.read());
-        p_vci_ini_d.trdid   = r_wbuf.getIndex() + (1<<(vci_param::T-1));
+        p_vci_ini_d.trdid   = r_wbuf.getIndex();
         p_vci_ini_d.pktid   = TYPE_WRITE;
         p_vci_ini_d.plen    = (r_vci_cmd_max.read() - r_vci_cmd_min.read() + 1) << 2;
@@ -4958,9 +5135,34 @@
         break;
 
+    case CMD_DATA_LL:
+        p_vci_ini_d.cmdval  = true;
+        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
+        p_vci_ini_d.wdata   = 0;
+        p_vci_ini_d.be      = 0xF;
+        p_vci_ini_d.trdid   = 0;    //TODO local table index
+        p_vci_ini_d.pktid   = TYPE_LL;
+        p_vci_ini_d.plen    = 8;
+        p_vci_ini_d.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini_d.eop     = true;
+        break;
+
+    case CMD_DATA_SC:
+        p_vci_ini_d.cmdval  = true;
+        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
+        if ( r_vci_cmd_cpt.read() == 0 ) p_vci_ini_d.wdata = r_sc_key.read();
+        else                             p_vci_ini_d.wdata = r_dcache_vci_sc_data.read();
+        p_vci_ini_d.be      = 0xF;
+        p_vci_ini_d.trdid   = 0;
+        p_vci_ini_d.pktid   = TYPE_SC;
+        p_vci_ini_d.plen    = 8;
+        p_vci_ini_d.cmd     = vci_param::CMD_NOP;
+        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == 1);
+        break;      
+
     case CMD_DATA_CAS:
         p_vci_ini_d.cmdval  = true;
         p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
-        if ( r_vci_cmd_cpt.read() == 0 ) p_vci_ini_d.wdata = r_dcache_vci_sc_old.read();
-        else                             p_vci_ini_d.wdata = r_dcache_vci_sc_new.read();
+        if ( r_vci_cmd_cpt.read() == 0 ) p_vci_ini_d.wdata = r_dcache_vci_cas_old.read();
+        else                             p_vci_ini_d.wdata = r_dcache_vci_cas_new.read();
         p_vci_ini_d.be      = 0xF;
         p_vci_ini_d.trdid   = 0;
@@ -4983,4 +5185,5 @@
         case RSP_DATA_MISS  : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
         case RSP_DATA_UNC   : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
+        case RSP_DATA_LL    : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
         case RSP_IDLE       : p_vci_ini_d.rspack = false; break;
     } // end switch r_vci_rsp_fsm
@@ -5051,12 +5254,2 @@
 
 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
-
-
-
-
-
-
-
-
-
-
Index: trunk/modules/vci_mem_cache_v4/caba/metadata/vci_mem_cache_v4.sd
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/metadata/vci_mem_cache_v4.sd	(revision 290)
+++ trunk/modules/vci_mem_cache_v4/caba/metadata/vci_mem_cache_v4.sd	(revision 291)
@@ -24,4 +24,5 @@
             Uses('common:mapping_table'),
             Uses('caba:generic_fifo'),
+            Uses('caba:generic_llsc_global_table'),
         ],
 
Index: trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h	(revision 290)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h	(revision 291)
@@ -54,4 +54,5 @@
 #include "mapping_table.h"
 #include "int_tab.h"
+#include "generic_llsc_global_table.h"
 #include "mem_cache_directory_v4.h"
 #include "xram_transaction_v4.h"
@@ -422,4 +423,12 @@
       CacheData       m_cache_data;       // data array[set][way][word]
       HeapDirectory   m_heap;             // heap for copies
+      GenericLLSCGlobalTable
+      <
+        32  ,   // desired number of slots
+        4096,   // number of processors in the system
+        8000,   // registratioÃ§n life span (in # of LL operations)
+        typename vci_param::fast_addr_t // address type
+      >
+      m_llsc_table;       // ll/sc global registration table
 
       // adress masks
@@ -491,4 +500,6 @@
       sc_signal<size_t>   r_read_next_ptr;   // Next entry to point to
       sc_signal<bool>     r_read_last_free;  // Last free entry
+      sc_signal<typename vci_param::fast_addr_t>
+                          r_read_ll_key;     // LL key returned by the llsc_global_table
 
       // Buffer between READ fsm and IXR_CMD fsm (ask a missing cache line to XRAM)
@@ -505,4 +516,6 @@
       sc_signal<size_t>   r_read_to_tgt_rsp_word;   // first word of the response
       sc_signal<size_t>   r_read_to_tgt_rsp_length; // length of the response
+      sc_signal<typename vci_param::fast_addr_t>
+                          r_read_to_tgt_rsp_ll_key; // LL key returned by the llsc_global_table
 
       ///////////////////////////////////////////////////////////////
@@ -533,10 +546,13 @@
       sc_signal<size_t>   r_write_trt_index;  // index in Transaction Table
       sc_signal<size_t>   r_write_upt_index;  // index in Update Table
+      sc_signal<bool>     r_write_sc_fail;    // sc command failed
+      sc_signal<bool>     r_write_pending_sc; // sc command pending in WRITE fsm
 
       // Buffer between WRITE fsm and TGT_RSP fsm (acknowledge a write command from L1)
-      sc_signal<bool>     r_write_to_tgt_rsp_req;   // valid request
-      sc_signal<size_t>   r_write_to_tgt_rsp_srcid; // transaction srcid
-      sc_signal<size_t>   r_write_to_tgt_rsp_trdid; // transaction trdid
-      sc_signal<size_t>   r_write_to_tgt_rsp_pktid; // transaction pktid
+      sc_signal<bool>     r_write_to_tgt_rsp_req;     // valid request
+      sc_signal<size_t>   r_write_to_tgt_rsp_srcid;   // transaction srcid
+      sc_signal<size_t>   r_write_to_tgt_rsp_trdid;   // transaction trdid
+      sc_signal<size_t>   r_write_to_tgt_rsp_pktid;   // transaction pktid
+      sc_signal<bool>     r_write_to_tgt_rsp_sc_fail; // sc command failed
 
       // Buffer between WRITE fsm and IXR_CMD fsm (ask a missing cache line to XRAM)
@@ -721,4 +737,6 @@
       sc_signal<size_t>   r_xram_rsp_to_tgt_rsp_length; // length of the response
       sc_signal<bool>     r_xram_rsp_to_tgt_rsp_rerror; // send error to requester
+      sc_signal<typename vci_param::fast_addr_t>
+                          r_xram_rsp_to_tgt_rsp_ll_key; // LL key returned by the llsc_global_table
 
       // Buffer between XRAM_RSP fsm and INIT_CMD fsm (Inval L1 Caches)
Index: trunk/modules/vci_mem_cache_v4/caba/source/include/xram_transaction_v4.h
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/include/xram_transaction_v4.h	(revision 290)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/xram_transaction_v4.h	(revision 291)
@@ -32,4 +32,5 @@
     std::vector<be_t>   wdata_be;    	// be for each data in the write buffer
     bool                rerror;         // error returned by xram
+    data_t              ll_key;         // LL key returned by the llsc_global_table
 
     /////////////////////////////////////////////////////////////////////
@@ -127,4 +128,5 @@
         wdata.assign(source.wdata.begin(),source.wdata.end());	
         rerror      = source.rerror;
+        ll_key      = source.ll_key;
     }
 
@@ -325,4 +327,5 @@
     // - data : the data to write (in case of write)
     // - data_be : the mask of the data to write (in case of write)
+    // - ll_key  : the ll key (if any) returned by the llsc_global_table
     /////////////////////////////////////////////////////////////////////
     void set(const size_t index,
@@ -336,5 +339,6 @@
             const size_t word_index,
             const std::vector<be_t> &data_be,
-            const std::vector<data_t> &data) 
+            const std::vector<data_t> &data, 
+            const data_t ll_key = 0) 
     {
         assert( (index < size_tab) 
@@ -354,4 +358,5 @@
         tab[index].read_length	    = read_length;
         tab[index].word_index	    = word_index;
+        tab[index].ll_key   	    = ll_key;
         for(size_t i=0; i<tab[index].wdata.size(); i++) 
         {
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 290)
+++ trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp	(revision 291)
@@ -293,4 +293,5 @@
     m_cache_data( nways, nsets, nwords ),
     m_heap( m_heap_size ),
+    m_llsc_table(),
 
 #define L2 soclib::common::uint32_log2
@@ -511,4 +512,7 @@
               << " | " << ixr_rsp_fsm_str[r_ixr_rsp_fsm]
               << " | " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl;
+
+              //m_llsc_table.print_trace();
+
 }
 
@@ -860,6 +864,5 @@
           assert(((p_vci_tgt.pktid.read() & 0x7) == 0x6) &&
             "The type specified in the pktid field is incompatible with the LL CMD");
-          assert(false && "TODO : LL not implemented"); //TODO
-          //r_tgt_cmd_fsm = TGT_CMD_READ;
+          r_tgt_cmd_fsm = TGT_CMD_READ;
         }
         else if ( p_vci_tgt.cmd.read() == vci_param::CMD_NOP )
@@ -874,9 +877,8 @@
             "The type specified in the pktid field is incompatible with the NOP CMD");
 
-          if(p_vci_tgt.pktid.read() == TYPE_CAS)
+          if((p_vci_tgt.pktid.read() & 0x7) == TYPE_CAS)
             r_tgt_cmd_fsm = TGT_CMD_CAS;
           else // TYPE_SC
-            assert(false && "TODO : SC not implemented"); //TODO
-            //r_tgt_cmd_fsm = TGT_CMD_WRITE;
+            r_tgt_cmd_fsm = TGT_CMD_WRITE;
         }
         else
@@ -892,5 +894,7 @@
     //////////////////
     case TGT_CMD_READ:
-      if ((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2)) > 16)
+      // This test checks that the read does not cross a cache line limit.
+      // It must not be taken into account when dealing with an LL CMD.
+      if (((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2)) > 16) && ( p_vci_tgt.cmd.read() != vci_param::CMD_LOCKED_READ ))
       {
         std::cout
@@ -907,5 +911,5 @@
           << std::endl;
         std::cout
-          << " read command packets must contain one single flit"
+          << " read or ll command packets must contain one single flit"
           << std::endl;
         exit(0);
@@ -927,5 +931,8 @@
 #endif
         cmd_read_fifo_put = true;
-        m_cpt_read++;
+        if ( p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ )
+          m_cpt_ll++;
+        else
+          m_cpt_read++;
         r_tgt_cmd_fsm = TGT_CMD_IDLE;
       }
@@ -1139,5 +1146,5 @@
   //    READ FSM
   ////////////////////////////////////////////////////////////////////////////////////
-  // The READ FSM controls the VCI read requests.
+  // The READ FSM controls the VCI read  and ll requests.
   // It takes the lock protecting the cache directory to check the cache line status:
   // - In case of HIT
@@ -1174,4 +1181,5 @@
             << " srcid = " << std::dec << m_cmd_read_srcid_fifo.read()
             << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
+            << " / pktid = " << std::hex << m_cmd_read_pktid_fifo.read()
             << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
         }
@@ -1211,5 +1219,8 @@
         DirectoryEntry entry =
           m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
-
+        if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL) // access the global table ONLY when we have an LL cmd
+        {
+          r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
+        }
         r_read_is_cnt     = entry.is_cnt;
         r_read_dirty      = entry.dirty;
@@ -1256,4 +1267,9 @@
             << " / count = " <<std::dec << entry.count
             << " / is_cnt = " << entry.is_cnt << std::endl;
+            if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)
+            {
+              std::cout
+                << "  <MEMC " << name() << ".READ_DIR_LOCK> global_llsc_table LL access" << std::endl;
+            }
         }
 #endif
@@ -1604,7 +1620,8 @@
         r_read_to_tgt_rsp_trdid  = m_cmd_read_trdid_fifo.read();
         r_read_to_tgt_rsp_pktid  = m_cmd_read_pktid_fifo.read();
-        cmd_read_fifo_get    = true;
-        r_read_to_tgt_rsp_req  = true;
-        r_read_fsm     = READ_IDLE;
+        r_read_to_tgt_rsp_ll_key = r_read_ll_key.read();
+        cmd_read_fifo_get        = true;
+        r_read_to_tgt_rsp_req    = true;
+        r_read_fsm               = READ_IDLE;
 
 #if DEBUG_MEMC_READ
@@ -1673,5 +1690,6 @@
             m_x[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
             std::vector<be_t>(m_words,0),
-            std::vector<data_t>(m_words,0));
+            std::vector<data_t>(m_words,0),
+            r_read_ll_key.read());
 #if DEBUG_MEMC_READ
         if( m_debug_read_fsm )
@@ -1718,5 +1736,5 @@
   //    WRITE FSM
   ///////////////////////////////////////////////////////////////////////////////////
-  // The WRITE FSM handles the write bursts sent by the processors.
+  // The WRITE FSM handles the write bursts and sc requests sent by the processors.
   // All addresses in a burst must be in the same cache line.
   // A complete write burst is consumed in the FIFO & copied to a local buffer.
@@ -1728,5 +1746,5 @@
   //   returned to the writing processor.
   //   If the data is cached by other processors, a coherence transaction must
-  //   be launched:
+  //   be launched (sc requests always require a coherence transaction):
   //   It is a multicast update if the line is not in counter mode, and the processor
   //   takes the lock protecting the Update Table (UPT) to register this transaction.
@@ -1753,9 +1771,15 @@
       if ( m_cmd_write_addr_fifo.rok() )
       {
-        m_cpt_write++;
-        m_cpt_write_cells++;
+        if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
+          m_cpt_sc++;
+        else
+        {
+          m_cpt_write++;
+          m_cpt_write_cells++;
+        }
 
         // consume a word in the FIFO & write it in the local buffer
         cmd_write_fifo_get  = true;
+        r_write_pending_sc  = false;
         size_t index        = m_x[(vci_addr_t)(m_cmd_write_addr_fifo.read())];
 
@@ -1775,5 +1799,5 @@
         }
 
-        if( m_cmd_write_eop_fifo.read() )
+        if( m_cmd_write_eop_fifo.read() || ((m_cmd_write_pktid_fifo.read() & 0x7)  == TYPE_SC) )
         {
           r_write_fsm = WRITE_DIR_REQ;
@@ -1824,4 +1848,5 @@
         // consume a word in the FIFO & write it in the local buffer
         cmd_write_fifo_get  = true;
+        r_write_pending_sc  = false;
         size_t index        = r_write_word_index.read() + r_write_word_count.read();
 
@@ -1844,4 +1869,36 @@
       if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE )
       {
+        if(((r_write_pktid.read() & 0x7) == TYPE_SC) && not r_write_pending_sc.read()) // check for an SC command (and check that its second flit is not already consumed)
+        {
+          if ( m_cmd_write_addr_fifo.rok() )
+          {
+            size_t index    = m_x[(vci_addr_t)(r_write_address.read())];
+            bool sc_success = m_llsc_table.sc(r_write_address.read(),r_write_data[index].read());
+            r_write_sc_fail = !sc_success;
+
+            assert(m_cmd_write_eop_fifo.read() && "Error in VCI_MEM_CACHE : 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_pending_sc  = true;
+            index               = m_x[(vci_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();
+            if (!sc_success)
+            {
+              r_write_fsm = WRITE_RSP;
+              break;
+            }
+          }
+          else break;
+        }
+        //else it is a TYPE_WRITE, need a simple sw access to the
+        // llsc_global_table
+        else
+        {
+          m_llsc_table.sw(r_write_address.read());
+        }
         r_write_fsm = WRITE_DIR_LOCK;
       }
@@ -1905,4 +1962,8 @@
             << " count = " << entry.count
             << " is_cnt = " << entry.is_cnt << std::endl;
+          if((r_write_pktid.read() & 0x7) == TYPE_SC)
+            std::cout << "  <MEMC " << name() << ".WRITE_DIR_LOCK> global_llsc_table SC access" << std::endl;
+          else
+            std::cout << "  <MEMC " << name() << ".WRITE_DIR_LOCK> global_llsc_table SW access" << std::endl;
         }
 #endif
@@ -1985,5 +2046,6 @@
 
       // no_update is true when there is no need for coherence transaction
-      bool no_update = (r_write_count.read()==0) || ( owner && (r_write_count.read()==1));
+      // (tests for sc requests)
+      bool no_update = ((r_write_count.read()==0) || ( owner && (r_write_count.read()==1) && (r_write_pktid.read() != TYPE_SC)));
 
       // write data in the cache if no coherence transaction
@@ -2004,5 +2066,5 @@
       }
 
-      if ( owner and not no_update )
+      if ( owner and not no_update and (r_write_pktid.read() != TYPE_SC))
       {
         r_write_count = r_write_count.read() - 1;
@@ -2127,5 +2189,5 @@
     case WRITE_UPT_REQ:
     {
-      // prepare the coherence ransaction for the INIT_CMD FSM
+      // prepare the coherence transaction for the INIT_CMD FSM
       // and write the first copy in the FIFO
       // send the request if only one copy
@@ -2146,5 +2208,5 @@
         for (size_t i=min ; i<max ; i++) r_write_to_init_cmd_data[i] = r_write_data[i];
 
-        if( (r_write_copy.read() != r_write_srcid.read()) or
+        if( (r_write_copy.read() != r_write_srcid.read()) or (r_write_pktid.read() == TYPE_SC) or
 #if L1_MULTI_CACHE
             (r_write_copy_cache.read() != r_write_pktid.read()) or
@@ -2159,5 +2221,5 @@
           write_to_init_cmd_fifo_cache_id= r_write_copy_cache.read();
 #endif
-          if(r_write_count.read() == 1)
+          if(r_write_count.read() == 1 || ((r_write_count.read() == 0) && (r_write_pktid.read() == TYPE_SC)) )
           {
             r_write_fsm = WRITE_IDLE;
@@ -2207,9 +2269,9 @@
       bool dec_upt_counter;
 
-      if( (entry.owner.srcid != r_write_srcid.read()) or
+      if(((entry.owner.srcid != r_write_srcid.read()) || (r_write_pktid.read() == TYPE_SC)) or
 #if L1_MULTI_CACHE
           (entry.owner.cache_id != r_write_pktid.read()) or
 #endif
-          entry.owner.inst)               // put te next srcid in the fifo
+          entry.owner.inst)             // put the next srcid in the fifo
       {
         dec_upt_counter                 = false;
@@ -2299,17 +2361,24 @@
       {
         // post the request to TGT_RSP_FSM
-        r_write_to_tgt_rsp_req   = true;
-        r_write_to_tgt_rsp_srcid = r_write_srcid.read();
-        r_write_to_tgt_rsp_trdid = r_write_trdid.read();
-        r_write_to_tgt_rsp_pktid = r_write_pktid.read();
+        r_write_to_tgt_rsp_req     = true;
+        r_write_to_tgt_rsp_srcid   = r_write_srcid.read();
+        r_write_to_tgt_rsp_trdid   = r_write_trdid.read();
+        r_write_to_tgt_rsp_pktid   = r_write_pktid.read();
+        r_write_to_tgt_rsp_sc_fail = r_write_sc_fail.read();
 
         // try to get a new write request from the FIFO
         if ( m_cmd_write_addr_fifo.rok() )
         {
-          m_cpt_write++;
-          m_cpt_write_cells++;
+          if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
+            m_cpt_sc++;
+          else
+          {
+            m_cpt_write++;
+            m_cpt_write_cells++;
+          }
 
           // consume a word in the FIFO & write it in the local buffer
           cmd_write_fifo_get  = true;
+          r_write_pending_sc  = false;
           size_t index        = m_x[(vci_addr_t)(m_cmd_write_addr_fifo.read())];
 
@@ -2329,5 +2398,5 @@
           }
 
-          if( m_cmd_write_eop_fifo.read() )
+          if( m_cmd_write_eop_fifo.read() || ((m_cmd_write_pktid_fifo.read() & 0x7)  == TYPE_SC) )
           {
             r_write_fsm = WRITE_DIR_REQ;
@@ -3191,5 +3260,5 @@
             entry.lock    = false;
             entry.dirty   = dirty;
-            entry.tag   = r_xram_rsp_trt_buf.nline / m_sets;
+            entry.tag     = r_xram_rsp_trt_buf.nline / m_sets;
             entry.ptr     = 0;
             if(cached_read)
@@ -3305,4 +3374,5 @@
                 r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
                 r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
+                r_xram_rsp_to_tgt_rsp_ll_key = r_xram_rsp_trt_buf.ll_key;
                 r_xram_rsp_to_tgt_rsp_rerror = false;
                 r_xram_rsp_to_tgt_rsp_req    = true;
@@ -4371,6 +4441,9 @@
         //////////////////////
         case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
-                                    // write data in cache if no CC request
-        {
+                                   // write data in cache if no CC request
+        {
+            // The CAS is a success => sw access to the llsc_global_table
+            m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
+
             // test coherence request
             if(r_cas_count.read())   // replicated line
@@ -4422,4 +4495,5 @@
               << " / value = " << r_cas_wdata.read()
               << " / count = " << r_cas_count.read() << std::endl;
+    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> global_llsc_table SW access" << std::endl;
 }
 #endif
@@ -6383,5 +6457,11 @@
       case TGT_RSP_READ:
         p_vci_tgt.rspval   = true;
-        p_vci_tgt.rdata    = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
+        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();
+        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();
@@ -6391,10 +6471,18 @@
         break;
       case TGT_RSP_WRITE:
+        /*if( ((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) )
+            {
+              std::cout << "SC RSP / rsrcid = " << r_write_to_tgt_rsp_srcid.read() << " / rdata = " << r_write_to_tgt_rsp_sc_fail.read() << std::endl;
+            }*/
         p_vci_tgt.rspval   = true;
-        p_vci_tgt.rdata    = 0;
+        if( ((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) && r_write_to_tgt_rsp_sc_fail.read() )
+          p_vci_tgt.rdata  = 1;
+        else
+          p_vci_tgt.rdata  = 0;
         p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
         p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
         p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
-        p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1);
+        //p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1);
+        p_vci_tgt.rerror   = 0;
         p_vci_tgt.reop     = true;
         break;
@@ -6419,5 +6507,9 @@
       case TGT_RSP_XRAM:
         p_vci_tgt.rspval   = true;
-        p_vci_tgt.rdata    = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
+        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();
@@ -6430,9 +6522,9 @@
       case TGT_RSP_INIT:
         p_vci_tgt.rspval   = true;
-        p_vci_tgt.rdata    = 0;
+        p_vci_tgt.rdata    = 0; // Can be a CAS or SC rsp
         p_vci_tgt.rsrcid   = r_init_rsp_to_tgt_rsp_srcid.read();
         p_vci_tgt.rtrdid   = r_init_rsp_to_tgt_rsp_trdid.read();
         p_vci_tgt.rpktid   = r_init_rsp_to_tgt_rsp_pktid.read();
-        p_vci_tgt.rerror   = 0; // Can be a CAS rsp
+        p_vci_tgt.rerror   = 0;
         p_vci_tgt.reop     = true;
         break;
