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 288)
+++ 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 288)
+++ 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 288)
+++ 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
-
-
-
-
-
-
-
-
-
-
