Index: /trunk/lib/generic_llsc_global_table/include/generic_llsc_global_table.h
===================================================================
--- /trunk/lib/generic_llsc_global_table/include/generic_llsc_global_table.h	(revision 291)
+++ /trunk/lib/generic_llsc_global_table/include/generic_llsc_global_table.h	(revision 291)
@@ -0,0 +1,496 @@
+/* -*- c++ -*-
+ *
+ * SOCLIB_LGPL_HEADER_BEGIN
+ *
+ * This file is part of SoCLib, GNU LGPLv2.1.
+ *
+ * SoCLib is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 of the License.
+ *
+ * SoCLib is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SoCLib; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * SOCLIB_LGPL_HEADER_END
+ *
+ * Alexandre JOANNOU <alexandre.joannou@lip6.fr>
+ *
+ */
+
+#ifndef SOCLIB_GENERIC_LLSC_GLOBAL_TABLE_H
+#define SOCLIB_GENERIC_LLSC_GLOBAL_TABLE_H
+
+#include <systemc>
+#include <arithmetics.h>
+#include <cassert>
+#include <cstring>
+#include <cmath>
+#include <iostream>
+#include <iomanip>
+
+namespace soclib
+{
+
+//////////////////////////
+//TODO switch to this
+/*
+template
+<
+size_t          nb_slots,   // max number of concerned shared resources
+typename        key_t,      // key type => max number of key; TODO wich one ?
+unsigned int    t_network,  // max number of cycle spent in the network when responding to a client (or more)
+unsigned int    t_inter_op, // min number of cycle between 2 reservation operation (or less but > 0)
+typename        addr_t      // ressource identifier type
+>
+*/
+template
+<
+size_t          nb_slots,   // desired number of slots
+unsigned int    nb_procs,   // number of processors in the system
+unsigned int    life_span,  // registratioÃ§n life span (in # of LL operations)
+typename        addr_t      // address type
+>
+class GenericLLSCGlobalTable
+////////////////////////////
+{
+    private :
+
+    const std::string           name              ; // component name
+
+    uint32_t                    r_key  [nb_slots] ; // array of key
+    addr_t                      r_addr [nb_slots] ; // array of addresses
+    bool                        r_val  [nb_slots] ; // array of valid bits
+
+    uint32_t                    r_next_key        ; // value of the next key
+    sc_dt::sc_uint<nb_slots>    r_block_mask      ; // mask for the slots blocks
+    sc_dt::sc_uint<nb_slots>    r_last_counter    ; // mask for the slots blocks
+    size_t                      r_write_ptr       ; // index of next slot to replace
+    size_t                      r_last_empty      ; // index of last empty slot used
+
+    uint32_t                    m_cpt_evic        ; // number of eviction in the table
+    uint32_t                    m_cpt_ll          ; // number of ll accesses to the table
+    uint32_t                    m_cpt_ll_update   ; // number of ll accesses to the table that trigger an update TODO check that
+    uint32_t                    m_cpt_sc          ; // number of sc accesses to the table
+    uint32_t                    m_cpt_sc_success  ; // number of sc accesses to the table that are successful
+    uint32_t                    m_cpt_sw          ; // number of sw accesses to the table
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void upNextKey()
+    //  This function generates a new value for the next key
+    {
+        // generating a new key in r_next_key
+        r_next_key++;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    /*
+    inline void updateVictimSlot()
+    //  This function selects the next slot to be evicted
+    //  This is done by updating the value of r_write_ptr
+    {
+        // updates the position of the next slot to be replaced
+
+        static unsigned int count = 0;
+
+
+        // for each slot, check if it actually is the slot to replace
+        // this is done by checking count % 2^(i+1) == (2^i)-1
+        // 2^(i+1) being the period
+        // (2^i)-1 being the first apparition
+        // NB : the -1 in (2^i)-1 is here because of the 0 indexed array
+
+        for (size_t i = 0 ; i < nb_slots; i++)
+            if (count % (int)pow(2,i+1) == pow(2,i)-1)
+                r_write_ptr = i;
+
+        count = (count + 1) % (int) pow(2,nb_slots);    // mustn't go further than 2^nb_slots
+                                                        // or (2^nb_slots)+1 for a 1 indexed array
+                                                        // 2^32 = periodicity of slot #31
+    }
+    */
+    ////////////////////////////////////////////////////////////////////////////
+    inline void updateVictimSlot()
+    //  This function selects the next slot to be evicted
+    //  This is done by updating the value of r_write_ptr
+    {
+        sc_dt::sc_uint<nb_slots> new_counter;
+        sc_dt::sc_uint<nb_slots> xor_counter;
+
+        new_counter = newCounter(r_block_mask, r_last_counter);
+        xor_counter = new_counter ^ r_last_counter;
+
+        for (size_t i = nb_slots - 1; i >= 0; --i)
+        {
+            if(xor_counter[i])
+            {
+                r_write_ptr = i;
+                break;
+            }
+        }
+
+        r_last_counter = new_counter;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline sc_dt::sc_uint<nb_slots> newCounter(const sc_dt::sc_uint<nb_slots>& mask,
+                                               const sc_dt::sc_uint<nb_slots>& counter)
+    // This function generates the new counter //TODO comment more
+    {
+        //
+        return ((((~counter) & (counter << 1)) & mask) | (counter + 1));
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void init_block_mask()
+    //TODO
+    //This function selects the block mask to be used
+    //Need to provide another way to do that ?
+    {
+        /*
+        //try to dynamically compute the block mask ...
+        #define L2 soclib::common::uint32_log2
+        unsigned int budget = nb_slots - (L2(nb_procs) + 1); //TODO +1?
+        #undef L2
+        */
+
+        switch(nb_slots)
+        {
+            case 12:
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0x000");
+            break;
+            case 16 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xA800");
+            break;
+            case 20 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xD5500");
+            break;
+            case 24 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xDB5540");
+            break;
+            case 28 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xEEDAAA0");
+            break;
+            case 32 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xF776D550");
+            break;
+            case 36 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xFBDDDB550");
+            break;
+            case 40 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xFDF7BB6D50");
+            break;
+            case 44 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xFEFBDEEDAA8");
+            break;
+            case 48 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xFF7EFBDDDAA8");
+            break;
+            case 52 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xFFBFBF7BBB6A8");
+            break;
+            case 56 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xFFDFEFDF7BB6A8");
+            break;
+            case 60 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xFFF7FDFDF7BB6A8");
+            break;
+            case 64 :
+            r_block_mask = sc_dt::sc_uint<nb_slots>("0xFFFBFF7FBF7BB6A8");
+            break;
+            default:
+            assert(false && "nb_slots must be either 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 or 64");
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline int nextEmptySlot()
+    //  This function returns :
+    //  - the position of the first next empty slot in the table
+    //    (starting from the last empty slot used)
+    //    and updates the r_last_empty_slot register
+    //  - -1 if the table is full
+    {
+        size_t i = r_last_empty;
+        do
+        {
+            // checking if current slot is empty
+            if(!r_val[i])
+            {
+                // updating last empty slot and returning its position
+                r_last_empty = i;
+                return i;
+            }
+            // selecting next slot
+            i = (i+1) % nb_slots;
+        }
+        // stop if all slots have been tested
+        while(i != r_last_empty);
+
+        // the table is full
+        return -1;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline int hitAddr(const addr_t ad)
+    //  HIT on the address only
+    //  This function takes an addr_t ad
+    //  It returns :
+    //  - the position of the first HIT in the table
+    //  - -1 in case of MISS
+    //  NB : HIT = (slot addr == ad) AND (slot is valid)
+    {
+        // checking all slots
+        for (size_t i = 0; i < nb_slots; i++)
+        {
+            // if HIT, returning its position
+            if(ad == r_addr[i] && r_val[i]) return i;
+        }
+
+        // MISS
+        return -1;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline int hitAddrKey(const addr_t ad, const uint32_t key)
+    //  HIT on the address AND the on the signature
+    //  This function takes an addr_t ad and a uint32_t key
+    //  It returns :
+    //  - the position of the first HIT in the table
+    //  - -1 in case of MISS
+    //  NB : HIT = (slot addr == ad) AND (slot key == key)
+    //                               AND (slot is valid)
+    {
+        // checking all slots
+        for (size_t i = 0; i < nb_slots; i++)
+        {
+            // if HIT, returning its position
+            if(ad == r_addr[i] && key == r_key[i] && r_val[i]) return i;
+        }
+
+        // MISS
+        return -1;
+    }
+
+    public:
+
+    ////////////////////////////////////////////////////////////////////////////
+    GenericLLSCGlobalTable( const std::string   &n = "llsc_global_table" )
+    :   name(n)
+    {
+        #define L2 soclib::common::uint32_log2
+        assert(nb_procs > 1); //nb_procs must be more than 1
+        //TODO >= or > ?
+        assert(nb_slots >= L2(nb_procs)); // nb_slot cannot be less then log2(nb_procs)
+        #undef L2
+        init();
+        init_block_mask();
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    ~GenericLLSCGlobalTable()
+    {
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void init()
+    //  This function initializes the table (all slots empty)
+    {
+        // making all slots available by reseting all valid bits
+        std::memset(r_val, 0, sizeof(*r_val)*nb_slots);
+
+        // init registers
+        r_next_key          = 0;
+        r_last_counter      = 0; //TODO static in updateVictimSlot() ?
+        r_write_ptr         = 0;
+        r_last_empty        = 0;
+
+        // init stat counters
+        m_cpt_evic          = 0;
+        m_cpt_ll            = 0;
+        m_cpt_ll_update     = 0;
+        m_cpt_sc            = 0;
+        m_cpt_sc_success    = 0;
+        m_cpt_sw            = 0;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline uint32_t ll(const addr_t ad)
+    //  This method registers an LL in the table and returns the key associated
+    //  with the registration
+    {
+        // increment the ll access counter (for stats)
+        m_cpt_ll++;
+
+        // hit addr ?
+        // YES
+        //      enough time left ?
+        //      YES
+        //          use this registration, return key
+        //      NO
+        //          update this registration with a new key, return new key
+        // NO
+        //      table has an empty slot ?
+        //      YES
+        //              select empty slot
+        //      NO
+        //              select victim slot (r_write_ptr)
+        //              update next victim
+        //      open registration on selected slot
+        //      update next key
+        //      return the registration key
+
+        //  Is the address found in the table ?
+        int pos = hitAddr(ad);
+
+        //  Yes, then return the associated key
+        if (pos >= 0)
+        {
+            if(r_key[pos] - r_next_key > life_span)
+                return r_key[pos];
+            r_key[pos] = r_next_key;
+            upNextKey();
+            m_cpt_ll_update++;
+            return r_key[pos];
+        }
+
+        //  No, then try to find an empty slot
+        pos = nextEmptySlot();
+
+        //  If there is no empty slot,
+        //  evict an existing registration
+        if (pos == -1)
+        {
+            //  get the position of the evicted registration
+            pos = r_write_ptr;
+            //  update the victim slot for the next eviction
+            updateVictimSlot();
+            // increment the eviction counter (for stats)
+            m_cpt_evic++;
+        }
+
+        // get the key for the new registration
+        uint32_t key    = r_next_key;
+        //  update the registration slot
+        r_key[pos]      = key   ;
+        r_addr[pos]     = ad    ;
+        r_val[pos]      = true  ;
+        //  compute the next key
+        upNextKey();
+
+        // return the key of the new registration
+        return key;
+
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline bool sc(const addr_t ad, const uint32_t key)
+    //  This method checks if there is a valid registration for the SC (ad &&
+    //  key) and, in case of hit,invalidates the registration and returns true
+    //  (returns false otherwise)
+    //
+    //  The return value can be used to tell if the SC is atomic
+    {
+        // increment the sc access counter (for stats)
+        m_cpt_sc++;
+        // hit addr && hit key ?
+        // NO
+        //      return miss
+        // YES
+        //      inval registration and return hit
+
+        //  Is there a valid registration in the table ?
+        int pos = hitAddrKey(ad, key);
+        if(pos >= 0)
+        {
+            // increment the sc success counter (for stats)
+            m_cpt_sc_success++;
+            // invalidate the registration
+            r_val[pos] = false;
+            // return the success of the sc operation
+            return true;
+        }
+        else
+        {
+            // return the failure of the sc operation
+            return false;
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void sw(const addr_t ad)
+    //  This method checks if there is a valid registration for the given
+    //  address and, in case of hit, invalidates the registration
+    {
+        // increment the sw access counter (for stats)
+        m_cpt_sw++;
+        // hit addr ?
+        // YES
+        //      inval registration
+        // NO
+        //      nothing
+
+        //  Is there a registration for the given address ?
+        int pos = hitAddr(ad);
+        //  If there is one, invalidate it
+        if(pos >= 0) r_val[pos] = false;
+
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    /*
+    void fileTrace(FILE* file)
+    {
+    }
+    */
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void print_trace(std::ostream& out = std::cout)
+    {
+        out <<  " ___________________________________" << std::endl
+            <<  "| " << std::setw(33) << "generic_llsc_global_table" << " |" << std::endl
+            <<  "| " << std::setw(33) << name << " |" << std::endl
+            <<  " ===================================" << std::endl
+            <<  "| "
+            <<  std::setw(11) << "addr"   << " | "
+            <<  std::setw(11) << "key"    << " | "
+            <<  std::setw(5)  << "val"
+            << " |" << std::endl
+            <<  " -----------------------------------" << std::endl;
+        for ( size_t i = 0; i < nb_slots ; i++ )
+        {
+            out << "| "
+                << std::showbase
+                << std::setw(11) << std::setfill('0')   << std::hex       << r_addr[i]    << " | "
+                << std::noshowbase
+                << std::setw(11) << std::setfill('0')   << std::dec       << r_key[i]     << " | "
+                << std::setw(5)  << std::setfill(' ')   << std::boolalpha << r_val[i]     << " |" << std::endl ;
+        }
+        out <<  " -----------------------------------" << std::endl
+            << std::noshowbase << std::dec << std::endl ;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void print_stats(std::ostream& out = std::cout)
+    {
+        out << "# of ll accesses : " << m_cpt_ll            << std::endl
+            << "# of ll updates  : " << m_cpt_ll_update     << std::endl
+            << "# of sc accesses : " << m_cpt_sc            << std::endl
+            << "# of sc success  : " << m_cpt_sc_success    << std::endl
+            << "# of sw accesses : " << m_cpt_sw            << std::endl
+            << "# of evictions   : " << m_cpt_evic          << std::endl ;
+    }
+
+};
+
+} // end namespace soclib
+
+#endif
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Index: /trunk/lib/generic_llsc_global_table/metadata/generic_llsc_global_table.sd
===================================================================
--- /trunk/lib/generic_llsc_global_table/metadata/generic_llsc_global_table.sd	(revision 291)
+++ /trunk/lib/generic_llsc_global_table/metadata/generic_llsc_global_table.sd	(revision 291)
@@ -0,0 +1,13 @@
+# -*- python -*-
+
+Module(
+    'caba:generic_llsc_global_table',
+    classname       = 'soclib::GenericLLSCGlobalTable',
+    header_files    = ['../include/generic_llsc_global_table.h'],
+    tmpl_parameters = 
+        [
+            parameter.Int('nb_slots', min = 2, max = 64, default = 32),
+            parameter.Int('nb_procs', min = 2, max = 4096, default = 4095), # default should be 4096, but soclib-cc problem
+            parameter.Type('addr_t', default = 'sc_dt::sc_uint<40>')
+        ]
+)
Index: /trunk/lib/generic_llsc_local_table/include/generic_llsc_local_table.h
===================================================================
--- /trunk/lib/generic_llsc_local_table/include/generic_llsc_local_table.h	(revision 291)
+++ /trunk/lib/generic_llsc_local_table/include/generic_llsc_local_table.h	(revision 291)
@@ -0,0 +1,504 @@
+/* -*- c++ -*-
+ *
+ * SOCLIB_LGPL_HEADER_BEGIN
+ *
+ * This file is part of SoCLib, GNU LGPLv2.1.
+ *
+ * SoCLib is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 of the License.
+ *
+ * SoCLib is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SoCLib; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * SOCLIB_LGPL_HEADER_END
+ *
+ * Alexandre JOANNOU <alexandre.joannou@lip6.fr>
+ *
+ */
+
+#ifndef SOCLIB_GENERIC_LLSC_LOCAL_TABLE_H
+#define SOCLIB_GENERIC_LLSC_LOCAL_TABLE_H
+
+#include <systemc>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <iomanip>
+
+namespace soclib {
+
+//////////////////////////
+//TODO switch to this
+/*
+template
+<
+size_t          nb_slots,   // max number of authorized atomic operation per agent
+typename        key_t,      // key type => max number of key; TODO wich one ?
+unsigned int    t_network,  // max number of cycle spent in the network when responding to a client (or more)
+unsigned int    t_inter_op, // min number of cycle between 2 reservation operation (or less but > 0)
+typename        addr_t      // ressource identifier type
+>
+*/
+template
+<
+uint32_t    life_span               ,   // desired life-span for a reservation
+size_t      nb_slots    = 1         ,   // desired number of reservation
+typename    addr_t      = uint32_t  ,   // ressource identifier type
+typename    index_t     = size_t    ,   // transaction index/identifier type (trdid size)
+typename    key_t       = uint32_t      // key identifier type
+>
+class GenericLLSCLocalTable
+///////////////////////////
+{
+    public:
+
+    // command type
+    enum cmd_t
+    {
+        LL_CMD  = 0x8,  // create a reservation in the table (to be called when an ll cmd is emited)
+        LL_RSP  = 0x4,  // updates a reservation in the table (to be called when an ll rsp is received)
+        SC_CMD  = 0x2,  // invalidate a reservation (if necessary) and reset the wait register
+        SW_CMD  = 0x1,  // invalidate a reservation (if necessary)
+        NOP     = 0x0   // no operation (internal updates only : aging counters)
+    };
+
+    struct in_t
+    {
+        addr_t  address ;   // the address  argument of the command
+        index_t index   ;   // the index    argument of the command
+        key_t   key     ;   // the key      argument of the command
+        cmd_t   cmd     ;   // the command for the table to execute
+    };
+
+    struct out_t
+    {
+        bool    done    ;   // true if operation was actually performed
+        bool    hit     ;   // true if there was a hit on the address
+        key_t   key     ;   // the matching key for an SC_CMD
+        index_t index   ;   // the index of the reservation for a LL_CMD
+    };
+
+    private :
+
+    const std::string           name                ;   // component name
+
+    addr_t                      r_addr  [nb_slots]  ;   // array of addresses
+    key_t                       r_key   [nb_slots]  ;   // array of keys
+    uint32_t                    r_cnt   [nb_slots]  ;   // array of aging counters
+    bool                        r_val   [nb_slots]  ;   // array of valid bits
+
+    uint32_t                    r_wait              ;   // number of cycles to wait (when trying to perform a reservation)
+    uint32_t                    r_wait_cnt          ;   // counter counting down from r_wait to 0
+    size_t                      r_write_ptr         ;   // index of next slot to replace
+    size_t                      r_last_empty        ;   // index of last empty slot used
+
+    uint32_t                    m_cpt_ll_cmd        ;   // number of ll_cmd accesses to the table
+    uint32_t                    m_cpt_ll_cmd_done   ;   // number of ll_cmd accesses to the table (effectivelly done)
+    uint32_t                    m_cpt_ll_rsp        ;   // number of ll_rsp accesses to the table
+    uint32_t                    m_cpt_sc_cmd        ;   // number of sc_cmd accesses to the table
+    uint32_t                    m_cpt_sw_cmd        ;   // number of sw_cmd accesses to the table
+    uint32_t                    m_cpt_nop           ;   // number of nop    accesses to the table
+    uint32_t                    m_cpt_evic          ;   // number of eviction in the table
+    uint32_t                    m_cpt_death         ;   // number of death of reservations due to aging
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline int hitAddr(const addr_t & address)
+    //  HIT on the address only
+    //  This function takes an addr_t address
+    //  It returns :
+    //  - the position of the first HIT in the table
+    //  - -1 in case of MISS
+    //  NB : HIT = (slot addr == ad) AND (slot is valid)
+    {
+        // checking all slots
+        for (size_t i = 0; i < nb_slots; i++)
+        {
+            // if HIT, returning its position
+            if(address == r_addr[i] && r_val[i]) return i;
+        }
+
+        // MISS
+        return -1;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline int nextEmptySlot()
+    //  This function returns :
+    //  - the position of the first next empty slot in the table
+    //    (starting from the last empty slot used)
+    //    and updates the r_last_empty_slot register
+    //  - -1 if the table is full
+    {
+        size_t i = r_last_empty;
+        do
+        {
+            // checking if current slot is empty
+            if(!r_val[i])
+            {
+                // updating last empty slot and returning its position
+                r_last_empty = i;
+                return i;
+            }
+            // selecting next slot
+            i = (i+1) % nb_slots;
+        }
+        // stop if all slots have been tested
+        while(i != r_last_empty);
+
+        // the table is full
+        return -1;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void updateVictimSlot()
+    //  This function selects the next slot to be evicted
+    //  This is done by updating the value of r_write_ptr
+    {
+        r_write_ptr = 0;
+    }
+
+    public:
+
+    ////////////////////////////////////////////////////////////////////////////
+    GenericLLSCLocalTable(  const std::string    &n = "llsc_local_table" )
+    :   name(n)
+    {
+        init();
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    ~GenericLLSCLocalTable()
+    {
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void init()
+    //  This function initializes the table (all slots empty)
+    {
+        // making all slots available by reseting all valid bits
+        std::memset(r_val, 0, sizeof(*r_val)*nb_slots);
+
+        // init registers
+        r_wait              = 0;
+        r_wait_cnt          = 0;
+        r_write_ptr         = 0;
+        r_last_empty        = 0;
+
+        // init stat counters
+        m_cpt_ll_cmd        = 0;
+        m_cpt_ll_cmd_done   = 0;
+        m_cpt_ll_rsp        = 0;
+        m_cpt_sc_cmd        = 0;
+        m_cpt_sw_cmd        = 0;
+        m_cpt_nop           = 0;
+        m_cpt_evic          = 0;
+        m_cpt_death         = 0;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void exec(const in_t & in, out_t & out)
+    // This function has to be called every cycle !
+    // It implements the behaviour of the generic_llsc_local_table.
+    // 5 commands can be performed :
+    // - LL_CMD
+    // - LL_RSP
+    // - SC_CMD
+    // - SW_CMD
+    // - NOP
+    // Each one of them are described further below
+    {
+        // First check the command
+        switch(in.cmd)
+        {
+            case LL_CMD :
+            // INPUTS :
+            // - address
+            //
+            // Check if r_wait_cnt has reached 0
+            // - YES
+            //      - the wait counter is re initialized with the content of the
+            //        r_wait register
+            //      - the r_wait register is doubled (<< 1) (delay mechanism)
+            //      - check if there is an empty slot
+            //          if YES, select the empty slot
+            //          if NO, select victim slot and update next victim
+            //      - the address of the selected slot is initialized with the given
+            //        address
+            //      - the aging counter of the selected slot is initialized with
+            //        the life-span of a reservation
+            //      - the valid bit of the selected slot is set to true
+            //
+            //          - out.hit   <= don't care
+            //          - out.done  <= true
+            //          - out.key   <= don't care
+            //          - out.index <= i the index of the selected slot
+            //
+            // - NO
+            //      - decrement r_wait_cnt
+            //
+            //          - out.hit   <= don't care
+            //          - out.done  <= false
+            //          - out.key   <= don't care
+            //          - out.index <= don't care
+            {
+                // increment the ll_cmd access counter (for stats)
+                m_cpt_ll_cmd++;
+
+                if(r_wait_cnt == 0)
+                {
+                    // increment the ll_cmd access counter (effectivelly done) (for stats)
+                    m_cpt_ll_cmd_done++;
+
+                    // increase the lenght of the next waiting session
+                    //r_wait      = (r_wait << 1) + 1 ;
+                    // re initialize the wait counter //TODO check this...
+                    //r_wait_cnt  = r_wait;
+
+                    // select a slot for the reservation
+                    // first check for an empty slot ...
+                    int pos = nextEmptySlot();
+                    // If there is no empty slot,
+                    // evict an existing registration
+                    if (pos == -1)
+                    {
+                        // get the position of the evicted registration
+                        pos = r_write_ptr;
+                        // update the victim slot for the next eviction
+                        updateVictimSlot();
+                        // increment the eviction counter (for stats)
+                        m_cpt_evic++;
+                    }
+
+                    // inscription in the slot
+                    r_addr  [pos]   =   in.address  ;
+                    r_cnt   [pos]   =   life_span   ;
+                    r_val   [pos]   =   true        ;
+
+                    // construct out argument
+                    //out.hit   = don't care;
+                    out.done    = 1;
+                    //out.key   = don't care;
+                    out.index   = pos;
+                }
+                else
+                {
+                    // decrement the wait counter
+                    r_wait_cnt--;
+
+                    // construct out argument
+                    //out.hit   = don't care;
+                    out.done    = 0;
+                    //out.key   = don't care;
+                    //out.index = don't care;
+                }
+            }
+            break;
+            case LL_RSP :
+            // INPUTS :
+            // - index
+            // - key
+            //
+            //  - the key of the reservation is updated with the given key
+            //
+            //      - out.hit   <= don't care
+            //      - out.done  <= true
+            //      - out.key   <= don't care
+            //      - out.index <= don't care
+            {
+                // increment the ll_rsp access counter (for stats)
+                m_cpt_ll_rsp++;
+
+                // insert new key in reservation
+                r_key[in.index]  = in.key;
+
+                // construct out argument
+                out.hit     = 1;
+                out.done    = 1;
+                //out.key   = don't care;
+                //out.index = don't care;
+            }
+            break;
+            case SC_CMD :
+            // INPUTS :
+            // - address
+            //
+            // Check if there is a hit for the address
+            // - HIT
+            //      - invalidate reservation
+            //      - reset r_wait to 0
+            //
+            //          - out.hit   <= true
+            //          - out.done  <= true
+            //          - out.key   <= r_key[hit_index]
+            //          - out.index <= don't care
+            //
+            // - NO HIT
+            //
+            //      - out.hit   <= false
+            //      - out.done  <= true
+            //      - out.key   <= don't care
+            //      - out.index <= don't care
+            {
+                // increment the sc_cmd access counter (for stats)
+                m_cpt_sc_cmd++;
+
+                // Is there a valid reservation in the table ?
+                int pos = hitAddr(in.address);
+                if(pos >= 0)
+                {
+                    // invalidate reservation
+                    r_val[pos]  = false     ;
+                    // reset r_wait to 0
+                    r_wait      = 0         ;
+                    // construct out argument
+                    out.hit     = 1         ;
+                    out.done    = 1         ;
+                    out.key     = r_key[pos];
+                }
+                else
+                {
+                    // construct out argument
+                    out.hit     = 0;
+                    out.done    = 1;
+                    //out.key   = don't care;
+                    //out.index = don't care;
+                }
+            }
+            break;
+            case SW_CMD :
+            // INPUTS :
+            // - address
+            //
+            // Check if there is a hit for the address
+            // - HIT
+            //      - invalidate reservation
+            //
+            //          - out.hit   <= true
+            //          - out.done  <= true
+            //          - out.key   <= don't care
+            //          - out.index <= don't care
+            //
+            // - NO HIT
+            //
+            //      - out.hit   <= false
+            //      - out.done  <= true
+            //      - out.key   <= don't care
+            //      - out.index <= don't care
+            {
+                // increment the sw_cmd access counter (for stats)
+                m_cpt_sw_cmd++;
+
+                // Is there a valid reservation in the table ?
+                int pos = hitAddr(in.address);
+                if(pos >= 0)
+                {
+                    // invalidate reservation
+                    r_val[pos]  = false     ;
+                    // construct out argument
+                    out.hit     = 1         ;
+                    out.done    = 1         ;
+                    //out.key   = don't care ;
+                    //out.index = don't care;
+                }
+                else
+                {
+                    // construct out argument
+                    out.hit     = 0;
+                    out.done    = 1;
+                    //out.key   = don't care;
+                    //out.index = don't care;
+                }
+            }
+            break;
+            case NOP :
+            // NOTHING except for the usual aging counter updates
+            //
+            //      - out.hit   <= don't care
+            //      - out.done  <= 1
+            //      - out.key   <= don't care
+            //      - out.index <= don't care
+            {
+                // increment the nop access counter (for stats)
+                m_cpt_nop++;
+                // construct out argument
+                //out.hit   = don't care;
+                out.done    = 1;
+                //out.key   = don't care;
+                //out.index = don't care;
+            }
+            break;
+        }
+        // aging counters ...
+        // for each slot
+        for (size_t i = 0; i < nb_slots; i++)
+        {
+            // decrement the counter
+            r_cnt[i]--;
+            // check if the counter has reached 0 (for an actual reservation,
+            // i.e. a valid reservation)
+            if(r_cnt[i] == 0 && r_val[i])
+            {
+                // increment the death counter (for stats)
+                m_cpt_death++;
+                // invalidate the reservation
+                r_val[i] = false;
+            }
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void print_trace(std::ostream& out = std::cout)
+    {
+        out <<  " _________________________________________________" << std::endl
+            <<  "| " << std::setw(47) << "generic_llsc_local_table" << " |" << std::endl
+            <<  "| " << std::setw(47) << name << " |" << std::endl
+            <<  " =================================================" << std::endl
+            <<  "| "
+            <<  std::setw(11) << "addr"   << " | "
+            <<  std::setw(11) << "key"    << " | "
+            <<  std::setw(11) << "cnt"    << " | "
+            <<  std::setw(5)  << "val"
+            << " |" << std::endl
+            <<  " -------------------------------------------------" << std::endl;
+        for ( size_t i = 0; i < nb_slots ; i++ )
+        {
+            out << "| "
+                << std::showbase
+                << std::setw(11) << std::setfill('0')   << std::hex       << r_addr[i]    << " | "
+                << std::noshowbase
+                << std::setw(11) << std::setfill('0')   << std::dec       << r_key[i]     << " | "
+                << std::setw(11) << std::setfill('0')   << std::dec       << r_cnt[i]     << " | "
+                << std::setw(5)  << std::setfill(' ')   << std::boolalpha << r_val[i]     << " |" << std::endl ;
+        }
+        out <<  " -------------------------------------------------" << std::endl
+            << std::noshowbase << std::dec << std::endl ;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    inline void print_stats(std::ostream& out = std::cout)
+    {
+        out << "# of ll_cmd accesses                     : " << m_cpt_ll_cmd        << std::endl
+            << "# of ll_cmd accesses (effectivelly done) : " << m_cpt_ll_cmd_done   << std::endl
+            << "# of ll_rsp accesses                     : " << m_cpt_ll_rsp        << std::endl
+            << "# of sc_cmd accesses                     : " << m_cpt_sc_cmd        << std::endl
+            << "# of sw_cmd accesses                     : " << m_cpt_sw_cmd        << std::endl
+            << "# of nop    accesses                     : " << m_cpt_nop           << std::endl
+            << "# of eviction                            : " << m_cpt_evic          << std::endl
+            << "# of death by aging                      : " << m_cpt_death         << std::endl ;
+    }
+
+};
+
+} // namespace soclib
+
+#endif
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Index: /trunk/lib/generic_llsc_local_table/metadata/generic_llsc_local_table.sd
===================================================================
--- /trunk/lib/generic_llsc_local_table/metadata/generic_llsc_local_table.sd	(revision 291)
+++ /trunk/lib/generic_llsc_local_table/metadata/generic_llsc_local_table.sd	(revision 291)
@@ -0,0 +1,12 @@
+# -*- python -*-
+
+Module(
+    'caba:generic_llsc_local_table',
+    classname       = 'soclib::GenericLLSCLocalTable',
+    header_files    = ['../include/generic_llsc_local_table.h'],
+    tmpl_parameters = 
+        [
+            parameter.Int('nb_slots', min = 1, max = 10, default = 1),
+            parameter.Type('addr_t', default = 'sc_dt::sc_uint<40>')
+        ]
+)
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;
