Index: trunk/modules/vci_block_device_tsar/caba/metadata/vci_block_device_tsar.sd
===================================================================
--- trunk/modules/vci_block_device_tsar/caba/metadata/vci_block_device_tsar.sd	(revision 2)
+++ trunk/modules/vci_block_device_tsar/caba/metadata/vci_block_device_tsar.sd	(revision 2)
@@ -0,0 +1,43 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_block_device_tsar',
+	   classname = 'soclib::caba::VciBlockDeviceTsar',
+	   tmpl_parameters = [
+	parameter.Module('vci_param',  default = 'caba:vci_param'),
+	],
+	   header_files = ['../source/include/vci_block_device_tsar.h',
+					],
+    interface_files = [
+					   '../../include/soclib/block_device_tsar.h'
+					   ],
+	   implementation_files = ['../source/src/vci_block_device_tsar.cpp',],
+	   ports = [
+	Port('caba:vci_target', 'p_vci_target'),
+	Port('caba:vci_initiator', 'p_vci_initiator'),
+	Port('caba:bit_out', 'p_irq'),
+	Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+	Port('caba:clock_in', 'p_clk', auto = 'clock'),
+	],
+	   uses = [
+	Uses('caba:base_module'),
+	Uses('caba:vci_target_fsm', default_target = 'true', support_llsc = 'false'),
+	Uses('caba:vci_initiator_simple_read_req'),
+	Uses('caba:vci_initiator_simple_write_req'),
+	Uses('caba:vci_initiator_fsm'),
+	],
+	instance_parameters = [
+        parameter.Module('mt', typename = 'common:mapping_table', auto = 'env:mapping_table'),
+        parameter.IntTab('srcid'),
+        parameter.IntTab('tgtid'),
+        parameter.String('filename'),
+        ],
+	   extensions = [
+	'dsx:addressable=tgtid',
+	'dsx:max_segments=1',
+	'dsx:get_ident=tgtid:p_vci_target,srcid:p_vci_initiator',
+   ],
+)
Index: trunk/modules/vci_block_device_tsar/caba/source/include/vci_block_device_tsar.h
===================================================================
--- trunk/modules/vci_block_device_tsar/caba/source/include/vci_block_device_tsar.h	(revision 2)
+++ trunk/modules/vci_block_device_tsar/caba/source/include/vci_block_device_tsar.h	(revision 2)
@@ -0,0 +1,115 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *         Eric Guthmuller  <eric.guthmuller@polytechnique.edu>
+ *
+ * Maintainers: nipo eric.guthmuller@polytechnique.edu
+ */
+#ifndef SOCLIB_VCI_BLOCK_DEVICE_TSAR_H
+#define SOCLIB_VCI_BLOCK_DEVICE_TSAR_H
+
+#include <stdint.h>
+#include <systemc>
+#include "vci_target_fsm.h"
+#include "vci_initiator_fsm.h"
+#include "caba_base_module.h"
+#include "mapping_table.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+template<typename vci_param>
+class VciBlockDeviceTsar
+	: public caba::BaseModule
+{
+private:
+    soclib::caba::VciTargetFsm<vci_param, true> m_vci_target_fsm;
+    soclib::caba::VciInitiatorFsm<vci_param> m_vci_init_fsm;
+    typedef typename soclib::caba::VciInitiatorReq<vci_param> req_t;
+
+    bool on_write(int seg, typename vci_param::addr_t addr, typename vci_param::data_t data, int be);
+    bool on_read(int seg, typename vci_param::addr_t addr, typename vci_param::data_t &data);
+    void read_done( req_t *req );
+    void write_finish( req_t *req );
+    void open_finish( req_t *req );
+    void next_req();
+    void transition();
+    void genMoore();
+
+	const uint32_t m_block_size;
+    const uint32_t m_burst_size;    // Maximum size of the burst
+
+	int m_fd;
+	int m_op;
+	uint32_t m_buffer;
+	uint32_t m_count;
+	uint64_t m_device_size;
+	uint32_t m_lba;
+    int m_status;
+    uint32_t m_chunck_offset;
+    uint32_t m_transfer_size;
+	bool m_irq_enabled;
+	bool r_irq;
+
+	int m_current_op;
+
+	uint8_t *m_data;
+
+	inline void ended(int status);
+
+protected:
+    SC_HAS_PROCESS(VciBlockDeviceTsar);
+
+public:
+    sc_in<bool> p_clk;
+    sc_in<bool> p_resetn;
+    soclib::caba::VciTarget<vci_param> p_vci_target;
+    soclib::caba::VciInitiator<vci_param> p_vci_initiator;
+    sc_out<bool> p_irq;
+
+	VciBlockDeviceTsar(
+		sc_module_name name,
+		const soclib::common::MappingTable &mt,
+		const soclib::common::IntTab &srcid,
+		const soclib::common::IntTab &tgtid,
+        const std::string &filename,
+        const uint32_t block_size = 512,
+        const uint32_t burst_size = 64);
+};
+
+}}
+
+#endif /* SOCLIB_VCI_BLOCK_DEVICE_TSAR_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_block_device_tsar/caba/source/src/vci_block_device_tsar.cpp
===================================================================
--- trunk/modules/vci_block_device_tsar/caba/source/src/vci_block_device_tsar.cpp	(revision 2)
+++ trunk/modules/vci_block_device_tsar/caba/source/src/vci_block_device_tsar.cpp	(revision 2)
@@ -0,0 +1,366 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *         Eric Guthmuller  <eric.guthmuller@polytechnique.edu>, 2009
+ */
+
+#include <stdint.h>
+#include <iostream>
+#include "register.h"
+#include "../include/vci_block_device_tsar.h"
+#include <fcntl.h>
+#include "block_device_tsar.h"
+
+namespace soclib { namespace caba {
+
+#ifdef SOCLIB_MODULE_DEBUG
+    namespace {
+        const char* SoclibBlockDeviceRegisters_str[] = {
+            "BLOCK_DEVICE_BUFFER",
+            "BLOCK_DEVICE_LBA",
+            "BLOCK_DEVICE_COUNT",
+            "BLOCK_DEVICE_OP",
+            "BLOCK_DEVICE_STATUS",
+            "BLOCK_DEVICE_IRQ_ENABLE",
+            "BLOCK_DEVICE_SIZE",
+            "BLOCK_DEVICE_BLOCK_SIZE"
+        };
+        const char* SoclibBlockDeviceOp_str[] = {
+            "BLOCK_DEVICE_NOOP",
+            "BLOCK_DEVICE_READ",
+            "BLOCK_DEVICE_WRITE",
+        };
+        const char* SoclibBlockDeviceStatus_str[] = {
+            "BLOCK_DEVICE_IDLE",
+            "BLOCK_DEVICE_BUSY",
+            "BLOCK_DEVICE_READ_SUCCESS",
+            "BLOCK_DEVICE_WRITE_SUCCESS",
+            "BLOCK_DEVICE_READ_ERROR",
+            "BLOCK_DEVICE_WRITE_ERROR",
+            "BLOCK_DEVICE_ERROR",
+        };
+    }
+#endif
+
+#define tmpl(t) template<typename vci_param> t VciBlockDeviceTsar<vci_param>
+
+tmpl(void)::ended(int status)
+{
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " finished current operation ("
+        << SoclibBlockDeviceOp_str[m_current_op]
+        << ") with the status "
+        << SoclibBlockDeviceStatus_str[status]
+        << std::endl;
+#endif
+
+	if ( m_irq_enabled )
+		r_irq = true;
+	m_current_op = m_op = BLOCK_DEVICE_NOOP;
+    m_status = status;
+}
+
+tmpl(bool)::on_write(int seg, typename vci_param::addr_t addr, typename vci_param::data_t data, int be)
+{
+    int cell = (int)addr / vci_param::B;
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " write config register "
+        << SoclibBlockDeviceRegisters_str[cell]
+        << " with data 0x"
+        << std::hex << data.read()
+        << std::endl;
+#endif
+
+	switch ((enum SoclibBlockDeviceRegisters)cell) {
+    case BLOCK_DEVICE_BUFFER:
+		m_buffer = data;
+		return true;
+    case BLOCK_DEVICE_COUNT:
+        m_count = data;
+        return true;
+    case BLOCK_DEVICE_LBA:
+		m_lba = data;
+		return true;
+    case BLOCK_DEVICE_OP:
+        if ( m_status == BLOCK_DEVICE_BUSY ) {
+            std::cerr << name() << " warning: receiving a new command while busy, ignored" << std::endl;
+        } else {
+            m_op = data;
+        }
+		return true;
+    case BLOCK_DEVICE_IRQ_ENABLE:
+		m_irq_enabled = data;
+		return true;
+    default:
+        return false;
+	}
+}
+
+tmpl(bool)::on_read(int seg, typename vci_param::addr_t addr, typename vci_param::data_t &data)
+{
+    int cell = (int)addr / vci_param::B;
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " read config register "
+        << SoclibBlockDeviceRegisters_str[cell]
+        << std::endl;
+#endif
+
+	switch ((enum SoclibBlockDeviceRegisters)cell) {
+    case BLOCK_DEVICE_SIZE:
+        data = (typename vci_param::fast_data_t)m_device_size;
+        return true;
+    case BLOCK_DEVICE_BLOCK_SIZE:
+        data = m_block_size;
+        return true;
+    case BLOCK_DEVICE_STATUS:
+        data = m_status;
+        if (m_status != BLOCK_DEVICE_BUSY) {
+            m_status = BLOCK_DEVICE_IDLE;
+            r_irq = false;
+        }
+        return true;
+    default:
+        return false;
+	}
+}
+
+tmpl(void)::read_done( req_t *req )
+{
+    if ( ! req->failed() && m_chunck_offset < m_transfer_size ) {
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " completed transferring a chunck. Do now the next one..."
+        << std::endl;
+#endif
+        next_req();
+        return;
+    }
+
+	ended( req->failed() ? BLOCK_DEVICE_READ_ERROR : BLOCK_DEVICE_READ_SUCCESS );
+    delete m_data;
+	delete req;
+}
+
+tmpl(void)::write_finish( req_t *req )
+{
+    if ( ! req->failed() && m_chunck_offset < m_transfer_size ) {
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " completed transferring a chunck. Do now the next one..."
+        << std::endl;
+#endif
+        next_req();
+        return;
+    }
+
+	ended(
+        ( ! req->failed() && ::write( m_fd, (char *)m_data, m_transfer_size ) > 0 )
+        ? BLOCK_DEVICE_WRITE_SUCCESS : BLOCK_DEVICE_WRITE_ERROR );
+    delete m_data;
+	delete req;
+}
+
+tmpl(void)::next_req()
+{
+    switch (m_current_op) {
+    case BLOCK_DEVICE_READ:
+    {
+        m_transfer_size = m_count * m_block_size;
+        if ( m_chunck_offset == 0 ) {
+            if ( m_lba + m_count > m_device_size ) {
+                std::cerr << name() << " warning: trying to read beyond end of device" << std::endl;
+                ended(BLOCK_DEVICE_READ_ERROR);
+                break;
+            }
+            m_data = new uint8_t[m_transfer_size];
+            lseek(m_fd, m_lba*m_block_size, SEEK_SET);
+            int retval = ::read(m_fd, m_data, m_transfer_size);
+            if ( retval < 0 ) {
+                ended(BLOCK_DEVICE_READ_ERROR);
+                break;
+            }
+        }
+        size_t chunck_size = m_transfer_size-m_chunck_offset;
+        if( m_chunck_offset == 0 )
+            chunck_size = ((m_buffer & ~(m_burst_size-1)) + m_burst_size) - m_buffer;
+        if ( chunck_size > m_burst_size )
+            chunck_size = m_burst_size;
+        VciInitSimpleWriteReq<vci_param> *req =
+            new VciInitSimpleWriteReq<vci_param>(
+                m_buffer+m_chunck_offset, m_data+m_chunck_offset, chunck_size );
+        m_chunck_offset += chunck_size;
+        req->setDone( this, ON_T(read_done) );
+        m_vci_init_fsm.doReq( req );
+		m_status = BLOCK_DEVICE_BUSY;
+        break;
+    }
+    case BLOCK_DEVICE_WRITE:
+    {
+        m_transfer_size = m_count * m_block_size;
+        if ( m_chunck_offset == 0 ) {
+            if ( m_lba + m_count > m_device_size ) {
+                std::cerr << name() << " warning: trying to write beyond end of device" << std::endl;
+                ended(BLOCK_DEVICE_WRITE_ERROR);
+                break;
+            }
+            m_data = new uint8_t[m_transfer_size];
+            lseek(m_fd, m_lba*m_block_size, SEEK_SET);
+        }
+        size_t chunck_size = m_transfer_size-m_chunck_offset;
+        if ( (( m_buffer + m_chunck_offset ) & ( m_burst_size-1 )) )
+            chunck_size = 4;
+        if ( chunck_size < m_burst_size )
+            chunck_size = 4;
+        if ( chunck_size > m_burst_size )
+            chunck_size = m_burst_size;
+        VciInitSimpleReadReq<vci_param> *req =
+            new VciInitSimpleReadReq<vci_param>(
+                m_data+m_chunck_offset, m_buffer+m_chunck_offset, chunck_size );
+        m_chunck_offset += chunck_size;
+        req->setDone( this, ON_T(write_finish) );
+        m_vci_init_fsm.doReq( req );
+		m_status = BLOCK_DEVICE_BUSY;
+        break;
+    }
+    default:
+        ended(BLOCK_DEVICE_ERROR);
+        break;
+    }
+}
+
+tmpl(void)::transition()
+{
+	if (!p_resetn) {
+		m_vci_target_fsm.reset();
+		m_vci_init_fsm.reset();
+		r_irq = false;
+		m_irq_enabled = false;
+		m_status = BLOCK_DEVICE_IDLE;
+		return;
+	}
+
+	if ( m_current_op == BLOCK_DEVICE_NOOP &&
+		 m_op != BLOCK_DEVICE_NOOP ) {
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " launch an operation "
+        << SoclibBlockDeviceOp_str[m_op]
+        << std::endl;
+#endif
+		m_current_op = m_op;
+        m_op = BLOCK_DEVICE_NOOP;
+        m_chunck_offset = 0;
+        next_req();
+	}
+
+	m_vci_target_fsm.transition();
+	m_vci_init_fsm.transition();
+}
+
+tmpl(void)::genMoore()
+{
+	m_vci_target_fsm.genMoore();
+	m_vci_init_fsm.genMoore();
+
+	p_irq = r_irq && m_irq_enabled;
+}
+
+tmpl(/**/)::VciBlockDeviceTsar(
+    sc_module_name name,
+    const MappingTable &mt,
+    const IntTab &srcid,
+    const IntTab &tgtid,
+    const std::string &filename,
+    const uint32_t block_size,
+    const uint32_t burst_size)
+	: caba::BaseModule(name),
+	  m_vci_target_fsm(p_vci_target, mt.getSegmentList(tgtid)),
+	  m_vci_init_fsm(p_vci_initiator, mt.indexForId(srcid)),
+      m_block_size(block_size),
+      m_burst_size(burst_size),
+      p_clk("clk"),
+      p_resetn("resetn"),
+      p_vci_target("vci_target"),
+      p_vci_initiator("vci_initiator"),
+      p_irq("irq")
+{
+	m_vci_target_fsm.on_read_write(on_read, on_write);
+
+    m_fd = ::open(filename.c_str(), O_RDWR);
+    if ( m_fd < 0 ) {
+        throw soclib::exception::RunTimeError(
+            std::string("Unable to open file ")+filename);
+    }
+    m_device_size = lseek(m_fd, 0, SEEK_END) / m_block_size;
+    if ( m_device_size > ((uint64_t)1<<(vci_param::B*8)) ) {
+        std::cerr
+            << "Warning: block device " << filename
+            << " has more blocks than addressable with "
+            << (8*vci_param::B) << "." << std::endl;
+        m_device_size = ((uint64_t)1<<(vci_param::B*8));
+    }
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name
+        << " = Opened " 
+        << filename
+        << " which has "
+        << m_device_size
+        << " blocks of "
+        << m_block_size
+        << " bytes"
+        << std::endl;
+#endif
+
+	SC_METHOD(transition);
+	dont_initialize();
+	sensitive << p_clk.pos();
+
+	SC_METHOD(genMoore);
+	dont_initialize();
+	sensitive << p_clk.neg();
+}
+
+}}
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_block_device_tsar/include/soclib/block_device_tsar.h
===================================================================
--- trunk/modules/vci_block_device_tsar/include/soclib/block_device_tsar.h	(revision 2)
+++ trunk/modules/vci_block_device_tsar/include/soclib/block_device_tsar.h	(revision 2)
@@ -0,0 +1,68 @@
+/*
+ * 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *         Eric Guthmuller  <eric.guthmuller@polytechnique.edu>, 2009
+ *
+ * Maintainers: nipo eric.guthmuller@polytechnique.edu
+ */
+#ifndef BLOCK_DEVICE_TSAR_REGS_H
+#define BLOCK_DEVICE_TSAR_REGS_H
+
+enum SoclibBlockDeviceRegisters {
+    BLOCK_DEVICE_BUFFER,
+    BLOCK_DEVICE_LBA,
+    BLOCK_DEVICE_COUNT,
+    BLOCK_DEVICE_OP,
+    BLOCK_DEVICE_STATUS,
+    BLOCK_DEVICE_IRQ_ENABLE,
+    BLOCK_DEVICE_SIZE,
+    BLOCK_DEVICE_BLOCK_SIZE,
+};
+
+enum SoclibBlockDeviceOp {
+	BLOCK_DEVICE_NOOP,
+	BLOCK_DEVICE_READ,
+	BLOCK_DEVICE_WRITE,
+};
+
+enum SoclibBlockDeviceStatus {
+	BLOCK_DEVICE_IDLE,
+	BLOCK_DEVICE_BUSY,
+	BLOCK_DEVICE_READ_SUCCESS,
+	BLOCK_DEVICE_WRITE_SUCCESS,
+	BLOCK_DEVICE_READ_ERROR,
+	BLOCK_DEVICE_WRITE_ERROR,
+	BLOCK_DEVICE_ERROR,
+};
+
+#endif /* BLOCK_DEVICE_TSAR_REGS_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_block_device_tsar_v2/caba/metadata/vci_block_device_tsar_v2.sd
===================================================================
--- trunk/modules/vci_block_device_tsar_v2/caba/metadata/vci_block_device_tsar_v2.sd	(revision 2)
+++ trunk/modules/vci_block_device_tsar_v2/caba/metadata/vci_block_device_tsar_v2.sd	(revision 2)
@@ -0,0 +1,43 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_block_device_tsar_v2',
+	   classname = 'soclib::caba::VciBlockDeviceTsarV2',
+	   tmpl_parameters = [
+	parameter.Module('vci_param',  default = 'caba:vci_param'),
+	],
+	   header_files = ['../source/include/vci_block_device_tsar_v2.h',
+					],
+    interface_files = [
+					   '../../include/soclib/block_device_tsar_v2.h'
+					   ],
+	   implementation_files = ['../source/src/vci_block_device_tsar_v2.cpp',],
+	   ports = [
+	Port('caba:vci_target', 'p_vci_target'),
+	Port('caba:vci_initiator', 'p_vci_initiator'),
+	Port('caba:bit_out', 'p_irq'),
+	Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+	Port('caba:clock_in', 'p_clk', auto = 'clock'),
+	],
+	   uses = [
+	Uses('caba:base_module'),
+	Uses('caba:vci_target_fsm', default_target = 'true', support_llsc = 'false'),
+	Uses('caba:vci_initiator_simple_read_req'),
+	Uses('caba:vci_initiator_simple_write_req'),
+	Uses('caba:vci_initiator_fsm'),
+	],
+	instance_parameters = [
+        parameter.Module('mt', typename = 'common:mapping_table', auto = 'env:mapping_table'),
+        parameter.IntTab('srcid'),
+        parameter.IntTab('tgtid'),
+        parameter.String('filename'),
+        ],
+	   extensions = [
+	'dsx:addressable=tgtid',
+	'dsx:max_segments=1',
+	'dsx:get_ident=tgtid:p_vci_target,srcid:p_vci_initiator',
+   ],
+)
Index: trunk/modules/vci_block_device_tsar_v2/caba/source/include/vci_block_device_tsar_v2.h
===================================================================
--- trunk/modules/vci_block_device_tsar_v2/caba/source/include/vci_block_device_tsar_v2.h	(revision 2)
+++ trunk/modules/vci_block_device_tsar_v2/caba/source/include/vci_block_device_tsar_v2.h	(revision 2)
@@ -0,0 +1,115 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *         Eric Guthmuller  <eric.guthmuller@polytechnique.edu>
+ *
+ * Maintainers: nipo eric.guthmuller@polytechnique.edu
+ */
+#ifndef SOCLIB_VCI_BLOCK_DEVICE_TSAR_V2_H
+#define SOCLIB_VCI_BLOCK_DEVICE_TSAR_V2_H
+
+#include <stdint.h>
+#include <systemc>
+#include "vci_target_fsm.h"
+#include "vci_initiator_fsm.h"
+#include "caba_base_module.h"
+#include "mapping_table.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+template<typename vci_param>
+class VciBlockDeviceTsarV2
+	: public caba::BaseModule
+{
+private:
+    soclib::caba::VciTargetFsm<vci_param, true> m_vci_target_fsm;
+    soclib::caba::VciInitiatorFsm<vci_param> m_vci_init_fsm;
+    typedef typename soclib::caba::VciInitiatorReq<vci_param> req_t;
+
+    bool on_write(int seg, typename vci_param::addr_t addr, typename vci_param::data_t data, int be);
+    bool on_read(int seg, typename vci_param::addr_t addr, typename vci_param::data_t &data);
+    void read_done( req_t *req );
+    void write_finish( req_t *req );
+    void open_finish( req_t *req );
+    void next_req();
+    void transition();
+    void genMoore();
+
+	const uint32_t m_block_size;
+    const uint32_t m_burst_size;    // Maximum size of the burst
+
+	int m_fd;
+	int m_op;
+	uint32_t m_buffer;
+	uint32_t m_count;
+	uint64_t m_device_size;
+	uint32_t m_lba;
+    int m_status;
+    uint32_t m_chunck_offset;
+    uint32_t m_transfer_size;
+	bool m_irq_enabled;
+	bool r_irq;
+
+	int m_current_op;
+
+	uint8_t *m_data;
+
+	inline void ended(int status);
+
+protected:
+    SC_HAS_PROCESS(VciBlockDeviceTsarV2);
+
+public:
+    sc_in<bool> p_clk;
+    sc_in<bool> p_resetn;
+    soclib::caba::VciTarget<vci_param> p_vci_target;
+    soclib::caba::VciInitiator<vci_param> p_vci_initiator;
+    sc_out<bool> p_irq;
+
+	VciBlockDeviceTsarV2(
+		sc_module_name name,
+		const soclib::common::MappingTable &mt,
+		const soclib::common::IntTab &srcid,
+		const soclib::common::IntTab &tgtid,
+        const std::string &filename,
+        const uint32_t block_size = 512,
+        const uint32_t burst_size = 64);
+};
+
+}}
+
+#endif /* SOCLIB_VCI_BLOCK_DEVICE_TSAR_V2_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_block_device_tsar_v2/caba/source/src/vci_block_device_tsar_v2.cpp
===================================================================
--- trunk/modules/vci_block_device_tsar_v2/caba/source/src/vci_block_device_tsar_v2.cpp	(revision 2)
+++ trunk/modules/vci_block_device_tsar_v2/caba/source/src/vci_block_device_tsar_v2.cpp	(revision 2)
@@ -0,0 +1,364 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *         Eric Guthmuller  <eric.guthmuller@polytechnique.edu>, 2009
+ */
+
+#include <stdint.h>
+#include <iostream>
+#include "register.h"
+#include "../include/vci_block_device_tsar_v2.h"
+#include <fcntl.h>
+#include "block_device_tsar_v2.h"
+
+namespace soclib { namespace caba {
+
+#ifdef SOCLIB_MODULE_DEBUG
+    namespace {
+        const char* SoclibBlockDeviceRegisters_str[] = {
+            "BLOCK_DEVICE_BUFFER",
+            "BLOCK_DEVICE_LBA",
+            "BLOCK_DEVICE_COUNT",
+            "BLOCK_DEVICE_OP",
+            "BLOCK_DEVICE_STATUS",
+            "BLOCK_DEVICE_IRQ_ENABLE",
+            "BLOCK_DEVICE_SIZE",
+            "BLOCK_DEVICE_BLOCK_SIZE"
+        };
+        const char* SoclibBlockDeviceOp_str[] = {
+            "BLOCK_DEVICE_NOOP",
+            "BLOCK_DEVICE_READ",
+            "BLOCK_DEVICE_WRITE",
+        };
+        const char* SoclibBlockDeviceStatus_str[] = {
+            "BLOCK_DEVICE_IDLE",
+            "BLOCK_DEVICE_BUSY",
+            "BLOCK_DEVICE_READ_SUCCESS",
+            "BLOCK_DEVICE_WRITE_SUCCESS",
+            "BLOCK_DEVICE_READ_ERROR",
+            "BLOCK_DEVICE_WRITE_ERROR",
+            "BLOCK_DEVICE_ERROR",
+        };
+    }
+#endif
+
+#define tmpl(t) template<typename vci_param> t VciBlockDeviceTsarV2<vci_param>
+
+tmpl(void)::ended(int status)
+{
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " finished current operation ("
+        << SoclibBlockDeviceOp_str[m_current_op]
+        << ") with the status "
+        << SoclibBlockDeviceStatus_str[status]
+        << std::endl;
+#endif
+
+	if ( m_irq_enabled )
+		r_irq = true;
+	m_current_op = m_op = BLOCK_DEVICE_NOOP;
+    m_status = status;
+}
+
+tmpl(bool)::on_write(int seg, typename vci_param::addr_t addr, typename vci_param::data_t data, int be)
+{
+    int cell = (int)addr / vci_param::B;
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " write config register "
+        << SoclibBlockDeviceRegisters_str[cell]
+        << " with data 0x"
+        << std::hex << data.read()
+        << std::endl;
+#endif
+
+	switch ((enum SoclibBlockDeviceRegisters)cell) {
+    case BLOCK_DEVICE_BUFFER:
+		m_buffer = data;
+		return true;
+    case BLOCK_DEVICE_COUNT:
+        m_count = data;
+        return true;
+    case BLOCK_DEVICE_LBA:
+		m_lba = data;
+		return true;
+    case BLOCK_DEVICE_OP:
+        if ( m_status == BLOCK_DEVICE_BUSY ) {
+            std::cerr << name() << " warning: receiving a new command while busy, ignored" << std::endl;
+        } else {
+            m_op = data;
+        }
+		return true;
+    case BLOCK_DEVICE_IRQ_ENABLE:
+		m_irq_enabled = data;
+		return true;
+    default:
+        return false;
+	}
+}
+
+tmpl(bool)::on_read(int seg, typename vci_param::addr_t addr, typename vci_param::data_t &data)
+{
+    int cell = (int)addr / vci_param::B;
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " read config register "
+        << SoclibBlockDeviceRegisters_str[cell]
+        << std::endl;
+#endif
+
+	switch ((enum SoclibBlockDeviceRegisters)cell) {
+    case BLOCK_DEVICE_SIZE:
+        data = (typename vci_param::fast_data_t)m_device_size;
+        return true;
+    case BLOCK_DEVICE_BLOCK_SIZE:
+        data = m_block_size;
+        return true;
+    case BLOCK_DEVICE_STATUS:
+        data = m_status;
+        if (m_status != BLOCK_DEVICE_BUSY) {
+            m_status = BLOCK_DEVICE_IDLE;
+            r_irq = false;
+        }
+        return true;
+    default:
+        return false;
+	}
+}
+
+tmpl(void)::read_done( req_t *req )
+{
+    if ( ! req->failed() && m_chunck_offset < m_transfer_size ) {
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " completed transferring a chunck. Do now the next one..."
+        << std::endl;
+#endif
+        next_req();
+        return;
+    }
+
+	ended( req->failed() ? BLOCK_DEVICE_READ_ERROR : BLOCK_DEVICE_READ_SUCCESS );
+    delete m_data;
+	delete req;
+}
+
+tmpl(void)::write_finish( req_t *req )
+{
+    if ( ! req->failed() && m_chunck_offset < m_transfer_size ) {
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " completed transferring a chunck. Do now the next one..."
+        << std::endl;
+#endif
+        next_req();
+        return;
+    }
+
+	ended(
+        ( ! req->failed() && ::write( m_fd, (char *)m_data, m_transfer_size ) > 0 )
+        ? BLOCK_DEVICE_WRITE_SUCCESS : BLOCK_DEVICE_WRITE_ERROR );
+    delete m_data;
+	delete req;
+}
+
+tmpl(void)::next_req()
+{
+    switch (m_current_op) {
+    case BLOCK_DEVICE_READ:
+    {
+        m_transfer_size = m_count * m_block_size;
+        if ( m_chunck_offset == 0 ) {
+            if ( m_lba + m_count > m_device_size ) {
+                std::cerr << name() << " warning: trying to read beyond end of device" << std::endl;
+                ended(BLOCK_DEVICE_READ_ERROR);
+                break;
+            }
+            m_data = new uint8_t[m_transfer_size];
+            lseek(m_fd, m_lba*m_block_size, SEEK_SET);
+            int retval = ::read(m_fd, m_data, m_transfer_size);
+            if ( retval < 0 ) {
+                ended(BLOCK_DEVICE_READ_ERROR);
+                break;
+            }
+        }
+        size_t chunck_size = m_transfer_size-m_chunck_offset;
+        if( m_chunck_offset == 0 )
+            chunck_size = ((m_buffer & ~(m_burst_size-1)) + m_burst_size) - m_buffer;
+        if ( chunck_size > m_burst_size )
+            chunck_size = m_burst_size;
+        VciInitSimpleWriteReq<vci_param> *req =
+            new VciInitSimpleWriteReq<vci_param>(
+                m_buffer+m_chunck_offset, m_data+m_chunck_offset, chunck_size );
+        m_chunck_offset += chunck_size;
+        req->setDone( this, ON_T(read_done) );
+        m_vci_init_fsm.doReq( req );
+		m_status = BLOCK_DEVICE_BUSY;
+        break;
+    }
+    case BLOCK_DEVICE_WRITE:
+    {
+        m_transfer_size = m_count * m_block_size;
+        if ( m_chunck_offset == 0 ) {
+            if ( m_lba + m_count > m_device_size ) {
+                std::cerr << name() << " warning: trying to write beyond end of device" << std::endl;
+                ended(BLOCK_DEVICE_WRITE_ERROR);
+                break;
+            }
+            m_data = new uint8_t[m_transfer_size];
+            lseek(m_fd, m_lba*m_block_size, SEEK_SET);
+        }
+        size_t chunck_size = m_transfer_size-m_chunck_offset;
+        if ( (( m_buffer + m_chunck_offset ) & ( m_burst_size-1 )) )
+            chunck_size = m_burst_size - (( m_buffer + m_chunck_offset ) & ( m_burst_size-1 ));
+        if ( chunck_size > m_burst_size )
+            chunck_size = m_burst_size;
+        VciInitSimpleReadReq<vci_param> *req =
+            new VciInitSimpleReadReq<vci_param>(
+                m_data+m_chunck_offset, m_buffer+m_chunck_offset, chunck_size );
+        m_chunck_offset += chunck_size;
+        req->setDone( this, ON_T(write_finish) );
+        m_vci_init_fsm.doReq( req );
+		m_status = BLOCK_DEVICE_BUSY;
+        break;
+    }
+    default:
+        ended(BLOCK_DEVICE_ERROR);
+        break;
+    }
+}
+
+tmpl(void)::transition()
+{
+	if (!p_resetn) {
+		m_vci_target_fsm.reset();
+		m_vci_init_fsm.reset();
+		r_irq = false;
+		m_irq_enabled = false;
+		m_status = BLOCK_DEVICE_IDLE;
+		return;
+	}
+
+	if ( m_current_op == BLOCK_DEVICE_NOOP &&
+		 m_op != BLOCK_DEVICE_NOOP ) {
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name()
+        << " launch an operation "
+        << SoclibBlockDeviceOp_str[m_op]
+        << std::endl;
+#endif
+		m_current_op = m_op;
+        m_op = BLOCK_DEVICE_NOOP;
+        m_chunck_offset = 0;
+        next_req();
+	}
+
+	m_vci_target_fsm.transition();
+	m_vci_init_fsm.transition();
+}
+
+tmpl(void)::genMoore()
+{
+	m_vci_target_fsm.genMoore();
+	m_vci_init_fsm.genMoore();
+
+	p_irq = r_irq && m_irq_enabled;
+}
+
+tmpl(/**/)::VciBlockDeviceTsarV2(
+    sc_module_name name,
+    const MappingTable &mt,
+    const IntTab &srcid,
+    const IntTab &tgtid,
+    const std::string &filename,
+    const uint32_t block_size,
+    const uint32_t burst_size)
+	: caba::BaseModule(name),
+	  m_vci_target_fsm(p_vci_target, mt.getSegmentList(tgtid)),
+	  m_vci_init_fsm(p_vci_initiator, mt.indexForId(srcid)),
+      m_block_size(block_size),
+      m_burst_size(burst_size),
+      p_clk("clk"),
+      p_resetn("resetn"),
+      p_vci_target("vci_target"),
+      p_vci_initiator("vci_initiator"),
+      p_irq("irq")
+{
+	m_vci_target_fsm.on_read_write(on_read, on_write);
+
+    m_fd = ::open(filename.c_str(), O_RDWR);
+    if ( m_fd < 0 ) {
+        throw soclib::exception::RunTimeError(
+            std::string("Unable to open file ")+filename);
+    }
+    m_device_size = lseek(m_fd, 0, SEEK_END) / m_block_size;
+    if ( m_device_size > ((uint64_t)1<<(vci_param::B*8)) ) {
+        std::cerr
+            << "Warning: block device " << filename
+            << " has more blocks than addressable with "
+            << (8*vci_param::B) << "." << std::endl;
+        m_device_size = ((uint64_t)1<<(vci_param::B*8));
+    }
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout 
+        << name
+        << " = Opened " 
+        << filename
+        << " which has "
+        << m_device_size
+        << " blocks of "
+        << m_block_size
+        << " bytes"
+        << std::endl;
+#endif
+
+	SC_METHOD(transition);
+	dont_initialize();
+	sensitive << p_clk.pos();
+
+	SC_METHOD(genMoore);
+	dont_initialize();
+	sensitive << p_clk.neg();
+}
+
+}}
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_block_device_tsar_v2/include/soclib/block_device_tsar_v2.h
===================================================================
--- trunk/modules/vci_block_device_tsar_v2/include/soclib/block_device_tsar_v2.h	(revision 2)
+++ trunk/modules/vci_block_device_tsar_v2/include/soclib/block_device_tsar_v2.h	(revision 2)
@@ -0,0 +1,68 @@
+/*
+ * 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *         Eric Guthmuller  <eric.guthmuller@polytechnique.edu>, 2009
+ *
+ * Maintainers: nipo eric.guthmuller@polytechnique.edu
+ */
+#ifndef BLOCK_DEVICE_TSAR_V2_REGS_H
+#define BLOCK_DEVICE_TSAR_V2_REGS_H
+
+enum SoclibBlockDeviceRegisters {
+    BLOCK_DEVICE_BUFFER,
+    BLOCK_DEVICE_LBA,
+    BLOCK_DEVICE_COUNT,
+    BLOCK_DEVICE_OP,
+    BLOCK_DEVICE_STATUS,
+    BLOCK_DEVICE_IRQ_ENABLE,
+    BLOCK_DEVICE_SIZE,
+    BLOCK_DEVICE_BLOCK_SIZE,
+};
+
+enum SoclibBlockDeviceOp {
+	BLOCK_DEVICE_NOOP,
+	BLOCK_DEVICE_READ,
+	BLOCK_DEVICE_WRITE,
+};
+
+enum SoclibBlockDeviceStatus {
+	BLOCK_DEVICE_IDLE,
+	BLOCK_DEVICE_BUSY,
+	BLOCK_DEVICE_READ_SUCCESS,
+	BLOCK_DEVICE_WRITE_SUCCESS,
+	BLOCK_DEVICE_READ_ERROR,
+	BLOCK_DEVICE_WRITE_ERROR,
+	BLOCK_DEVICE_ERROR,
+};
+
+#endif /* BLOCK_DEVICE_TSAR_V2_REGS_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_cc_vcache_wrapper2/caba/metadata/vci_cc_vcache_wrapper2.sd
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper2/caba/metadata/vci_cc_vcache_wrapper2.sd	(revision 2)
+++ trunk/modules/vci_cc_vcache_wrapper2/caba/metadata/vci_cc_vcache_wrapper2.sd	(revision 2)
@@ -0,0 +1,59 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_cc_vcache_wrapper2',
+	classname = 'soclib::caba::VciCcVCacheWrapper2',
+	   tmpl_parameters = [
+	parameter.Module('vci_param', default = 'caba:vci_param'),
+	parameter.Module('iss_t'),
+	],
+	header_files = [
+	'../source/include/vci_cc_vcache_wrapper2.h',
+	],
+	implementation_files = [
+	'../source/src/vci_cc_vcache_wrapper2.cpp',
+	],
+	uses = [
+	Uses('caba:base_module'),
+	Uses('caba:write_buffer'),
+	Uses('caba:generic_tlb', addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', parameter.Reference('addr_size'))),
+	Uses('caba:generic_cache', addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', parameter.Reference('addr_size'))),
+	Uses('common:address_masking_table', data_t = parameter.StringExt('sc_dt::sc_uint<%d> ', parameter.Reference('addr_size'))),
+	Uses('common:iss2'),
+	Uses('common:mapping_table'),
+	],
+	ports = [
+	Port('caba:vci_initiator', 'p_vci_ini'),
+	Port('caba:vci_target', 'p_vci_tgt'),
+	Port('caba:bit_in','p_irq', parameter.Constant('n_irq')),
+	Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+	Port('caba:clock_in', 'p_clk', auto = 'clock'),
+	],
+	instance_parameters = [
+	parameter.Int('proc_id'),
+	parameter.Module('mt', 'common:mapping_table', auto='env:mapping_table'),
+	parameter.Module('mc', 'common:mapping_table', auto='env:mapping_table'),
+	parameter.IntTab('initiator_index'),
+	parameter.IntTab('target_index'),
+    	parameter.Int('itlb_ways'),
+    	parameter.Int('itlb_sets'),
+    	parameter.Int('dtlb_ways'),
+    	parameter.Int('dtlb_sets'),
+    	parameter.Int('icache_ways'),
+    	parameter.Int('icache_sets'),
+    	parameter.Int('icache_words'),
+    	parameter.Int('dcache_ways'),
+    	parameter.Int('dcache_sets'),
+    	parameter.Int('dcache_words'),
+    	parameter.Int('write_buf_size'),
+	],
+	   extensions = [
+	'dsx:get_ident=initiator_index:p_vci_ini',
+	'dsx:cpu=wrapper:iss_t',
+	'dsx:mapping_type=processor:proc_id',
+   ],
+)
+
Index: trunk/modules/vci_cc_vcache_wrapper2/caba/source/include/vci_cc_vcache_wrapper2.h
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper2/caba/source/include/vci_cc_vcache_wrapper2.h	(revision 2)
+++ trunk/modules/vci_cc_vcache_wrapper2/caba/source/include/vci_cc_vcache_wrapper2.h	(revision 2)
@@ -0,0 +1,549 @@
+/* -*- c++ -*-
+ * File : vci_cc_vcache_wrapper2.h
+ * Copyright (c) UPMC, Lip6, SoC
+ * Authors : Alain GREINER, Yang GAO
+ *
+ * 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
+ */
+ 
+#ifndef SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER2_H
+#define SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER2_H
+
+#include <inttypes.h>
+#include <systemc>
+#include "caba_base_module.h"
+#include "write_buffer.h"
+#include "generic_cache.h"
+#include "vci_initiator.h"
+#include "vci_target.h"
+#include "mapping_table.h"
+#include "generic_tlb.h"
+#include "static_assert.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+////////////////////////////////////////////
+template<typename vci_param, typename iss_t>
+class VciCcVCacheWrapper2
+////////////////////////////////////////////
+    : public soclib::caba::BaseModule
+{
+    typedef uint32_t vaddr_t;
+    typedef uint32_t data_t;
+    typedef uint32_t tag_t;
+    typedef uint32_t type_t;
+    typedef typename iss_t::DataOperationType data_op_t;
+
+    typedef typename vci_param::addr_t  paddr_t;
+    typedef typename vci_param::be_t    vci_be_t;
+	typedef typename vci_param::srcid_t vci_srcid_t;
+	typedef typename vci_param::trdid_t vci_trdid_t;
+	typedef typename vci_param::pktid_t vci_pktid_t;
+	typedef typename vci_param::plen_t  vci_plen_t;
+
+    enum icache_fsm_state_e {  
+        ICACHE_IDLE,                // 00
+        ICACHE_BIS,                 // 01
+        ICACHE_TLB1_READ,           // 02
+        ICACHE_TLB1_WRITE,          // 03
+        ICACHE_TLB1_UPDT,           // 04
+        ICACHE_TLB2_READ,           // 05
+        ICACHE_TLB2_WRITE,          // 06
+        ICACHE_TLB2_UPDT,           // 07
+        ICACHE_SW_FLUSH,            // 08
+        ICACHE_CACHE_FLUSH,         // 09
+        ICACHE_TLB_INVAL,           // 0a
+        ICACHE_CACHE_INVAL,         // 0b
+        ICACHE_MISS_WAIT,           // 0c
+        ICACHE_UNC_WAIT,            // 0d
+        ICACHE_MISS_UPDT,           // 0e
+        ICACHE_ERROR,               // 0f
+        ICACHE_CC_INVAL,            // 10
+        ICACHE_TLB_CC_INVAL,        // 11
+        ICACHE_TLB_FLUSH,           // 12
+    };
+
+    enum dcache_fsm_state_e {  
+        DCACHE_IDLE,                // 00
+        DCACHE_BIS,                 // 01
+        DCACHE_DTLB1_READ_CACHE,    // 02
+        DCACHE_TLB1_LL_WAIT,        // 03
+        DCACHE_TLB1_SC_WAIT,        // 04
+        DCACHE_TLB1_READ,           // 05
+        DCACHE_TLB1_READ_UPDT,      // 06
+        DCACHE_TLB1_UPDT,           // 07
+        DCACHE_DTLB2_READ_CACHE,    // 08
+        DCACHE_TLB2_LL_WAIT,        // 09
+        DCACHE_TLB2_SC_WAIT,        // 0a
+        DCACHE_TLB2_READ,           // 0b
+        DCACHE_TLB2_READ_UPDT,      // 0c
+        DCACHE_TLB2_UPDT,           // 0d
+        DCACHE_CTXT_SWITCH,         // 0e
+        DCACHE_ICACHE_FLUSH,        // 0f
+        DCACHE_DCACHE_FLUSH,        // 10
+        DCACHE_ITLB_INVAL,          // 11
+        DCACHE_DTLB_INVAL,          // 12
+        DCACHE_ICACHE_INVAL,        // 13
+        DCACHE_DCACHE_INVAL,        // 14
+        DCACHE_DCACHE_SYNC,         // 15
+        DCACHE_LL_DIRTY_WAIT,       // 16
+        DCACHE_SC_DIRTY_WAIT,       // 17
+        DCACHE_WRITE_UPDT,          // 18
+        DCACHE_WRITE_DIRTY,         // 19
+        DCACHE_WRITE_REQ,           // 1a
+        DCACHE_MISS_WAIT,           // 1b
+        DCACHE_MISS_UPDT,           // 1c
+        DCACHE_UNC_WAIT,            // 1d
+        DCACHE_ERROR,               // 1e
+        DCACHE_ITLB_READ,           // 1f
+        DCACHE_ITLB_UPDT,           // 20
+        DCACHE_ITLB_LL_WAIT,        // 21
+        DCACHE_ITLB_SC_WAIT,        // 22
+        DCACHE_CC_CHECK,            // 23
+        DCACHE_CC_INVAL,            // 24
+        DCACHE_CC_UPDT,             // 25
+        DCACHE_CC_NOP,              // 26
+        DCACHE_TLB_CC_INVAL,        // 27
+        DCACHE_ITLB_CLEANUP,        // 28
+    };
+
+    enum cmd_fsm_state_e {      
+        CMD_IDLE,                   // 00
+        CMD_ITLB_READ,              // 01
+        CMD_ITLB_ACC_LL,            // 02
+        CMD_ITLB_ACC_SC,            // 03
+        CMD_INS_MISS,               // 04
+        CMD_INS_UNC,                // 05
+        CMD_DTLB_READ,              // 06
+        CMD_DTLB_ACC_LL,            // 07
+        CMD_DTLB_ACC_SC,            // 08
+        CMD_DTLB_DIRTY_LL,          // 09
+        CMD_DTLB_DIRTY_SC,          // 0a
+        CMD_DATA_UNC,               // 0b
+        CMD_DATA_MISS,              // 0c
+        CMD_DATA_WRITE,             // 0d
+        CMD_INS_CLEANUP,            // 0e
+        CMD_DATA_CLEANUP,           // 0f
+    };
+
+    enum rsp_fsm_state_e {       
+        RSP_IDLE,                   // 00
+        RSP_ITLB_READ,              // 01
+        RSP_ITLB_ACC_LL,            // 02
+        RSP_ITLB_ACC_SC,            // 03
+        RSP_INS_MISS,               // 04
+        RSP_INS_UNC,                // 05
+        RSP_DTLB_READ,              // 06
+        RSP_DTLB_ACC_LL,            // 07
+        RSP_DTLB_ACC_SC,            // 08
+        RSP_DTLB_DIRTY_LL,          // 09
+        RSP_DTLB_DIRTY_SC,          // 0a
+        RSP_DATA_MISS,              // 0b
+        RSP_DATA_UNC,               // 0c
+        RSP_DATA_WRITE,             // 0d
+        RSP_INS_CLEANUP,            // 0e
+        RSP_DATA_CLEANUP,           // 0f
+    };
+
+    enum tgt_fsm_state_e {  
+        TGT_IDLE,                   // 00
+        TGT_UPDT_WORD,              // 01
+        TGT_UPDT_DATA,              // 02
+        TGT_REQ_BROADCAST,          // 03
+        TGT_REQ_DCACHE,             // 04
+        TGT_RSP_BROADCAST,          // 05
+        TGT_RSP_DCACHE,             // 06
+    };
+
+    enum inval_itlb_fsm_state_e {
+        INVAL_ITLB_IDLE,            // 00
+        INVAL_ITLB_CHECK,           // 01
+        INVAL_ITLB_INVAL,           // 02
+        INVAL_ITLB_CLEAR,           // 03
+    };
+
+    enum inval_dtlb_fsm_state_e {
+        INVAL_DTLB_IDLE,            // 00
+        INVAL_DTLB_CHECK,           // 01
+        INVAL_DTLB_INVAL,           // 02
+        INVAL_DTLB_CLEAR,           // 03
+    };
+
+    // TLB Mode ITLB / DTLB / ICACHE / DCACHE
+    enum {          
+        ALL_DEACTIVE = 0x0000,   // TLBs disactive caches disactive
+        INS_TLB_MASK    = 0x8,
+        DATA_TLB_MASK   = 0x4,
+        INS_CACHE_MASK  = 0x2,
+        DATA_CACHE_MASK = 0x1,
+    };
+
+    // Error Type
+    enum mmu_error_type_e {
+        MMU_NONE                      = 0x0000, // None
+        MMU_WRITE_PT1_UNMAPPED 	      = 0x0001, // Write access of Page fault on Page Table 1          (non fatal error)
+        MMU_WRITE_PT2_UNMAPPED 	      = 0x0002, // Write access of Page fault on Page Table 2          (non fatal error)
+        MMU_WRITE_PRIVILEGE_VIOLATION = 0x0004, // Write access of Protected access in user mode       (user error)
+        MMU_WRITE_ACCES_VIOLATION 	  = 0x0008, // Write access of write access to a non writable page (user error)
+        MMU_WRITE_UNDEFINED_XTN 	  = 0x0020, // Write access of undefined external access address   (user error)
+        MMU_WRITE_PT1_ILLEGAL_ACCESS  = 0x0040, // Write access of Bus Error accessing Table 1         (kernel error)
+        MMU_WRITE_PT2_ILLEGAL_ACCESS  = 0x0080, // Write access of Bus Error accessing Table 2         (kernel error)
+        MMU_WRITE_DATA_ILLEGAL_ACCESS = 0x0100, // Write access of Bus Error in cache access           (kernel error)
+        MMU_READ_PT1_UNMAPPED 	      = 0x1001, // Read access of Page fault on Page Table 1  	       (non fatal error)
+        MMU_READ_PT2_UNMAPPED 	      = 0x1002, // Read access of Page fault on Page Table 2  	       (non fatal error)
+        MMU_READ_PRIVILEGE_VIOLATION  = 0x1004, // Read access of Protected access in user mode 	   (user error)
+        MMU_READ_EXEC_VIOLATION 	  = 0x1010, // Exec access to a non exec page                      (user error)
+        MMU_READ_UNDEFINED_XTN 	      = 0x1020, // Read access of Undefined external access address    (user error)
+        MMU_READ_PT1_ILLEGAL_ACCESS   = 0x1040, // Read access of Bus Error in Table1 access           (kernel error)
+        MMU_READ_PT2_ILLEGAL_ACCESS   = 0x1080, // Read access of Bus Error in Table2 access 	       (kernel error)
+        MMU_READ_DATA_ILLEGAL_ACCESS  = 0x1100, // Read access of Bus Error in cache access 	       (kernel error)
+    };
+
+public:
+    sc_in<bool>                             p_clk;
+    sc_in<bool>                             p_resetn;
+    sc_in<bool>                             p_irq[iss_t::n_irq];
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini;
+    soclib::caba::VciTarget<vci_param>      p_vci_tgt;
+
+private:
+    // STRUCTURAL PARAMETERS
+    soclib::common::AddressDecodingTable<uint32_t, bool>    m_cacheability_table;
+    const soclib::common::Segment                           m_segment;
+    iss_t                                                   m_iss;   
+    const vci_srcid_t                                       m_srcid;
+
+    const size_t  m_itlb_ways;
+    const size_t  m_itlb_sets;
+
+    const size_t  m_dtlb_ways;
+    const size_t  m_dtlb_sets;
+
+    const size_t  m_icache_ways;
+    const size_t  m_icache_sets;
+    const size_t  m_icache_yzmask;
+    const size_t  m_icache_words;
+
+    const size_t  m_dcache_ways;
+    const size_t  m_dcache_sets;
+    const size_t  m_dcache_yzmask;
+    const size_t  m_dcache_words;
+
+    const size_t  m_write_buf_size;  
+    const size_t  m_paddr_nbits;  
+
+    // instruction and data vcache tlb instances 
+    soclib::caba::GenericCcTlb<paddr_t>    icache_tlb;
+    soclib::caba::GenericCcTlb<paddr_t>    dcache_tlb;
+
+    sc_signal<vaddr_t>      r_mmu_ptpr;             // page table pointer register
+    sc_signal<int>          r_mmu_mode;             // tlb mode register
+    sc_signal<int>          r_mmu_params;           // mmu parameters register
+    sc_signal<int>          r_mmu_release;          // mmu release register
+
+    // DCACHE FSM REGISTERS
+    sc_signal<int>          r_dcache_fsm;               // state register
+    sc_signal<paddr_t>      r_dcache_paddr_save;        // physical address
+    sc_signal<data_t>       r_dcache_wdata_save;        // write data
+    sc_signal<data_t>       r_dcache_rdata_save;        // read data
+    sc_signal<type_t>       r_dcache_type_save;         // access type
+    sc_signal<vci_be_t>     r_dcache_be_save;           // byte enable
+    sc_signal<bool>         r_dcache_cached_save;       // used by the write buffer
+    sc_signal<paddr_t>      r_dcache_tlb_paddr;         // physical address of tlb miss
+    sc_signal<bool>         r_dcache_dirty_save;        // used for TLB dirty bit update
+    sc_signal<size_t>       r_dcache_tlb_set_save;      // used for TLB dirty bit update
+    sc_signal<size_t>       r_dcache_tlb_way_save;      // used for TLB dirty bit update
+    sc_signal<vaddr_t>      r_dcache_id1_save;          // used by the PT1 bypass
+    sc_signal<paddr_t>      r_dcache_ptba_save;         // used by the PT1 bypass
+    sc_signal<bool>         r_dcache_ptba_ok;           // used by the PT1 bypass
+    sc_signal<data_t>       r_dcache_pte_update;        // used for page table update
+    sc_signal<data_t>       r_dcache_ppn_update;        // used for physical page number update 
+    sc_signal<tag_t>        r_dcache_ppn_save;          // used for speculative cache access
+    sc_signal<tag_t>        r_dcache_vpn_save;          // used for speculative cache access
+    sc_signal<bool>         r_dtlb_translation_valid;   // used for speculative address
+    sc_signal<bool>         r_dcache_buf_unc_valid;     // used for uncached read
+    sc_signal<bool>         r_dcache_hit_p_save;        // used to save hit_p in case BIS
+
+    sc_signal<data_t>       r_dcache_error_type;        // software visible register
+    sc_signal<vaddr_t>      r_dcache_bad_vaddr;         // software visible register 
+
+    sc_signal<bool>         r_dcache_miss_req;          // used for cached read miss
+    sc_signal<bool>         r_dcache_unc_req;           // used for uncached read miss
+    sc_signal<bool>         r_dcache_write_req;         // used for write 
+    sc_signal<bool>         r_dcache_tlb_read_req;      // used for tlb ptba or pte read
+
+    sc_signal<bool>         r_dcache_llsc_reserved;     // used for check address reserved
+    sc_signal<paddr_t>      r_dcache_llsc_addr_save;    // used for save llsc address
+ 
+    sc_signal<bool>         r_dcache_tlb_ll_acc_req;    // used for tlb access bit update
+    sc_signal<bool>         r_dcache_tlb_sc_acc_req;    // used for tlb access bit update
+    sc_signal<bool>         r_dcache_tlb_ll_dirty_req;  // used for tlb dirty bit update 
+    sc_signal<bool>         r_dcache_tlb_sc_dirty_req;  // used for tlb dirty bit update 
+    sc_signal<bool>         r_dcache_tlb_ptba_read;     // used for tlb ptba read when write dirty bit 
+    sc_signal<bool>         r_dcache_xtn_req;           // used for xtn write for ICACHE
+
+    bool                    *r_dcache_in_itlb;          // indicates some words of dcache line in ins TLB 
+    bool                    *r_dcache_in_dtlb;          // indicates some words of dcache line in data TLB 
+
+    // coherence registers
+    sc_signal<int>          r_dcache_fsm_save;          // state save register
+    sc_signal<size_t>       r_dcache_way;
+    sc_signal<size_t>       r_dcache_set;
+    sc_signal<bool>         r_dcache_cleanup_req;       // data cleanup request
+    sc_signal<paddr_t>      r_dcache_cleanup_line;      // data cleanup NLINE
+    sc_signal<bool>         r_dcache_inval_rsp;         // data cache invalidate
+
+    // ICACHE FSM REGISTERS
+    sc_signal<int>          r_icache_fsm;               // state register
+    sc_signal<paddr_t>      r_icache_paddr_save;        // physical address
+    sc_signal<vaddr_t>      r_icache_id1_save;          // used by the PT1 bypass
+    sc_signal<paddr_t>      r_icache_ptba_save;         // used by the PT1 bypass
+    sc_signal<bool>         r_icache_ptba_ok;           // used by the PT1 bypass
+    sc_signal<data_t>       r_icache_pte_update;        // used for page table update
+    sc_signal<tag_t>        r_icache_ppn_save;          // used for speculative cache access
+    sc_signal<tag_t>        r_icache_vpn_save;          // used for speculative cache access
+    sc_signal<bool>         r_itlb_translation_valid;   // used for speculative physical address
+    sc_signal<bool>         r_icache_buf_unc_valid;     // used for uncached read
+
+    sc_signal<data_t>       r_icache_error_type;        // software visible registers
+    sc_signal<vaddr_t>      r_icache_bad_vaddr;         // software visible registers
+
+    sc_signal<bool>         r_icache_miss_req;          // used for cached read miss
+    sc_signal<bool>         r_icache_unc_req;           // used for uncached read miss
+    sc_signal<bool>         r_dcache_itlb_read_req;     // used for tlb ptba or pte read 
+
+    sc_signal<bool>         r_dcache_itlb_ll_acc_req;   // used for tlb access bit update
+    sc_signal<bool>         r_dcache_itlb_sc_acc_req;   // used for tlb access bit update
+
+    sc_signal<bool>	        r_itlb_read_dcache_req;     // used for instruction tlb miss, request in data cache
+    sc_signal<bool>	        r_itlb_acc_dcache_req;          // used for itlb update access bit via dcache
+    sc_signal<bool>	        r_dcache_rsp_itlb_error;        // used for data cache rsp error when itlb miss
+    sc_signal<data_t>	    r_dcache_rsp_itlb_miss;	        // used for dcache rsp data when itlb miss
+    sc_signal<data_t>	    r_dcache_rsp_itlb_ppn;	        // used for dcache rsp ppn when itlb miss
+
+    // coherence registers
+    sc_signal<int>          r_icache_fsm_save;          // state save register
+    sc_signal<size_t>       r_icache_way;
+    sc_signal<size_t>       r_icache_set;
+    sc_signal<bool>         r_icache_cleanup_req;       // ins cleanup request
+    sc_signal<paddr_t>      r_icache_cleanup_line;      // ins cleanup NLINE
+    sc_signal<bool>         r_icache_inval_rsp;         // ins cache invalidate
+
+    // VCI_CMD FSM REGISTERS
+    sc_signal<int>          r_vci_cmd_fsm;
+    sc_signal<size_t>       r_vci_cmd_min;       
+    sc_signal<size_t>       r_vci_cmd_max;       
+    sc_signal<size_t>       r_vci_cmd_cpt;     
+
+    // VCI_RSP FSM REGISTERS
+    sc_signal<int>          r_vci_rsp_fsm;
+    sc_signal<size_t>       r_vci_rsp_cpt;
+    sc_signal<bool>         r_vci_rsp_ins_error;
+    sc_signal<bool>         r_vci_rsp_data_error;
+
+    data_t                  *r_icache_miss_buf;    
+    data_t                  *r_dcache_miss_buf;  
+
+    // VCI_TGT FSM REGISTERS
+    data_t                  *r_tgt_buf;
+    bool                    *r_tgt_val;
+
+    sc_signal<int>          r_vci_tgt_fsm;
+    sc_signal<paddr_t>      r_tgt_addr;
+    sc_signal<size_t>       r_tgt_word;
+    sc_signal<bool>         r_tgt_update;
+    sc_signal<vci_srcid_t>  r_tgt_srcid;
+    sc_signal<vci_pktid_t>  r_tgt_pktid;
+    sc_signal<vci_trdid_t>  r_tgt_trdid;
+    sc_signal<vci_plen_t>   r_tgt_plen;
+    sc_signal<bool>         r_tgt_req;
+    sc_signal<bool>         r_tgt_icache_req;
+    sc_signal<bool>         r_tgt_dcache_req;
+    sc_signal<bool>         r_tgt_icache_rsp;
+    sc_signal<bool>         r_tgt_dcache_rsp;
+
+    // INVAL CHECK FSM
+    sc_signal<int>          r_inval_itlb_fsm;          
+    sc_signal<bool>         r_dcache_itlb_inval_req;
+    sc_signal<paddr_t>      r_dcache_itlb_inval_line;
+    sc_signal<bool>         r_itlb_cc_check_end;
+    sc_signal<size_t>       r_ccinval_itlb_way; 
+    sc_signal<size_t>       r_ccinval_itlb_set; 
+    sc_signal<bool>         r_icache_inval_tlb_rsp;
+    sc_signal<paddr_t>      r_icache_tlb_nline;
+
+    sc_signal<int>          r_inval_dtlb_fsm;          
+    sc_signal<bool>         r_dcache_dtlb_inval_req;
+    sc_signal<paddr_t>      r_dcache_dtlb_inval_line;
+    sc_signal<bool>         r_dtlb_cc_check_end;
+    sc_signal<size_t>       r_ccinval_dtlb_way; 
+    sc_signal<size_t>       r_ccinval_dtlb_set; 
+    sc_signal<bool>         r_dcache_inval_tlb_rsp;
+    sc_signal<paddr_t>      r_dcache_tlb_nline;
+
+    sc_signal<bool>         r_dcache_itlb_cleanup_req;
+    sc_signal<paddr_t>      r_dcache_itlb_cleanup_line;
+
+    sc_signal<bool>         r_dcache_dtlb_cleanup_req;
+    sc_signal<paddr_t>      r_dcache_dtlb_cleanup_line;
+
+    sc_signal<bool>         r_itlb_inval_req;
+    sc_signal<bool>         r_dcache_cc_check;
+
+    WriteBuffer<paddr_t>     r_wbuf;
+    GenericCache<paddr_t>    r_icache;
+    GenericCache<paddr_t>    r_dcache;
+
+    // Activity counters
+    uint32_t m_cpt_dcache_data_read;        // DCACHE DATA READ
+    uint32_t m_cpt_dcache_data_write;       // DCACHE DATA WRITE
+    uint32_t m_cpt_dcache_dir_read;         // DCACHE DIR READ
+    uint32_t m_cpt_dcache_dir_write;        // DCACHE DIR WRITE
+
+    uint32_t m_cpt_icache_data_read;        // ICACHE DATA READ
+    uint32_t m_cpt_icache_data_write;       // ICACHE DATA WRITE
+    uint32_t m_cpt_icache_dir_read;         // ICACHE DIR READ
+    uint32_t m_cpt_icache_dir_write;        // ICACHE DIR WRITE
+
+    uint32_t m_cpt_frz_cycles;	            // number of cycles where the cpu is frozen
+    uint32_t m_cpt_total_cycles;	        // total number of cycles 
+
+    // Cache activity counters
+    uint32_t m_cpt_read;                    // total number of read data
+    uint32_t m_cpt_write;                   // total number of write data
+    uint32_t m_cpt_data_miss;               // number of read miss
+    uint32_t m_cpt_ins_miss;                // number of instruction miss
+    uint32_t m_cpt_unc_read;                // number of read uncached
+    uint32_t m_cpt_write_cached;            // number of cached write
+    uint32_t m_cpt_ins_read;                // number of instruction read
+
+    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
+    uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
+    uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
+    uint32_t m_cost_ins_miss_frz;           // number of frozen cycles related to ins miss
+
+    uint32_t m_cpt_imiss_transaction;       // number of VCI instruction miss transactions
+    uint32_t m_cpt_dmiss_transaction;       // number of VCI data miss transactions
+    uint32_t m_cpt_unc_transaction;         // number of VCI uncached read transactions
+    uint32_t m_cpt_write_transaction;       // number of VCI write transactions
+
+    uint32_t m_cost_imiss_transaction;      // cumulated duration for VCI IMISS transactions
+    uint32_t m_cost_dmiss_transaction;      // cumulated duration for VCI DMISS transactions
+    uint32_t m_cost_unc_transaction;        // cumulated duration for VCI UNC transactions
+    uint32_t m_cost_write_transaction;      // cumulated duration for VCI WRITE transactions
+    uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions
+
+    // TLB activity counters
+    uint32_t m_cpt_ins_tlb_read;            // number of instruction tlb read
+    uint32_t m_cpt_ins_tlb_miss;            // number of instruction tlb miss
+    uint32_t m_cpt_ins_tlb_write_et;        // number of instruction tlb write ET
+
+    uint32_t m_cpt_data_tlb_read;           // number of data tlb read
+    uint32_t m_cpt_data_tlb_miss;           // number of data tlb miss
+    uint32_t m_cpt_data_tlb_write_et;       // number of data tlb write ET
+    uint32_t m_cpt_data_tlb_write_dirty;    // number of data tlb write dirty
+    
+    uint32_t m_cost_ins_tlb_miss_frz;       // number of frozen cycles related to instruction tlb miss
+    uint32_t m_cost_data_tlb_miss_frz;      // number of frozen cycles related to data tlb miss
+
+    uint32_t m_cost_ins_waste_wait_frz;     // number of frozen cycles related to ins wait coherence operate 
+    uint32_t m_cost_ins_tlb_sw_frz;         // number of frozen cycles related to ins context switch
+    uint32_t m_cost_ins_cache_flush_frz;    // number of frozen cycles related to ins cache flush 
+
+    uint32_t m_cpt_ins_tlb_cleanup;         // number of ins tlb cleanup 
+    uint32_t m_cost_data_waste_wait_frz;    // number of frozen cycles related to data wait coherence operate
+    uint32_t m_cost_data_tlb_sw_frz;        // number of frozen cycles related to data context switch
+    uint32_t m_cost_data_cache_flush_frz;   // number of frozen cycles related to data cache flush
+
+    uint32_t m_cpt_itlbmiss_transaction;    // number of itlb miss transactions
+    uint32_t m_cpt_itlb_write_transaction;  // number of itlb write ET transactions
+    uint32_t m_cpt_dtlbmiss_transaction;    // number of dtlb miss transactions
+    uint32_t m_cpt_dtlb_write_transaction;  // number of dtlb write ET and dirty transactions
+
+    uint32_t m_cost_itlbmiss_transaction;   // cumulated duration for VCI instruction TLB miss transactions
+    uint32_t m_cost_itlb_write_transaction; // cumulated duration for VCI instruction TLB write ET transactions
+    uint32_t m_cost_dtlbmiss_transaction;   // cumulated duration for VCI data TLB miss transactions
+    uint32_t m_cost_dtlb_write_transaction; // cumulated duration for VCI data TLB write transactions
+
+    uint32_t m_cpt_cc_update;               // number of coherence update packets 
+    uint32_t m_cpt_cc_inval;                // number of coherence inval packets
+    uint32_t m_cpt_cc_broadcast;            // number of coherence broadcast packets
+
+    uint32_t m_cost_ins_tlb_inval_frz;      // number of frozen cycles related to checking ins tlb invalidate
+    uint32_t m_cpt_ins_tlb_inval;           // number of ins tlb invalidate
+
+    uint32_t m_cost_data_tlb_inval_frz;     // number of frozen cycles related to checking data tlb invalidate    
+    uint32_t m_cpt_data_tlb_inval;          // number of data tlb invalidate
+
+protected:
+    SC_HAS_PROCESS(VciCcVCacheWrapper2);
+
+public:
+    VciCcVCacheWrapper2(
+        sc_module_name insname,
+        int proc_id,
+        const soclib::common::MappingTable &mtp,
+        const soclib::common::MappingTable &mtc,
+        const soclib::common::IntTab &initiator_index,
+        const soclib::common::IntTab &target_index,
+        size_t itlb_ways,
+        size_t itlb_sets,
+        size_t dtlb_ways,
+        size_t dtlb_sets,
+        size_t icache_ways,
+        size_t icache_sets,
+        size_t icache_words,
+        size_t dcache_ways,
+        size_t dcache_sets,
+        size_t dcache_words,
+        size_t write_buf_size );
+
+    ~VciCcVCacheWrapper2();
+
+    void print_cpi();
+    void print_stats();
+
+private:
+    void transition();
+    void genMoore();
+
+    soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC);
+    soclib_static_assert((int)iss_t::SC_NOT_ATOMIC == (int)vci_param::STORE_COND_NOT_ATOMIC);
+};
+
+}}
+
+#endif /* SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER2_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
Index: trunk/modules/vci_cc_vcache_wrapper2/caba/source/src/vci_cc_vcache_wrapper2.cpp
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper2/caba/source/src/vci_cc_vcache_wrapper2.cpp	(revision 2)
+++ trunk/modules/vci_cc_vcache_wrapper2/caba/source/src/vci_cc_vcache_wrapper2.cpp	(revision 2)
@@ -0,0 +1,5426 @@
+/* -*- c++ -*-
+ * File : vci_cc_vcache_wrapper2.cpp
+ * Copyright (c) UPMC, Lip6, SoC
+ * Authors : Alain GREINER, Yang GAO
+ *
+ * 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
+ */
+
+#include <cassert>
+#include "arithmetics.h"
+#include "../include/vci_cc_vcache_wrapper2.h"
+
+namespace soclib { 
+namespace caba {
+
+#ifdef SOCLIB_MODULE_DEBUG
+namespace {
+const char *icache_fsm_state_str[] = {
+        "ICACHE_IDLE",
+        "ICACHE_BIS",       
+        "ICACHE_TLB1_READ",  
+        "ICACHE_TLB1_WRITE",  
+        "ICACHE_TLB1_UPDT",  
+        "ICACHE_TLB2_READ",  
+        "ICACHE_TLB2_WRITE",  
+        "ICACHE_TLB2_UPDT",  
+        "ICACHE_SW_FLUSH", 
+        "ICACHE_CACHE_FLUSH", 
+        "ICACHE_TLB_INVAL",  
+        "ICACHE_CACHE_INVAL",
+        "ICACHE_MISS_WAIT",
+        "ICACHE_UNC_WAIT",  
+        "ICACHE_MISS_UPDT",  
+        "ICACHE_ERROR", 	
+        "ICACHE_CC_INVAL", 
+        "ICACHE_TLB_CC_INVAL",        
+        "ICACHE_TLB_FLUSH", 
+    };
+const char *dcache_fsm_state_str[] = {
+        "DCACHE_IDLE",       
+        "DCACHE_BIS",   
+        "DCACHE_DTLB1_READ_CACHE",
+	"DCACHE_TLB1_LL_WAIT",
+	"DCACHE_TLB1_SC_WAIT",    
+        "DCACHE_TLB1_READ",
+        "DCACHE_TLB1_READ_UPDT",  
+        "DCACHE_TLB1_UPDT", 
+        "DCACHE_DTLB2_READ_CACHE", 
+	"DCACHE_TLB2_LL_WAIT",
+	"DCACHE_TLB2_SC_WAIT",   
+        "DCACHE_TLB2_READ",
+        "DCACHE_TLB2_READ_UPDT",  
+        "DCACHE_TLB2_UPDT",   
+        "DCACHE_CTXT_SWITCH",   
+        "DCACHE_ICACHE_FLUSH", 
+        "DCACHE_DCACHE_FLUSH", 
+        "DCACHE_ITLB_INVAL",
+        "DCACHE_DTLB_INVAL",
+        "DCACHE_ICACHE_INVAL",
+        "DCACHE_DCACHE_INVAL",
+	"DCACHE_DCACHE_SYNC",
+	"DCACHE_LL_DIRTY_WAIT",
+	"DCACHE_SC_DIRTY_WAIT",
+        "DCACHE_WRITE_UPDT", 
+        "DCACHE_WRITE_DIRTY",
+        "DCACHE_WRITE_REQ",  
+        "DCACHE_MISS_WAIT",  
+        "DCACHE_MISS_UPDT",  
+        "DCACHE_UNC_WAIT",   
+        "DCACHE_ERROR", 
+        "DCACHE_ITLB_READ",
+        "DCACHE_ITLB_UPDT",
+        "DCACHE_ITLB_LL_WAIT",        
+        "DCACHE_ITLB_SC_WAIT",        
+        "DCACHE_CC_CHECK",
+        "DCACHE_CC_INVAL",
+        "DCACHE_CC_UPDT",
+        "DCACHE_CC_NOP",
+        "DCACHE_TLB_CC_INVAL",
+        "DCACHE_ITLB_CLEANUP",
+    };
+const char *cmd_fsm_state_str[] = {
+        "CMD_IDLE",           
+        "CMD_ITLB_READ", 
+        "CMD_ITLB_ACC_LL",                
+        "CMD_ITLB_ACC_SC",                
+        "CMD_INS_MISS",     
+        "CMD_INS_UNC",     
+        "CMD_DTLB_READ",   
+        "CMD_DTLB_ACC_LL",            
+        "CMD_DTLB_ACC_SC",            
+        "CMD_DTLB_DIRTY_LL",          
+        "CMD_DTLB_DIRTY_SC",          
+        "CMD_DATA_UNC",     
+        "CMD_DATA_MISS",    
+        "CMD_DATA_WRITE", 
+        "CMD_INS_CLEANUP",    
+        "CMD_DATA_CLEANUP",      
+    };
+const char *rsp_fsm_state_str[] = {
+        "RSP_IDLE",                  
+        "RSP_ITLB_READ",             
+        "RSP_ITLB_ACC_LL",                
+        "RSP_ITLB_ACC_SC",                
+        "RSP_INS_MISS",   
+        "RSP_INS_UNC",           
+        "RSP_DTLB_READ",            
+        "RSP_DTLB_ACC_LL",            
+        "RSP_DTLB_ACC_SC",            
+        "RSP_DTLB_DIRTY_LL",          
+        "RSP_DTLB_DIRTY_SC",          
+        "RSP_DATA_MISS",             
+        "RSP_DATA_UNC",              
+        "RSP_DATA_WRITE",     
+        "RSP_INS_CLEANUP",    
+        "RSP_DATA_CLEANUP",        
+    };
+const char *tgt_fsm_state_str[] = {
+        "TGT_IDLE",
+        "TGT_UPDT_WORD",
+        "TGT_UPDT_DATA",
+        "TGT_REQ_BROADCAST",
+        "TGT_REQ_DCACHE",
+        "TGT_RSP_BROADCAST",
+        "TGT_RSP_DCACHE",
+    };	
+const char *inval_itlb_fsm_state_str[] = {
+        "INVAL_ITLB_IDLE",        
+        "INVAL_ITLB_CHECK"  , 
+        "INVAL_ITLB_INVAL",      
+        "INVAL_ITLB_CLEAR",           
+    };
+const char *inval_dtlb_fsm_state_str[] = {
+        "INVAL_DTLB_IDLE",        
+        "INVAL_DTLB_CHECK", 
+        "INVAL_DTLB_INVAL",    
+        "INVAL_DTLB_CLEAR",         
+    };
+}
+#endif
+
+#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcVCacheWrapper2<vci_param, iss_t>
+
+using soclib::common::uint32_log2;
+
+/***********************************************/
+tmpl(/**/)::VciCcVCacheWrapper2(
+    sc_module_name name,
+    int proc_id,
+    const soclib::common::MappingTable &mtp,
+    const soclib::common::MappingTable &mtc,
+    const soclib::common::IntTab &initiator_index,
+    const soclib::common::IntTab &target_index,
+    size_t itlb_ways,
+    size_t itlb_sets,
+    size_t dtlb_ways,
+    size_t dtlb_sets,
+    size_t icache_ways,
+    size_t icache_sets,
+    size_t icache_words,
+    size_t dcache_ways,
+    size_t dcache_sets,
+    size_t dcache_words,
+    size_t write_buf_size )
+/***********************************************/
+    : soclib::caba::BaseModule(name),
+
+      p_clk("clk"),
+      p_resetn("resetn"),
+      p_vci_ini("vci_ini"),
+      p_vci_tgt("vci_tgt"),
+
+      m_cacheability_table(mtp.getCacheabilityTable()),
+      m_segment(mtc.getSegment(target_index)),
+      m_iss(this->name(), proc_id),
+      m_srcid(mtp.indexForId(initiator_index)),
+
+      m_itlb_ways(itlb_ways),
+      m_itlb_sets(itlb_sets),
+
+      m_dtlb_ways(dtlb_ways),
+      m_dtlb_sets(dtlb_sets),
+
+      m_icache_ways(icache_ways),
+      m_icache_sets(icache_sets),
+      m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
+      m_icache_words(icache_words),
+
+      m_dcache_ways(dcache_ways),
+      m_dcache_sets(dcache_sets),
+      m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
+      m_dcache_words(dcache_words),
+
+      m_write_buf_size(write_buf_size),	
+      m_paddr_nbits(vci_param::N),
+
+      icache_tlb(itlb_ways,itlb_sets,vci_param::N),
+      dcache_tlb(dtlb_ways,dtlb_sets,vci_param::N),
+
+      r_dcache_fsm("r_dcache_fsm"),
+      r_dcache_paddr_save("r_dcache_paddr_save"),
+      r_dcache_wdata_save("r_dcache_wdata_save"),
+      r_dcache_rdata_save("r_dcache_rdata_save"),
+      r_dcache_type_save("r_dcache_type_save"),
+      r_dcache_be_save("r_dcache_be_save"),
+      r_dcache_cached_save("r_dcache_cached_save"),
+      r_dcache_tlb_paddr("r_dcache_tlb_paddr"),
+      r_dcache_miss_req("r_dcache_miss_req"),
+      r_dcache_unc_req("r_dcache_unc_req"),
+      r_dcache_write_req("r_dcache_write_req"),
+      r_dcache_tlb_read_req("r_dcache_tlb_read_req"),
+
+      r_dcache_tlb_ll_acc_req("r_dcache_tlb_ll_acc_req"),       
+      r_dcache_tlb_sc_acc_req("r_dcache_tlb_sc_acc_req"),       
+      r_dcache_tlb_ll_dirty_req("r_dcache_tlb_ll_dirty_req"),    
+      r_dcache_tlb_sc_dirty_req("r_dcache_tlb_sc_dirty_req"), 
+      r_dcache_tlb_ptba_read("r_dcache_tlb_ptba_read"),
+      r_dcache_xtn_req("r_dcache_xtn_req"),
+
+      r_dcache_fsm_save("r_dcache_fsm_save"),
+      r_dcache_cleanup_req("r_dcache_cleanup_req"),
+      r_dcache_inval_rsp("r_dcache_inval_rsp"),
+
+      r_icache_fsm("r_icache_fsm"),
+      r_icache_paddr_save("r_icache_paddr_save"),
+      r_icache_miss_req("r_icache_miss_req"),
+      r_icache_unc_req("r_icache_unc_req"),
+      r_dcache_itlb_read_req("r_dcache_itlb_read_req"),
+      r_dcache_itlb_ll_acc_req("r_dcache_itlb_ll_acc_req"),     
+      r_dcache_itlb_sc_acc_req("r_dcache_itlb_sc_acc_req"),
+
+      r_itlb_read_dcache_req("r_itlb_read_dcache_req"),
+      r_itlb_acc_dcache_req("r_itlb_acc_dcache_req"),
+      r_dcache_rsp_itlb_error("r_dcache_rsp_itlb_error"),
+
+      r_icache_fsm_save("r_icache_fsm_save"),
+      r_icache_cleanup_req("r_icache_cleanup_req"),
+      r_icache_inval_rsp("r_icache_inval_rsp"),
+
+      r_vci_cmd_fsm("r_vci_cmd_fsm"),
+      r_vci_cmd_min("r_vci_cmd_min"),
+      r_vci_cmd_max("r_vci_cmd_max"),
+      r_vci_cmd_cpt("r_vci_cmd_cpt"),
+
+      r_vci_rsp_fsm("r_vci_rsp_fsm"),
+      r_vci_rsp_cpt("r_vci_rsp_cpt"),
+      r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
+      r_vci_rsp_data_error("r_vci_rsp_data_error"),
+
+      r_vci_tgt_fsm("r_vci_tgt_fsm"),
+      r_tgt_addr("r_tgt_addr"),
+      r_tgt_word("r_tgt_word"),
+      r_tgt_update("r_tgt_update"),
+      r_tgt_srcid("r_tgt_srcid"),
+      r_tgt_pktid("r_tgt_pktid"),
+      r_tgt_trdid("r_tgt_trdid"),
+      r_tgt_icache_req("r_tgt_icache_req"),
+      r_tgt_dcache_req("r_tgt_dcache_req"),
+
+      r_inval_itlb_fsm("r_inval_itlb_fsm"),          
+      r_dcache_itlb_inval_req("r_dcache_itlb_inval_req"),
+      r_dcache_itlb_inval_line("r_dcache_itlb_inval_line"),
+      r_itlb_cc_check_end("r_itlb_cc_check_end"),
+      r_ccinval_itlb_way("r_ccinval_itlb_way"), 
+      r_ccinval_itlb_set("r_ccinval_itlb_set"), 
+      r_icache_inval_tlb_rsp("r_icache_inval_tlb_rsp"),
+      r_icache_tlb_nline("r_icache_tlb_nline"),
+
+      r_inval_dtlb_fsm("r_inval_dtlb_fsm"),          
+      r_dcache_dtlb_inval_req("r_dcache_dtlb_inval_req"),
+      r_dcache_dtlb_inval_line("r_dcache_dtlb_inval_line"),
+      r_dtlb_cc_check_end("r_dtlb_cc_check_end"),
+      r_ccinval_dtlb_way("r_ccinval_dtlb_way"), 
+      r_ccinval_dtlb_set("r_ccinval_dtlb_set"), 
+      r_dcache_inval_tlb_rsp("r_dcache_inval_tlb_rsp"),
+      r_dcache_tlb_nline("r_dcache_tlb_nline"),
+
+      r_dcache_itlb_cleanup_req("r_dcache_itlb_cleanup_req"),
+      r_dcache_itlb_cleanup_line("r_dcache_itlb_cleanup_line"),
+
+      r_dcache_dtlb_cleanup_req("r_dcache_dtlb_cleanup_req"),
+      r_dcache_dtlb_cleanup_line("r_dcache_dtlb_cleanup_line"),
+
+      r_wbuf("wbuf", write_buf_size ),
+      r_icache("icache", icache_ways, icache_sets, icache_words),
+      r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
+{
+    r_icache_miss_buf = new data_t[icache_words];
+    r_dcache_miss_buf = new data_t[dcache_words];
+    r_tgt_buf         = new data_t[dcache_words];
+    r_tgt_val         = new bool[dcache_words];
+    r_dcache_in_itlb  = new bool[dcache_ways*dcache_sets];           
+    r_dcache_in_dtlb  = new bool[dcache_ways*dcache_sets];          
+
+    SC_METHOD(transition);
+    dont_initialize();
+    sensitive << p_clk.pos();
+  
+    SC_METHOD(genMoore);
+    dont_initialize();
+    sensitive << p_clk.neg();
+
+    typename iss_t::CacheInfo cache_info;
+    cache_info.has_mmu = true;
+    cache_info.icache_line_size = icache_words*sizeof(data_t);
+    cache_info.icache_assoc = icache_ways;
+    cache_info.icache_n_lines = icache_sets;
+    cache_info.dcache_line_size = dcache_words*sizeof(data_t);
+    cache_info.dcache_assoc = dcache_ways;
+    cache_info.dcache_n_lines = dcache_sets;
+    m_iss.setCacheInfo(cache_info);
+}
+
+/////////////////////////////////////
+tmpl(/**/)::~VciCcVCacheWrapper2()
+/////////////////////////////////////
+{
+    delete [] r_icache_miss_buf;
+    delete [] r_dcache_miss_buf;
+    delete [] r_tgt_val;
+    delete [] r_tgt_buf;
+    delete [] r_dcache_in_itlb;           
+    delete [] r_dcache_in_dtlb;          
+}
+
+////////////////////////
+tmpl(void)::print_cpi()
+////////////////////////
+{
+    std::cout << name() << " CPI = " 
+        << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
+}
+
+////////////////////////
+tmpl(void)::print_stats()
+////////////////////////
+{
+    float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
+    std::cout << name() << std::endl
+    	      << "- CPI                    = " << (float)m_cpt_total_cycles/run_cycles << std::endl 
+    	      << "- READ RATE              = " << (float)m_cpt_read/run_cycles << std::endl 
+    	      << "- WRITE RATE             = " << (float)m_cpt_write/run_cycles << std::endl
+    	      << "- UNCACHED READ RATE     = " << (float)m_cpt_unc_read/m_cpt_read << std::endl 
+    	      << "- CACHED WRITE RATE      = " << (float)m_cpt_write_cached/m_cpt_write << std::endl 
+    	      << "- IMISS_RATE             = " << (float)m_cpt_ins_miss/m_cpt_ins_read << std::endl    
+    	      << "- DMISS RATE             = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl 
+    	      << "- INS MISS COST          = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl
+    	      << "- IMISS TRANSACTION      = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl
+    	      << "- DMISS COST             = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl
+    	      << "- DMISS TRANSACTION      = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl
+    	      << "- UNC COST               = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl
+    	      << "- UNC TRANSACTION        = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl
+    	      << "- WRITE COST             = " << (float)m_cost_write_frz/m_cpt_write << std::endl
+    	      << "- WRITE TRANSACTION      = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl
+    	      << "- WRITE LENGTH           = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl
+    	      << "- INS TLB MISS RATE      = " << (float)m_cpt_ins_tlb_miss/m_cpt_ins_tlb_read << std::endl
+    	      << "- DATA TLB MISS RATE     = " << (float)m_cpt_data_tlb_miss/m_cpt_data_tlb_read << std::endl
+    	      << "- ITLB MISS TRANSACTION  = " << (float)m_cost_itlbmiss_transaction/m_cpt_itlbmiss_transaction << std::endl
+    	      << "- ITLB WRITE TRANSACTION = " << (float)m_cost_itlb_write_transaction/m_cpt_itlb_write_transaction << std::endl
+    	      << "- ITLB MISS COST         = " << (float)m_cost_ins_tlb_miss_frz/(m_cpt_ins_tlb_miss+m_cpt_ins_tlb_write_et) << std::endl
+    	      << "- DTLB MISS TRANSACTION  = " << (float)m_cost_dtlbmiss_transaction/m_cpt_dtlbmiss_transaction << std::endl
+    	      << "- DTLB WRITE TRANSACTION = " << (float)m_cost_dtlb_write_transaction/m_cpt_dtlb_write_transaction << std::endl
+    	      << "- DTLB MISS COST         = " << (float)m_cost_data_tlb_miss_frz/(m_cpt_data_tlb_miss+m_cpt_data_tlb_write_et+m_cpt_data_tlb_write_dirty) << std::endl;
+}
+
+/*************************************************/
+tmpl(void)::transition()
+/*************************************************/
+{
+    if ( ! p_resetn.read() ) 
+    {
+        m_iss.reset();
+
+        r_dcache_fsm = DCACHE_IDLE;
+        r_icache_fsm = ICACHE_IDLE;
+        r_vci_cmd_fsm = CMD_IDLE;
+        r_vci_rsp_fsm = RSP_IDLE;
+        r_vci_tgt_fsm = TGT_IDLE;
+        r_inval_itlb_fsm = INVAL_ITLB_IDLE;          
+        r_inval_dtlb_fsm = INVAL_DTLB_IDLE;          
+
+        // write buffer & caches
+        r_wbuf.reset();
+        r_icache.reset();
+        r_dcache.reset();
+
+        icache_tlb.reset();    
+        dcache_tlb.reset();    
+
+        std::memset(r_dcache_in_itlb, 0, sizeof(*r_dcache_in_itlb)*m_icache_ways*m_icache_sets);
+        std::memset(r_dcache_in_dtlb, 0, sizeof(*r_dcache_in_dtlb)*m_dcache_ways*m_dcache_sets);
+
+        r_mmu_mode = ALL_DEACTIVE;
+        r_mmu_params = (uint32_log2(m_dtlb_ways) << 29)   | (uint32_log2(m_dtlb_sets) << 25)   |
+                       (uint32_log2(m_dcache_ways) << 22) | (uint32_log2(m_dcache_sets) << 18) |
+                       (uint32_log2(m_itlb_ways) << 15)   | (uint32_log2(m_itlb_sets) << 11)   |
+                       (uint32_log2(m_icache_ways) << 8)  | (uint32_log2(m_icache_sets) << 4)  |
+                       (uint32_log2(m_icache_words * 4));
+        r_mmu_release = (uint32_t)(1 << 16) | 0x1;
+
+        r_icache_miss_req         = false;
+        r_icache_unc_req          = false;
+        r_dcache_itlb_read_req    = false;
+
+        r_itlb_read_dcache_req    = false;      
+        r_itlb_acc_dcache_req     = false;   
+        r_dcache_rsp_itlb_error   = false;
+ 
+        r_dcache_miss_req         = false;
+        r_dcache_unc_req          = false;
+        r_dcache_write_req        = false;
+        r_dcache_tlb_read_req     = false;
+        r_dcache_tlb_ptba_read    = false;
+        r_dcache_xtn_req          = false;
+	r_dcache_llsc_reserved    = false;
+
+        r_dcache_tlb_ll_acc_req   = false;    
+        r_dcache_tlb_sc_acc_req   = false;    
+        r_dcache_tlb_ll_dirty_req = false;   
+        r_dcache_tlb_sc_dirty_req = false;   
+        r_dcache_itlb_ll_acc_req  = false;   
+        r_dcache_itlb_sc_acc_req  = false;   
+
+        r_icache_cleanup_req      = false;
+        r_dcache_cleanup_req      = false;
+
+        r_tgt_icache_req          = false;
+        r_tgt_dcache_req          = false;
+
+        r_icache_inval_rsp        = false;
+        r_dcache_inval_rsp        = false;
+
+        r_dcache_dirty_save       = false;
+        r_dcache_hit_p_save       = false;
+
+        r_icache_buf_unc_valid    = false;
+        r_dcache_buf_unc_valid    = false;
+
+        r_vci_rsp_ins_error       = false;
+        r_vci_rsp_data_error      = false;
+
+        r_icache_id1_save         = 0;
+        r_icache_ppn_save         = 0;
+        r_icache_vpn_save         = 0;
+        r_itlb_translation_valid  = false;
+
+        r_dcache_id1_save         = 0;
+        r_dcache_ppn_save         = 0;
+        r_dcache_vpn_save         = 0;
+        r_dtlb_translation_valid  = false;
+
+        r_icache_ptba_ok          = false;
+        r_dcache_ptba_ok          = false;
+
+        r_icache_error_type       = MMU_NONE;
+        r_dcache_error_type       = MMU_NONE;
+
+        // coherence registers
+        r_icache_way              = 0;
+        r_icache_set              = 0;
+        r_icache_cleanup_req      = false;
+        r_icache_inval_rsp        = false;
+
+        r_dcache_way              = 0;
+        r_dcache_set              = 0;
+        r_dcache_cleanup_req      = false;
+        r_dcache_inval_rsp        = false;
+
+	r_itlb_inval_req 	  = false;
+        r_dcache_itlb_inval_req   = false;
+        r_itlb_cc_check_end       = false;
+        r_ccinval_itlb_way        = 0; 
+        r_ccinval_itlb_set        = 0; 
+        r_icache_inval_tlb_rsp    = false;
+
+        r_dcache_dtlb_inval_req   = false;
+        r_dtlb_cc_check_end       = false;
+        r_ccinval_dtlb_way        = 0; 
+        r_ccinval_dtlb_set        = 0; 
+        r_dcache_inval_tlb_rsp    = false;
+
+        r_dcache_itlb_cleanup_req = false;
+        r_dcache_dtlb_cleanup_req = false;
+
+	r_dcache_cc_check         = false;
+
+        // activity counters
+        m_cpt_dcache_data_read  = 0;
+        m_cpt_dcache_data_write = 0;
+        m_cpt_dcache_dir_read   = 0;
+        m_cpt_dcache_dir_write  = 0;
+        m_cpt_icache_data_read  = 0;
+        m_cpt_icache_data_write = 0;
+        m_cpt_icache_dir_read   = 0;
+        m_cpt_icache_dir_write  = 0;
+
+	m_cpt_frz_cycles   = 0;
+        m_cpt_total_cycles = 0;
+
+        m_cpt_read         = 0;
+        m_cpt_write        = 0;
+        m_cpt_data_miss    = 0;
+        m_cpt_ins_miss     = 0;
+        m_cpt_unc_read     = 0;
+        m_cpt_write_cached = 0;
+        m_cpt_ins_read     = 0;
+
+        m_cost_write_frz     = 0;
+        m_cost_data_miss_frz = 0;
+        m_cost_unc_read_frz  = 0;
+        m_cost_ins_miss_frz  = 0;
+
+        m_cpt_imiss_transaction = 0;
+        m_cpt_dmiss_transaction = 0;
+        m_cpt_unc_transaction   = 0;
+        m_cpt_write_transaction = 0;
+
+        m_cost_imiss_transaction   = 0;
+        m_cost_dmiss_transaction   = 0;
+        m_cost_unc_transaction     = 0;
+        m_cost_write_transaction   = 0;
+        m_length_write_transaction = 0;
+
+        m_cpt_ins_tlb_read         = 0;             
+        m_cpt_ins_tlb_miss         = 0;             
+        m_cpt_ins_tlb_write_et     = 0;         
+
+        m_cpt_data_tlb_read        = 0;           
+        m_cpt_data_tlb_miss        = 0;           
+        m_cpt_data_tlb_write_et    = 0;       
+        m_cpt_data_tlb_write_dirty = 0;    
+
+        m_cost_ins_tlb_miss_frz    = 0;      
+        m_cost_data_tlb_miss_frz   = 0;      
+
+        m_cpt_itlbmiss_transaction   = 0;    
+        m_cpt_itlb_write_transaction = 0;  
+        m_cpt_dtlbmiss_transaction   = 0;  
+        m_cpt_dtlb_write_transaction = 0;  
+ 
+        m_cost_itlbmiss_transaction   = 0;   
+        m_cost_itlb_write_transaction = 0;  
+        m_cost_dtlbmiss_transaction   = 0;   
+        m_cost_dtlb_write_transaction = 0;   
+        return;
+    }
+
+#ifdef SOCLIB_MODULE_DEBUG
+std::cout << name() << "cycle = " << m_cpt_total_cycles  
+       	  << " tgt fsm: " << tgt_fsm_state_str[r_vci_tgt_fsm]
+       	  << " dcache fsm: " << dcache_fsm_state_str[r_dcache_fsm]
+       	  << " icache fsm: " << icache_fsm_state_str[r_icache_fsm]
+       	  << " cmd fsm: " << cmd_fsm_state_str[r_vci_cmd_fsm]
+       	  << " rsp fsm: " << rsp_fsm_state_str[r_vci_rsp_fsm] 
+       	  << " inval itlb fsm: " << inval_itlb_fsm_state_str[r_inval_itlb_fsm] 
+          << " inval dtlb fsm: " << inval_dtlb_fsm_state_str[r_inval_dtlb_fsm] << std::endl;
+#endif
+
+    m_cpt_total_cycles++;
+
+    typename iss_t::InstructionRequest ireq = ISS_IREQ_INITIALIZER;
+    typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
+
+    typename iss_t::DataRequest dreq = ISS_DREQ_INITIALIZER;
+    typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
+
+    m_iss.getRequests( ireq, dreq );
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout << name() << " Instruction Request: " << ireq << std::endl;
+    std::cout << name() << " Data Request: " << dreq << std::endl;
+#endif
+
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_FSM controls the following ressources:
+    // - r_vci_tgt_fsm
+    // - r_tgt_buf[nwords]
+    // - r_tgt_val[nwords]
+    // - r_tgt_update
+    // - r_tgt_word
+    // - r_tgt_addr
+    // - r_tgt_srcid
+    // - r_tgt_trdid
+    // - r_tgt_pktid
+    // All VCI commands must be CMD_WRITE.
+    // If the VCI address offset is null, the command is an invalidate 
+    // request. It is an update request otherwise.
+    // The VCI_TGT FSM stores the external request arguments in the
+    // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 
+    // & r_tgt_dcache_req flip-flops to signal the external request to 
+    // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
+    // of the update or invalidate request in the RSP state.
+    // -  for an invalidate request the VCI packet length is 1 word.
+    // The WDATA field contains the line index (i.e. the Z & Y fields).
+    // -  for an update request the VCI packet length is (n+2) words.
+    // The WDATA field of the first VCI word contains the line number.
+    // The WDATA field of the second VCI word contains the word index.
+    // The WDATA field of the n following words contains the values.
+    // -  for both invalidate & update requests, the VCI response
+    // is one single word.
+    // In case of errors in the VCI command packet, the simulation
+    // is stopped with an error message.
+    /////////////////////////////////////////////////////////////////////
+    
+    switch(r_vci_tgt_fsm) {
+    //////////////
+    case TGT_IDLE:
+    {
+        if ( p_vci_tgt.cmdval.read() ) 
+        {
+            paddr_t address = p_vci_tgt.address.read();
+
+            if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the received VCI command is not a write" << std::endl;
+                exit(0);
+            }
+
+            // multi-update or multi-invalidate for data type
+            if ( ( address != 0x3 ) && ( ! m_segment.contains(address)) ) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "out of segment VCI command received for a multi-updt or multi-inval request" << std::endl;
+                exit(0);
+            }
+
+            r_tgt_srcid = p_vci_tgt.srcid.read();
+            r_tgt_trdid = p_vci_tgt.trdid.read();
+            r_tgt_pktid = p_vci_tgt.pktid.read();
+            r_tgt_plen  = p_vci_tgt.plen.read(); // todo: wait L2 modification
+            r_tgt_addr = (paddr_t)p_vci_tgt.wdata.read() * m_dcache_words * 4; 
+
+            if ( address == 0x3 ) // broadcast invalidate for data or instruction type
+            {
+                if ( ! p_vci_tgt.eop.read() ) 
+                {
+                    std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                    std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
+                    exit(0);
+                }
+                r_tgt_update = false; 
+                r_vci_tgt_fsm = TGT_REQ_BROADCAST;
+                m_cpt_cc_broadcast++;
+            }
+            else                // multi-update or multi-invalidate for data type
+            {
+                paddr_t cell = address - m_segment.baseAddress();   
+
+                if (cell == 0)                      // invalidate   
+                {                         
+                    if ( ! p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_update = false; 
+                    r_vci_tgt_fsm = TGT_REQ_DCACHE;
+                    m_cpt_cc_inval++ ;
+                } 
+                else                                // update
+                {                                
+                    if ( p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_update = true; 
+                    r_vci_tgt_fsm = TGT_UPDT_WORD;
+                    m_cpt_cc_update++ ;
+                }     
+            } // end if address    
+        } // end if cmdval
+        break;
+    }
+    ///////////////////
+    case TGT_UPDT_WORD:
+    {
+        if (p_vci_tgt.cmdval.read()) 
+        {
+            if ( p_vci_tgt.eop.read() ) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                exit(0);
+            }
+            for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_val[i] = false;
+            r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
+            r_vci_tgt_fsm = TGT_UPDT_DATA;
+        }
+        break;
+    }
+    ///////////////////
+    case TGT_UPDT_DATA:
+    {
+        if (p_vci_tgt.cmdval.read()) 
+        {
+            size_t word = r_tgt_word.read();
+            if (word >= m_dcache_words) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
+                exit(0);
+            }
+            r_tgt_buf[word] = p_vci_tgt.wdata.read();
+            if(p_vci_tgt.be.read())    r_tgt_val[word] = true;
+            r_tgt_word = word + 1;
+            if (p_vci_tgt.eop.read())  r_vci_tgt_fsm = TGT_REQ_DCACHE;
+        }
+        break;
+    }
+    ////////////////////////
+    case TGT_REQ_BROADCAST:
+    {
+        if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_RSP_BROADCAST; 
+            r_tgt_icache_req = true;
+            r_tgt_dcache_req = true;
+        }
+        break;
+    }
+    /////////////////////
+    case TGT_REQ_DCACHE:
+    {
+        if ( !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_RSP_DCACHE; 
+            r_tgt_dcache_req = true;
+        }
+        break;
+    }
+    ///////////////////////
+    case TGT_RSP_BROADCAST:
+    {
+        // no response
+        if ( !r_tgt_icache_rsp.read() && !r_tgt_dcache_rsp.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
+        {
+            r_vci_tgt_fsm = TGT_IDLE;
+            break;
+        }
+
+        if ( p_vci_tgt.rspack.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+        {
+            // one response
+            if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
+            {
+                r_vci_tgt_fsm = TGT_IDLE; 
+                r_tgt_icache_rsp = false;
+                r_tgt_dcache_rsp = false;
+            }
+
+            // if data and instruction have the inval line, need two responses  
+            if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
+            {
+                r_tgt_icache_rsp = false; // only reset one for respond the second time 
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case TGT_RSP_DCACHE:
+    {
+        if ( p_vci_tgt.rspack.read() && !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_IDLE;
+            r_tgt_dcache_rsp = false; 
+        }
+        break;
+    }
+    } // end switch TGT_FSM
+
+    ////////////////////////////////////////////////////////////////////////////////////////
+    //      ICACHE_FSM
+    //
+    // There is 9 mutually exclusive conditions to exit the IDLE state.
+    // Four configurations corresponding to an XTN request from processor,
+    // - Flush TLB (in case of Context switch) => TLB_FLUSH state 
+    // - Flush cache => CACHE_FLUSH state 
+    // - Invalidate a TLB entry => TLB_INVAL state
+    // - Invalidate a cache line => CACHE_INVAL state
+    // Five configurations corresponding to various TLB or cache MISS :
+    // - TLB miss(in case hit_p miss) => TLB1_READ state
+    // - TLB miss(in case hit_p hit) => TLB2_READ state
+    // - Hit in TLB but VPN changed => BIS state
+    // - Cached read miss => MISS_REQ state
+    // - Uncache read miss => UNC_REQ state
+    // 
+    // In case of MISS, the controller writes a request in the r_icache_paddr_save register 
+    // and sets the corresponding request flip-flop : r_dcache_itlb_read_req, r_icache_miss_req 
+    // or r_icache_unc_req. These request flip-flops are reset by the VCI_RSP controller 
+    // when the response is ready in the ICACHE buffer.
+    //
+    // The DCACHE FSM signals XTN processor requests using the r_dcache_xtn_req flip-flop. 
+    // The request opcod and the address to be invalidated are transmitted
+    // in the r_dcache_paddr_save & r_dcache_wdata_save registers respectively.
+    // The request flip-flop is reset by the ICACHE_FSM when the operation is completed.
+    //
+    // The r_vci_rsp_ins_error flip-flop is set by the VCI_RSP FSM and reset
+    // by the ICACHE-FSM in the ICACHE_ERROR state.
+    //
+    //----------------------------------------------------------------------------------- 
+    // Instruction TLB: 
+    //  
+    // - int        ET          (00: unmapped; 01: unused or PTD)
+    //                          (10: PTE new;  11: PTE old      )
+    // - bool       cachable    (cached bit)
+    // - bool       writable    (** not used alwayse false) 
+    // - bool       executable  (executable bit)
+    // - bool       user        (access in user mode allowed)
+    // - bool       global      (PTE not invalidated by a TLB flush)
+    // - bool       dirty       (** not used alwayse false) 
+    // - uint32_t   vpn         (virtual page number)
+    // - uint32_t   ppn         (physical page number)
+    ////////////////////////////////////////////////////////////////////////////////////////
+
+    switch(r_icache_fsm) {
+
+    ////////////////
+    case ICACHE_IDLE:
+    {
+        pte_info_t  icache_pte_info;
+        paddr_t     tlb_ipaddr       = 0;    	// physical address obtained from TLB                         
+        paddr_t     spc_ipaddr       = 0;    	// physical adress obtained from PPN_save (speculative)       
+        data_t      icache_ins       = 0;    	// read instruction
+        bool        icache_hit_c     = false;	// Cache hit
+        bool        icache_cached    = false;	// cacheable access (read)
+        bool        icache_hit_t     = false;	// hit on TLB
+        bool        icache_hit_x     = false;	// VPN unmodified (can use spc_dpaddr)
+        bool        icache_hit_p     = false;	// PTP unmodified (can skip first level page table walk)
+        size_t      icache_tlb_way   = 0;    	// selected way (in case of cache hit)
+        size_t      icache_tlb_set   = 0;    	// selected set (Y field in address)
+        paddr_t     icache_tlb_nline = 0;  	// TLB NLINE 
+
+        // Decoding processor XTN requests
+        // They are sent by DCACHE FSM  
+
+        if (r_dcache_xtn_req)
+        {
+            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+            
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_PTPR )  
+            {
+                r_icache_way = 0;
+                r_icache_set = 0;
+                r_icache_fsm = ICACHE_SW_FLUSH;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_ICACHE_FLUSH)
+            {
+                r_icache_way = 0;
+                r_icache_set = 0;
+                r_icache_fsm = ICACHE_CACHE_FLUSH;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_ITLB_INVAL) 
+            {
+                r_icache_fsm = ICACHE_TLB_INVAL;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_ICACHE_INVAL) 
+            {
+                r_icache_fsm = ICACHE_CACHE_INVAL;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_DCACHE_FLUSH )  
+            {
+                // special for ins tlb miss via data cache
+                r_icache_fsm = ICACHE_TLB_FLUSH;   
+                break;
+            }
+        } // end if xtn_req
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            break;
+        }
+
+        // icache_hit_t_m, icache_hit_t_k, icache_hit_x, icache_hit_p 
+        // icache_pte_info, icache_tlb_way, icache_tlb_set & ipaddr & cacheability 
+        // - If MMU activated : cacheability is defined by the cachable bit in the TLB
+        // - If MMU not activated : cacheability is defined by the segment table.
+
+        if ( !(r_mmu_mode.read() & INS_TLB_MASK) )   // MMU not activated 
+        {
+            icache_hit_t  = true;         
+            icache_hit_x  = true;         
+            icache_hit_p  = true;         
+            tlb_ipaddr    = ireq.addr;
+            spc_ipaddr    = ireq.addr;
+            icache_cached = m_cacheability_table[ireq.addr];
+        } 
+        else                                                                // MMU activated
+        { 
+            m_cpt_ins_tlb_read++;
+            icache_hit_t  = icache_tlb.cctranslate(ireq.addr, &tlb_ipaddr, &icache_pte_info, 
+                                                   &icache_tlb_nline, &icache_tlb_way, &icache_tlb_set); 
+            icache_hit_x  = (((vaddr_t)r_icache_vpn_save << PAGE_K_NBITS) == (ireq.addr & ~PAGE_K_MASK)) && r_itlb_translation_valid;
+            icache_hit_p  = (((ireq.addr >> PAGE_M_NBITS) == r_icache_id1_save) && r_icache_ptba_ok); 
+            spc_ipaddr    = ((paddr_t)r_icache_ppn_save << PAGE_K_NBITS) | (paddr_t)(ireq.addr & PAGE_K_MASK);
+            icache_cached = icache_pte_info.c; 
+        }
+
+        if ( !(r_mmu_mode.read() & INS_CACHE_MASK) )   // cache not actived
+        {
+            icache_cached = false;
+        }
+
+        if ( ireq.valid ) 
+        {
+            m_cpt_icache_dir_read += m_icache_ways;
+            m_cpt_icache_data_read += m_icache_ways;
+
+            // icache_hit_c & icache_ins
+            if ( icache_cached )    // using speculative physical address for cached access
+            {
+                icache_hit_c = r_icache.read(spc_ipaddr, &icache_ins);
+            }
+            else                    // using actual physical address for uncached access
+            {
+                icache_hit_c = ( r_icache_buf_unc_valid && (tlb_ipaddr == (paddr_t)r_icache_paddr_save) );
+                icache_ins = r_icache_miss_buf[0];
+            }
+
+            if ( r_mmu_mode.read() & INS_TLB_MASK ) 
+            {
+                if ( icache_hit_t ) 
+                {
+                    // check access rights
+                    if ( !icache_pte_info.u && (ireq.mode == iss_t::MODE_USER)) 
+                    {
+                        r_icache_error_type = MMU_READ_PRIVILEGE_VIOLATION;  
+                        r_icache_bad_vaddr = ireq.addr;
+                        irsp.valid = true;
+                        irsp.error = true;
+                        irsp.instruction = 0;
+                        break;
+                    }
+                    if ( !icache_pte_info.x ) 
+                    {
+                        r_icache_error_type = MMU_READ_EXEC_VIOLATION;  
+                        r_icache_bad_vaddr = ireq.addr;
+                        irsp.valid = true;
+                        irsp.error = true;
+                        irsp.instruction = 0;
+                        break;
+                    }
+                }
+
+                // update LRU, save ppn, vpn and page type
+                if ( icache_hit_t )
+                {  
+                    icache_tlb.setlru(icache_tlb_way,icache_tlb_set);     
+                    r_icache_ppn_save = tlb_ipaddr >> PAGE_K_NBITS;
+                    r_icache_vpn_save = ireq.addr >> PAGE_K_NBITS;
+                    r_icache_tlb_nline = icache_tlb_nline;
+                    r_itlb_translation_valid = true;
+                }
+                else
+                {
+                    r_itlb_translation_valid = false;
+                }
+
+            } // end if MMU activated
+
+            // compute next state 
+            if ( !icache_hit_t && !icache_hit_p )      // TLB miss
+            {
+                // walk page table  level 1
+                r_icache_paddr_save = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((ireq.addr>>PAGE_M_NBITS)<<2);
+                r_itlb_read_dcache_req = true;
+                r_icache_fsm = ICACHE_TLB1_READ;
+                m_cpt_ins_tlb_miss++;
+                m_cost_ins_tlb_miss_frz++;
+            }
+            else if ( !icache_hit_t && icache_hit_p )  // TLB Miss with possibility of bypass first level page
+            {
+                // walk page table level 2
+                r_icache_paddr_save = (paddr_t)r_icache_ptba_save | 
+                                      (paddr_t)(((ireq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                r_itlb_read_dcache_req = true;
+                r_icache_fsm = ICACHE_TLB2_READ;
+                m_cpt_ins_tlb_miss++;
+                m_cost_ins_tlb_miss_frz++;
+            }
+            else if ( icache_hit_t && !icache_hit_x && icache_cached ) // cached access with an ucorrect speculative physical address
+            {
+                r_icache_paddr_save = tlb_ipaddr;   // save actual physical address for BIS
+                r_icache_fsm = ICACHE_BIS;
+                m_cost_ins_miss_frz++;
+            }
+            else    // cached or uncached access with a correct speculative physical address 
+            {        
+                m_cpt_ins_read++; 
+                if ( !icache_hit_c ) 
+                {
+                    m_cpt_ins_miss++;
+                    m_cost_ins_miss_frz++;
+                    if ( icache_cached ) 
+                    {
+                        r_icache_miss_req = true;
+                    	r_icache_paddr_save = spc_ipaddr; 
+                        r_icache_fsm = ICACHE_MISS_WAIT;
+                    } 
+                    else 
+                    {
+                        r_icache_unc_req = true;
+                        r_icache_buf_unc_valid = false;
+                    	r_icache_paddr_save = tlb_ipaddr; 
+                        r_icache_fsm = ICACHE_UNC_WAIT;
+                    } 
+                } 
+                else 
+                {
+                    r_icache_buf_unc_valid = false;
+                    r_icache_fsm = ICACHE_IDLE;
+                }
+                irsp.valid = icache_hit_c;
+                irsp.instruction = icache_ins;
+            } // end if next states
+            
+        } // end if ireq.valid
+        break;
+    }
+    ////////////////
+    case ICACHE_BIS: 
+    {
+        m_cost_ins_miss_frz++;
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+      
+        // using page is invalidated 
+        if ( r_icache_inval_tlb_rsp )
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+            m_cost_ins_tlb_miss_frz++;
+            break;
+        }
+ 
+        data_t	icache_ins = 0;
+        bool	icache_hit_c = false;
+        bool    icache_hit_t = false;
+        paddr_t	tlb_ipaddr = 0;
+
+	icache_hit_t = icache_tlb.translate(ireq.addr, &tlb_ipaddr);
+
+	if ( (tlb_ipaddr == r_icache_paddr_save.read()) && ireq.valid && icache_hit_t )		// unmodified & valid
+	{
+            m_cpt_ins_read++;
+
+            // acces is always cached in this state
+            icache_hit_c = r_icache.read(r_icache_paddr_save, &icache_ins);
+
+            if ( !icache_hit_c )
+            {
+                r_icache_miss_req = true;
+                r_icache_fsm = ICACHE_MISS_WAIT;
+                m_cpt_ins_miss++;
+            } 
+            else
+            {
+                r_icache_fsm = ICACHE_IDLE; 
+            }
+            irsp.valid = icache_hit_c;
+            irsp.error = false;
+            irsp.instruction = icache_ins;
+	}
+	else	// modified or invalid
+	{
+            irsp.valid = false;
+            irsp.error = false;
+            irsp.instruction = 0;
+            r_icache_fsm = ICACHE_IDLE;
+	}
+        break;
+    }
+    //////////////////////
+    case ICACHE_TLB1_READ:
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( !r_itlb_read_dcache_req && !r_icache_inval_tlb_rsp ) // TLB miss read response and no invalidation
+        {
+            if ( !r_dcache_rsp_itlb_error ) // vci response ok
+            {  
+		if ( !(r_dcache_rsp_itlb_miss >> PTE_V_SHIFT) ) // unmapped
+		{
+            	    r_icache_ptba_ok    = false;	
+                    r_icache_error_type = MMU_READ_PT1_UNMAPPED;  
+                    r_icache_bad_vaddr  = ireq.addr;
+                    r_icache_fsm        = ICACHE_ERROR;
+		}
+		else if ( (r_dcache_rsp_itlb_miss & PTE_T_MASK ) >> PTE_T_SHIFT ) // PTD
+		{
+            	    r_icache_ptba_ok       = true;	
+                    r_icache_ptba_save     = (paddr_t)(r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS; 
+                    r_icache_id1_save      = ireq.addr >> PAGE_M_NBITS;
+                    r_icache_paddr_save    = (paddr_t)(r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
+                                             (paddr_t)(((ireq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3); 
+                    r_itlb_read_dcache_req = true;
+                    r_icache_fsm           = ICACHE_TLB2_READ;
+		}	
+		else
+		{
+            	    r_icache_ptba_ok = false;
+	
+		    if ( (m_srcid >> 4) == ((r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		    {
+			if ( (r_dcache_rsp_itlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+			{
+                            r_icache_pte_update = r_dcache_rsp_itlb_miss;
+                            r_icache_fsm        = ICACHE_TLB1_UPDT;
+			}
+			else
+			{
+                            r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_L_MASK;
+                            r_itlb_acc_dcache_req = true;
+                            r_icache_fsm          = ICACHE_TLB1_WRITE;
+                            m_cpt_ins_tlb_write_et++;
+			}
+    	            }
+		    else // remotely
+		    {
+			if ( (r_dcache_rsp_itlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+			{
+                            r_icache_pte_update = r_dcache_rsp_itlb_miss;
+                            r_icache_fsm        = ICACHE_TLB1_UPDT;
+			}
+			else
+			{
+                            r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_R_MASK;
+                            r_itlb_acc_dcache_req = true;
+                            r_icache_fsm          = ICACHE_TLB1_WRITE;
+                            m_cpt_ins_tlb_write_et++;
+			}
+		    }
+		}
+            }
+            else                        // vci response error
+            {  
+                r_icache_fsm = ICACHE_ERROR;
+                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;    
+                r_icache_bad_vaddr = ireq.addr;
+            }
+        }
+
+        if ( !r_itlb_read_dcache_req && r_icache_inval_tlb_rsp ) // TLB miss read response and invalidation
+        {
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;    
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;  
+            } 
+        }
+        break;
+    }
+    ///////////////////////
+    case ICACHE_TLB1_WRITE:  
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if (!r_itlb_acc_dcache_req && !r_icache_inval_tlb_rsp ) // TLB access bits write response and no invalidation        
+        { 
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;  
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else  
+            {
+                r_icache_fsm = ICACHE_TLB1_UPDT;  
+            }
+        } 
+
+        if (!r_itlb_acc_dcache_req && r_icache_inval_tlb_rsp) // TLB ET write response and invalidation     
+        {   
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;  
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else  
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;    
+            }
+        }
+        break;
+    }
+    //////////////////////
+    case ICACHE_TLB1_UPDT:
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req ) 
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // TLB update and invalidate different PTE
+        if ( !r_dcache_itlb_cleanup_req && !r_icache_inval_tlb_rsp )  
+        {
+            paddr_t victim_index = 0;
+            r_dcache_itlb_cleanup_req = icache_tlb.update(r_icache_pte_update,ireq.addr,(r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index);
+            r_dcache_itlb_cleanup_line = victim_index;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+
+        // TLB update and invalidate same PTE
+        if ( r_icache_inval_tlb_rsp )                                 
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB2_READ:
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( !r_itlb_read_dcache_req && !r_icache_inval_tlb_rsp ) // TLB miss read response 
+        {
+            if ( !r_dcache_rsp_itlb_error ) // VCI response ok        
+            {
+		if ( !(r_dcache_rsp_itlb_miss >> PTE_V_SHIFT) ) // unmapped
+		{
+                    r_icache_error_type = MMU_READ_PT2_UNMAPPED;  
+                    r_icache_bad_vaddr  = ireq.addr;
+                    r_icache_fsm = ICACHE_ERROR;
+		}
+		else
+		{
+		    if ( (m_srcid >> 4) == ((r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		    {
+			if ( (r_dcache_rsp_itlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+			{
+                    	    r_icache_fsm        = ICACHE_TLB2_UPDT;
+                    	    r_icache_pte_update = r_dcache_rsp_itlb_miss;
+			}
+			else
+			{
+                    	    r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_L_MASK;
+                    	    r_itlb_acc_dcache_req = true;
+                    	    r_icache_fsm          = ICACHE_TLB2_WRITE;
+                     	    m_cpt_ins_tlb_write_et++;
+			}
+    	            }
+		    else // remotely
+		    {
+			if ( (r_dcache_rsp_itlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+			{
+                    	    r_icache_fsm        = ICACHE_TLB2_UPDT;
+                    	    r_icache_pte_update = r_dcache_rsp_itlb_miss;
+			}
+			else
+			{
+                    	    r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_R_MASK;
+                    	    r_itlb_acc_dcache_req = true;
+                    	    r_icache_fsm          = ICACHE_TLB2_WRITE;
+                    	    m_cpt_ins_tlb_write_et++;
+			}
+		    }
+		}
+            }
+            else                            // VCI response error        
+            {
+                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            }
+        }
+
+        if ( !r_itlb_read_dcache_req && r_icache_inval_tlb_rsp ) // TLB miss read response and invalidation
+        {
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;    
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;  
+            } 
+        }
+        break;
+    }
+    /////////////////////////
+    case ICACHE_TLB2_WRITE:
+    {  
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if (!r_itlb_acc_dcache_req && !r_icache_inval_tlb_rsp ) // TLB access bits write response          
+        {
+            if ( r_dcache_rsp_itlb_error )             
+            {
+                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;  
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else  
+            {
+                r_icache_fsm = ICACHE_TLB2_UPDT;  
+            }
+        } 
+        if (!r_itlb_acc_dcache_req && r_icache_inval_tlb_rsp) // TLB ET write response and invalidation     
+        {   
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;  
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else  
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;    
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB2_UPDT: 
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req ) 
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // TLB update and invalidate different PTE
+        if ( !r_dcache_itlb_cleanup_req && !r_icache_inval_tlb_rsp ) 
+        {
+            paddr_t victim_index = 0;
+            r_dcache_itlb_cleanup_req = icache_tlb.update(r_icache_pte_update,r_dcache_rsp_itlb_ppn,ireq.addr,(r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index);
+            r_dcache_itlb_cleanup_line = victim_index;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        // TLB update and invalidate same PTE
+        if ( r_icache_inval_tlb_rsp )                            
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    /////////////////////////////
+    case ICACHE_SW_FLUSH:
+    {
+        size_t way = r_icache_way;
+        size_t set = r_icache_set;
+        bool clean = false;
+
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+        m_cost_ins_tlb_sw_frz++;
+
+        // 4K page size TLB flush leads to cleanup req to data cache 
+        if ( !r_dcache_itlb_cleanup_req )    // last cleanup finish
+        {
+            paddr_t victim_index = 0;
+            for ( ; way < m_itlb_ways; way++)
+            {
+                for ( ; set < m_itlb_sets; set++)
+                {
+                    if(icache_tlb.checkcleanup(way, set, &victim_index))
+                    {
+                        clean = true;
+                        r_dcache_itlb_cleanup_req = true;
+                        r_dcache_itlb_cleanup_line = victim_index;
+                        r_icache_way = way + ((set+1)/m_itlb_sets);
+                        r_icache_set = (set+1) % m_itlb_sets;
+                        break;
+                    }
+                }
+                if (clean) break;
+            }
+
+            if ((way == m_itlb_ways) && (set == m_itlb_sets))
+            {
+                r_dcache_xtn_req = false;
+        	r_itlb_translation_valid = false;
+        	r_icache_ptba_ok = false;
+                r_icache_fsm = ICACHE_IDLE;
+                break;
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB_FLUSH:
+    {   
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+
+        // data cache flush leads to ins tlb flush, flush all tlb entry 
+        icache_tlb.flush(true);    // global entries are invalidated
+        r_dcache_xtn_req = false;
+        r_icache_fsm = ICACHE_IDLE;
+        break;
+    }
+    ////////////////////////
+    case ICACHE_CACHE_FLUSH:
+    {
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_tgt_icache_req = false;
+        }
+
+        size_t way = r_icache_way;
+        size_t set = r_icache_set;
+        bool clean = false;
+
+        m_cost_ins_cache_flush_frz++;
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+
+        // cache flush and send cleanup to external
+        if ( !r_icache_cleanup_req )
+        {
+            paddr_t victim_index = 0;
+            for ( ; way < m_icache_ways; way++ )
+            {    
+                for ( ; set < m_icache_sets; set++ )
+                {    
+                    if ( r_icache.flush(way, set, &victim_index) )
+                    {
+                        clean = true;
+                        r_icache_cleanup_req = true;
+                        r_icache_cleanup_line = victim_index;
+                        r_icache_way = way + ((set+1)/m_icache_sets);
+                        r_icache_set = (set+1) % m_icache_sets;
+                        break;
+                    }
+                }
+                if (clean) break;
+            }
+            if ((way == m_icache_ways) && (set == m_icache_sets))
+            {
+                r_dcache_xtn_req = false;
+                r_icache_fsm = ICACHE_IDLE;
+                break;
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB_INVAL:  
+    {
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+        paddr_t victim_index = 0;
+
+        if ( !r_dcache_itlb_cleanup_req )
+        {
+            r_dcache_itlb_cleanup_req = icache_tlb.inval(r_dcache_wdata_save, &victim_index);
+            r_dcache_itlb_cleanup_line = victim_index;
+            r_dcache_xtn_req = false;
+            r_itlb_translation_valid = false;
+            r_icache_ptba_ok = false;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    ////////////////////////
+    case ICACHE_CACHE_INVAL:
+    {	
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+
+        paddr_t ipaddr = 0;                     
+        bool    icache_hit_t = false;
+
+        if ( !r_icache_cleanup_req )
+        {    
+            if ( r_mmu_mode.read() & INS_TLB_MASK ) 
+            {
+                icache_hit_t = icache_tlb.translate(r_dcache_wdata_save, &ipaddr); 
+            } 
+            else 
+            {
+                ipaddr = (paddr_t)r_dcache_wdata_save;
+                icache_hit_t = true;
+            }
+            if ( icache_hit_t )
+            {
+                // invalidate and cleanup if necessary
+                r_icache_cleanup_req = r_icache.inval(ipaddr);
+                r_icache_cleanup_line = ipaddr >> (uint32_log2(m_icache_words) + 2);   
+            }
+            r_dcache_xtn_req = false; 
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    ///////////////////////
+    case ICACHE_MISS_WAIT:
+    {
+        m_cost_ins_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )     
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+       
+	if ( !r_icache_miss_req )
+	{
+	    if ( r_vci_rsp_ins_error ) 
+            {
+                r_icache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+
+            	if ( r_icache_inval_tlb_rsp ) r_icache_inval_tlb_rsp = false;
+            	if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
+		break;
+            }
+
+            if ( r_icache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_icache_fsm = ICACHE_IDLE;
+                r_icache_inval_tlb_rsp = false;
+                m_cost_ins_tlb_miss_frz++;
+                break;
+            }
+	
+            if ( r_icache_inval_rsp ) // Miss read response and tlb invalidation
+            {
+                r_icache_fsm = ICACHE_IDLE;
+                r_icache_inval_rsp = false;
+                break;
+            }
+            r_icache_fsm = ICACHE_MISS_UPDT;  
+	}	
+        break;
+    }
+    ////////////////////
+    case ICACHE_UNC_WAIT:
+    {
+        m_cost_ins_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req ) 
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_icache_unc_req )
+	{
+	    if ( r_vci_rsp_ins_error ) 
+            {
+                r_icache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS;    
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+
+            	if ( r_icache_inval_tlb_rsp ) r_icache_inval_tlb_rsp = false;
+            	//if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
+		break;
+            }
+
+	    if ( r_icache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;
+		break;
+            }
+/*	    
+	    if ( r_icache_inval_rsp ) // Miss read response and cache invalidation
+            {
+                r_icache_inval_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;
+		break;
+            }
+*/
+	    // Miss read response and no invalidation
+            r_icache_buf_unc_valid = true;
+            r_icache_fsm = ICACHE_IDLE;
+	}	
+        break;
+    }
+    //////////////////////
+    case ICACHE_MISS_UPDT:
+    {
+        m_cost_ins_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )   
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( r_icache_inval_tlb_rsp ) // tlb invalidation
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+            m_cost_ins_tlb_miss_frz++;
+            break;
+        }
+
+        if ( r_icache_inval_rsp ) // invalidation
+        {
+            r_icache_inval_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+            break;
+        } 
+
+        if ( !r_icache_cleanup_req ) // Miss update and no invalidation
+        {
+            data_t* buf = r_icache_miss_buf;
+            paddr_t  victim_index = 0;
+            m_cpt_icache_dir_write++;
+            m_cpt_icache_data_write++;
+
+            r_icache_cleanup_req = r_icache.update(r_icache_paddr_save.read(), buf, &victim_index);
+            r_icache_cleanup_line = victim_index;            
+
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    ///////////////////
+    case ICACHE_ERROR:
+    {
+        r_vci_rsp_ins_error = false;
+        r_dcache_rsp_itlb_error = false;
+        irsp.valid = true;
+        irsp.error = true;
+        irsp.instruction = 0; 
+        r_icache_fsm = ICACHE_IDLE;
+        break;
+    }
+    /////////////////////
+    case ICACHE_CC_INVAL:  
+    {                       
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+        m_cpt_icache_dir_read += m_icache_ways;
+
+        // invalidate cache
+        if( (( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT ) /*|| 
+             ( r_icache_fsm_save == ICACHE_UNC_WAIT )*/ ) && 
+            ((r_icache_paddr_save.read() & ~((m_icache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_icache_words<<2)-1))) ) 
+        {
+            r_icache_inval_rsp = true;
+        } 
+        else 
+        {
+            r_tgt_icache_rsp = r_icache.inval(r_tgt_addr.read());
+        }
+        r_tgt_icache_req = false;
+        r_icache_fsm = r_icache_fsm_save;
+        break;
+    }
+    /////////////////////////
+    case ICACHE_TLB_CC_INVAL:
+    {
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;        
+
+	if ( r_itlb_inval_req ) break;
+
+        // invalidate cache
+        if( (( r_icache_fsm_save == ICACHE_TLB1_READ ) || ( r_icache_fsm_save == ICACHE_TLB2_READ )  ||
+             ( r_icache_fsm_save == ICACHE_TLB1_WRITE )|| ( r_icache_fsm_save == ICACHE_TLB2_WRITE ) ||
+             ( r_icache_fsm_save == ICACHE_TLB1_UPDT ) || ( r_icache_fsm_save == ICACHE_TLB2_UPDT )) && 
+            (((r_icache_paddr_save.read() & ~((m_icache_words<<2)-1)) >> (uint32_log2(m_icache_words) + 2) ) == r_dcache_itlb_inval_line.read()) ) 
+        {
+            r_icache_inval_tlb_rsp = true;
+        } 
+        else if (((r_icache_fsm_save == ICACHE_BIS)||(r_icache_fsm_save == ICACHE_MISS_WAIT) ||
+                 (r_icache_fsm_save == ICACHE_UNC_WAIT)||(r_icache_fsm_save == ICACHE_MISS_UPDT)) && 
+                (r_icache_tlb_nline == r_dcache_itlb_inval_line))
+        {
+            r_icache_inval_tlb_rsp = true;
+        }
+	r_dcache_itlb_inval_req = false;
+        r_icache_fsm = r_icache_fsm_save;
+        break;
+    }
+    } // end switch r_icache_fsm
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout << name() << " Instruction Response: " << irsp << std::endl;
+#endif
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //      INVAL ITLB CHECK FSM 
+    ////////////////////////////////////////////////////////////////////////////////////////
+    switch(r_inval_itlb_fsm) {
+    /////////////////////
+    case INVAL_ITLB_IDLE:
+    {
+        if ( r_itlb_inval_req )
+        {
+            r_ccinval_itlb_way = 0; 
+            r_ccinval_itlb_set = 0;
+            r_inval_itlb_fsm = INVAL_ITLB_CHECK;   
+            m_cost_ins_tlb_inval_frz++; 
+        }   
+        break;
+    }
+    ////////////////////////////
+    case INVAL_ITLB_CHECK:
+    {
+        m_cost_ins_tlb_inval_frz++; 
+
+        size_t way = r_ccinval_itlb_way; 
+        size_t set = r_ccinval_itlb_set;
+        bool end = false;        
+        bool tlb_hit = icache_tlb.cccheck(r_dcache_itlb_inval_line.read(), way, set, &way, &set, &end); 
+    
+        if ( tlb_hit )
+        {
+            r_ccinval_itlb_way = way; 
+            r_ccinval_itlb_set = set;
+            r_itlb_cc_check_end = end;
+            r_inval_itlb_fsm = INVAL_ITLB_INVAL; 
+            m_cpt_ins_tlb_inval++;   
+        }        
+        else
+        {
+            r_inval_itlb_fsm = INVAL_ITLB_CLEAR;    
+        }
+        break;
+    }
+    /////////////////////////
+    case INVAL_ITLB_INVAL:
+    {
+        m_cost_ins_tlb_inval_frz++;
+ 
+        icache_tlb.ccinval(r_ccinval_itlb_way, r_ccinval_itlb_set);
+
+        if ( !r_itlb_cc_check_end )
+        {
+            r_inval_itlb_fsm = INVAL_ITLB_CHECK; 
+        }
+        else
+        {
+            r_inval_itlb_fsm = INVAL_ITLB_CLEAR;    
+        }
+        break;
+    }
+    ////////////////////
+    case INVAL_ITLB_CLEAR:
+    {
+        r_itlb_inval_req = false;
+        r_itlb_cc_check_end = false;
+        r_ccinval_itlb_way = 0; 
+        r_ccinval_itlb_set = 0; 
+        r_inval_itlb_fsm = INVAL_ITLB_IDLE;    
+        m_cost_ins_tlb_inval_frz++; 
+        break;
+    }
+    } // end switch r_inval_itlb_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //      DCACHE FSM 
+    //
+    // Both the Cacheability Table, and the MMU cached bit are used to define
+    // the cacheability.
+    // 
+    // There is 14 mutually exclusive conditions to exit the IDLE state.
+    // Seven configurations corresponding to an XTN request from processor:
+    // - Context switch => CTXT_SWITCH state
+    // - Flush dcache => DCACHE_FLUSH state 
+    // - Flush icache => ICACHE_FLUSH state 
+    // - Invalidate a dtlb entry => DTLB_INVAL state
+    // - Invalidate a itlb entry => ITLB_INVAL state
+    // - Invalidate a dcache line => DCACHE_INVAL state
+    // - Invalidate a icache line => ICACHE_INVAL state
+    // Seven configurations corresponding to various read miss or write requests: 
+    // - TLB miss(in case hit_p miss) => TLB1_READ state
+    // - TLB miss(in case hit_p hit) => TLB2_READ state
+    // - Hit in TLB but VPN changed => BIS state
+    // - Cached read miss => MISS_REQ state
+    // - Uncache read miss => UNC_REQ state
+    // - Write hit => WRITE_UPDT state
+    // - Write miss => WRITE_REQ
+    //
+    // The r_vci_rsp_data_error flip-flop is set by the VCI_RSP controller and reset 
+    // by DCACHE-FSM when its state is in DCACHE_ERROR. 
+    //--------------------------------------------------------------------- 
+    // Data TLB: 
+    //  
+    // - int        ET          (00: unmapped; 01: unused or PTD)
+    //                          (10: PTE new;  11: PTE old      )
+    // - bool       cachable    (cached bit)
+    // - bool       writable    (writable bit) 
+    // - bool       executable  (** not used alwayse false)
+    // - bool       user        (access in user mode allowed)
+    // - bool       global      (PTE not invalidated by a TLB flush)
+    // - bool       dirty       (page has been modified) 
+    // - uint32_t   vpn         (virtual page number)
+    // - uint32_t   ppn         (physical page number)
+    ////////////////////////////////////////////////////////////////////////////////////////
+
+    switch (r_dcache_fsm) {
+    //////////////////////
+    case DCACHE_WRITE_REQ:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++; 
+            break;
+        }
+
+        // try to post the write request in the write buffer
+        if ( !r_dcache_write_req )     // no previous write transaction     
+        {
+            if ( r_wbuf.wok(r_dcache_paddr_save) )   // write request in the same cache line 
+            {    
+                r_wbuf.write(r_dcache_paddr_save.read(), r_dcache_be_save.read(), r_dcache_wdata_save);
+                // closing the write packet if uncached
+                if ( !r_dcache_cached_save )
+                { 
+                    r_dcache_write_req = true;
+                }
+            } 
+            else 
+            {    // close the write packet if write request not in the same cache line
+                r_dcache_write_req = true;
+                m_cost_write_frz++;
+                break;  //  posting not possible : stay in DCACHE_WRITEREQ state
+            }
+        } 
+        else     //  previous write transaction not completed
+        {
+            m_cost_write_frz++;
+            break;  //  posting not possible : stay in DCACHE_WRITEREQ state
+        }
+
+        // close the write packet if the next processor request is not a write 
+        if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE)) 
+        {
+            r_dcache_write_req = true;
+        }
+        
+        // The next state and the processor request parameters are computed 
+        // as in the DCACHE_IDLE state (see below ...)
+    }
+    /////////////////
+    case DCACHE_IDLE:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = DCACHE_IDLE;
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // ins tlb cleanup
+        if ( r_dcache_itlb_cleanup_req )
+        {
+            r_dcache_fsm = DCACHE_ITLB_CLEANUP;
+            m_cpt_ins_tlb_cleanup++;
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+            break;
+        }    
+        // ins tlb miss
+    	if ( r_itlb_read_dcache_req )
+    	{
+            data_t rsp_itlb_miss;
+	    data_t rsp_itlb_ppn;
+
+    	    bool itlb_hit_dcache = r_dcache.read(r_icache_paddr_save, &rsp_itlb_miss);
+	    if ( (r_icache_fsm == ICACHE_TLB2_READ) && itlb_hit_dcache )
+	    {	
+	        bool itlb_hit_ppn = r_dcache.read(r_icache_paddr_save.read()+4, &rsp_itlb_ppn);
+		assert(itlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+	    }
+
+            m_cpt_dcache_data_read += m_dcache_ways;
+            m_cpt_dcache_dir_read += m_dcache_ways;
+
+    	    if ( itlb_hit_dcache )  // ins TLB request hits in data cache 
+    	    {
+                r_dcache_rsp_itlb_miss = rsp_itlb_miss; 
+                r_dcache_rsp_itlb_ppn = rsp_itlb_ppn; 
+    	    	r_itlb_read_dcache_req = false;
+                r_dcache_fsm = DCACHE_IDLE;
+                
+                // set TLB bit if it's a PTE
+                if ( !((rsp_itlb_miss & PTE_T_MASK ) >> PTE_T_SHIFT) )
+                {
+                    r_dcache.setinbit(r_icache_paddr_save, r_dcache_in_itlb, true);
+                }
+    	    }
+    	    else                    // ins TLB request miss in data cache
+    	    {
+                r_dcache_itlb_read_req = true;
+                r_dcache_fsm = DCACHE_ITLB_READ;
+            }
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++; 
+    	}
+    	else if ( r_itlb_acc_dcache_req ) // ins tlb write access bit
+    	{
+            bool write_hit = r_dcache.write(r_icache_paddr_save, r_icache_pte_update);
+            assert(write_hit && "Write on miss ignores data");
+            r_dcache_itlb_ll_acc_req = true;
+	    r_dcache_fsm = DCACHE_ITLB_LL_WAIT;	    		
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++; 
+    	}
+        else if (dreq.valid) 
+        {
+            pte_info_t  dcache_pte_info;
+            int         xtn_opcod        = (int)dreq.addr/4;
+            paddr_t     tlb_dpaddr       = 0;        // physical address obtained from TLB
+            paddr_t     spc_dpaddr       = 0;        // physical adress obtained from PPN_save (speculative)
+            bool        dcache_hit_t     = false;    // hit on 4Kilo TLB
+            bool        dcache_hit_x     = false;    // VPN unmodified (can use spc_dpaddr)
+            bool        dcache_hit_p     = false;    // PTP unmodified (can skip first level page table walk)
+            bool        dcache_hit_c     = false;    // Cache hit
+            bool        dcache_cached    = false;    // cacheable access (read or write)
+            size_t      dcache_tlb_way   = 0;        // selected way (in case of cache hit)
+            size_t      dcache_tlb_set   = 0;        // selected set (Y field in address)
+            data_t      dcache_rdata     = 0;        // read data
+            paddr_t     dcache_tlb_nline = 0;       // TLB NLINE 
+
+            m_cpt_dcache_data_read += m_dcache_ways;
+            m_cpt_dcache_dir_read += m_dcache_ways;
+
+            // Decoding READ XTN requests from processor
+            // They are executed in this DCACHE_IDLE state
+
+            if (dreq.type == iss_t::XTN_READ) 
+            {
+                switch(xtn_opcod) {
+                case iss_t::XTN_INS_ERROR_TYPE:
+                    drsp.rdata = (uint32_t)r_icache_error_type;
+                    r_icache_error_type = MMU_NONE;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_DATA_ERROR_TYPE:
+                    drsp.rdata = (uint32_t)r_dcache_error_type;
+                    r_dcache_error_type = MMU_NONE;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_INS_BAD_VADDR:
+                    drsp.rdata = (uint32_t)r_icache_bad_vaddr;       
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_DATA_BAD_VADDR:
+                    drsp.rdata = (uint32_t)r_dcache_bad_vaddr;        
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_PTPR:
+                    drsp.rdata = (uint32_t)r_mmu_ptpr;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_TLB_MODE:
+                    drsp.rdata = (uint32_t)r_mmu_mode;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_MMU_PARAMS:
+                    drsp.rdata = (uint32_t)r_mmu_params;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_MMU_RELEASE:
+                    drsp.rdata = (uint32_t)r_mmu_release;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                default:
+                    r_dcache_error_type = MMU_READ_UNDEFINED_XTN; 
+                    r_dcache_bad_vaddr  = dreq.addr;
+                    drsp.valid = true;
+                    drsp.error = true;
+                    break;
+                }
+                r_dcache_fsm = DCACHE_IDLE;
+                break;
+            }
+
+            // Decoding WRITE XTN requests from processor
+            // If there is no privilege violation, they are not executed in this DCACHE_IDLE state,
+            // but in the next state, because they generally require access to the caches or the TLBs 
+
+            if (dreq.type == iss_t::XTN_WRITE) 
+            {
+                drsp.valid = false;
+                drsp.error = false;
+                drsp.rdata = 0;
+                r_dcache_wdata_save = dreq.wdata;   
+                switch(xtn_opcod) {     
+
+                case iss_t::XTN_PTPR:       // context switch : checking the kernel mode
+                                            // both instruction & data TLBs must be flushed
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_mmu_ptpr = dreq.wdata;
+                        r_icache_error_type = MMU_NONE;
+                        r_dcache_error_type = MMU_NONE;
+                        r_dcache_type_save = dreq.addr/4; 
+                        r_dcache_xtn_req = true;
+                        r_dcache_fsm = DCACHE_CTXT_SWITCH;
+                    } 
+                    else 
+                    { 
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                	r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+
+                case iss_t::XTN_TLB_MODE:     // modifying TLBs mode : checking the kernel mode
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_mmu_mode = (int)dreq.wdata;
+                        drsp.valid = true;
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                    }
+                    r_dcache_fsm = DCACHE_IDLE;
+                    break;
+
+                case iss_t::XTN_DTLB_INVAL:     //  checking the kernel mode
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_dcache_fsm = DCACHE_DTLB_INVAL;  
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                	r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+
+                case iss_t::XTN_ITLB_INVAL:     //  checking the kernel mode
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_dcache_xtn_req = true;
+                        r_dcache_type_save = dreq.addr/4;
+                        r_dcache_fsm = DCACHE_ITLB_INVAL;  
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                	r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+
+                case iss_t::XTN_DCACHE_INVAL:   // cache inval can be executed in user mode.
+                    r_dcache_fsm = DCACHE_DCACHE_INVAL;
+                    break;
+
+                case iss_t::XTN_DCACHE_FLUSH:   // cache flush can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true;
+                    r_dcache_way = 0;
+                    r_dcache_set = 0;
+                    r_dcache_fsm = DCACHE_DCACHE_FLUSH; 
+                    break;
+
+                case iss_t::XTN_ICACHE_INVAL:   // cache inval can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true;
+                    r_dcache_fsm = DCACHE_ICACHE_INVAL; 
+                    break;
+
+                case iss_t::XTN_ICACHE_FLUSH:   // cache flush can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true; 
+                    r_dcache_fsm = DCACHE_ICACHE_FLUSH;
+                    break;
+
+                case iss_t::XTN_SYNC:           // cache synchronization can be executed in user mode.
+                    if (r_wbuf.rok())
+                    {
+                        r_dcache_fsm = DCACHE_DCACHE_SYNC; 
+                    }
+                    else
+                    {
+                        drsp.valid = true;
+                        r_dcache_fsm = DCACHE_IDLE;
+                    }
+		    break;
+	
+                default:
+                    r_dcache_error_type = MMU_WRITE_UNDEFINED_XTN; 
+                    r_dcache_bad_vaddr  = dreq.addr;
+                    drsp.valid = true;
+                    drsp.error = true;
+                    r_dcache_fsm = DCACHE_IDLE;
+                    break;
+                } // end switch xtn_opcod
+
+                break;
+            } // end if XTN_WRITE
+
+            // Evaluating dcache_hit_t, dcache_hit_x, dcache_hit_p, dcache_hit_c,
+            // dcache_pte_info, dcache_tlb_way, dcache_tlb_set & dpaddr & cacheability 
+            // - If MMU activated : cacheability is defined by the cachable bit in the TLB
+            // - If MMU not activated : cacheability is defined by the segment table.
+
+            if ( !(r_mmu_mode.read() & DATA_TLB_MASK) ) // MMU not activated
+            {
+                dcache_hit_t  = true;       
+                dcache_hit_x  = true;   
+                dcache_hit_p  = true;  
+                tlb_dpaddr    = dreq.addr; 
+                spc_dpaddr    = dreq.addr;    
+                dcache_cached = m_cacheability_table[dreq.addr] && 
+                                ((dreq.type != iss_t::DATA_LL)  && (dreq.type != iss_t::DATA_SC) &&
+                                 (dreq.type != iss_t::XTN_READ) && (dreq.type != iss_t::XTN_WRITE));     
+            } 
+            else                                                            // MMU activated
+            {
+                m_cpt_data_tlb_read++;
+                dcache_hit_t  = dcache_tlb.cctranslate(dreq.addr, &tlb_dpaddr, &dcache_pte_info, 
+                                                       &dcache_tlb_nline, &dcache_tlb_way, &dcache_tlb_set);                  
+                dcache_hit_x  = (((vaddr_t)r_dcache_vpn_save << PAGE_K_NBITS) == (dreq.addr & ~PAGE_K_MASK)) && r_dtlb_translation_valid; 
+                dcache_hit_p  = (((dreq.addr >> PAGE_M_NBITS) == r_dcache_id1_save) && r_dcache_ptba_ok );
+                spc_dpaddr    = ((paddr_t)r_dcache_ppn_save << PAGE_K_NBITS) | (paddr_t)((dreq.addr & PAGE_K_MASK));
+                dcache_cached = dcache_pte_info.c && 
+                                ((dreq.type != iss_t::DATA_LL)  && (dreq.type != iss_t::DATA_SC) &&
+                                 (dreq.type != iss_t::XTN_READ) && (dreq.type != iss_t::XTN_WRITE));    
+            }
+
+            if ( !(r_mmu_mode.read() & DATA_CACHE_MASK) )   // cache not actived
+            {
+                dcache_cached = false;
+            }
+
+            // dcache_hit_c & dcache_rdata
+            if ( dcache_cached )    // using speculative physical address for cached access
+            {
+                dcache_hit_c = r_dcache.read(spc_dpaddr, &dcache_rdata);
+            } 
+            else                    // using actual physical address for uncached access
+            {
+                dcache_hit_c = ((tlb_dpaddr == (paddr_t)r_dcache_paddr_save) && r_dcache_buf_unc_valid ); 
+                dcache_rdata = r_dcache_miss_buf[0];
+            }
+
+            if ( r_mmu_mode.read() & DATA_TLB_MASK ) 
+            {
+                // Checking access rights
+                if ( dcache_hit_t ) 
+                {
+                    if (!dcache_pte_info.u && (dreq.mode == iss_t::MODE_USER)) 
+                    {
+                        if ((dreq.type == iss_t::DATA_READ)||(dreq.type == iss_t::DATA_LL))
+                        {
+                            r_dcache_error_type = MMU_READ_PRIVILEGE_VIOLATION;
+                        }
+                        else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                        {
+                            r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION;
+                        }  
+                        r_dcache_bad_vaddr = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                        drsp.rdata = 0;
+                        r_dcache_fsm = DCACHE_IDLE;
+                        break;
+                    }
+                    if (!dcache_pte_info.w && ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))) 
+                    {
+                        r_dcache_error_type = MMU_WRITE_ACCES_VIOLATION;  
+                        r_dcache_bad_vaddr = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                        drsp.rdata = 0;
+                        r_dcache_fsm = DCACHE_IDLE;
+                        break;
+                    }
+                }
+
+                // update LRU, save ppn, vpn and page type
+                if ( dcache_hit_t ) {
+                    dcache_tlb.setlru(dcache_tlb_way,dcache_tlb_set); 
+                    r_dcache_ppn_save = tlb_dpaddr >> PAGE_K_NBITS;
+                    r_dcache_vpn_save = dreq.addr >> PAGE_K_NBITS;
+                    r_dcache_tlb_nline = dcache_tlb_nline;
+                    r_dtlb_translation_valid = true;
+                }
+                else
+                {
+                    r_dtlb_translation_valid = false;
+                }
+
+            } // end if MMU activated
+
+            // compute next state 
+            if ( !dcache_hit_p && !dcache_hit_t )  // TLB miss
+            {
+                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                m_cpt_data_tlb_miss++;
+                m_cost_data_tlb_miss_frz++;
+            }
+            else if ( dcache_hit_p && !dcache_hit_t )  // TLB Miss with possibility of bypass first level page
+            {
+                // walk page table level 2
+                r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save | 
+                                     (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3); 
+                r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
+                m_cpt_data_tlb_miss++;
+                m_cost_data_tlb_miss_frz++;
+            }
+            else if ( dcache_hit_t && !dcache_hit_x && dcache_cached )// cached access with an ucorrect speculative physical address
+            {
+                r_dcache_hit_p_save = dcache_hit_p;
+                r_dcache_fsm = DCACHE_BIS;
+                m_cost_data_miss_frz++;
+            }
+            else  // cached or uncached access with a correct speculative physical address
+            {
+                switch( dreq.type ) {
+                    case iss_t::DATA_READ:
+                    case iss_t::DATA_LL:
+                    case iss_t::DATA_SC:
+                        m_cpt_read++;
+                        if ( dcache_hit_c ) 
+                        {
+                            r_dcache_buf_unc_valid = false;
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+                        } 
+                        else 
+                        {
+                            if ( dcache_cached ) 
+                            {
+                                r_dcache_miss_req = true;
+                                r_dcache_fsm = DCACHE_MISS_WAIT;
+                                m_cpt_data_miss++;
+                                m_cost_data_miss_frz++;
+                            } 
+                            else 
+                            {
+                                r_dcache_unc_req = true;
+                                r_dcache_fsm = DCACHE_UNC_WAIT;
+                                m_cpt_unc_read++;
+                                m_cost_unc_read_frz++;
+                            }
+                        }
+                        break;
+/*
+                    case iss_t::DATA_READ:
+                        m_cpt_read++;
+                        if ( dcache_hit_c ) 
+                        {
+                            r_dcache_buf_unc_valid = false;
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+                        } 
+                        else 
+                        {
+                            if ( dcache_cached ) 
+                            {
+                                r_dcache_miss_req = true;
+                                r_dcache_fsm = DCACHE_MISS_WAIT;
+                                m_cpt_data_miss++;
+                                m_cost_data_miss_frz++;
+                            } 
+                            else 
+                            {
+                                r_dcache_unc_req = true;
+                                r_dcache_fsm = DCACHE_UNC_WAIT;
+                                m_cpt_unc_read++;
+                                m_cost_unc_read_frz++;
+                            }
+                        }
+                        break;
+                    case iss_t::DATA_LL:
+			if (r_dcache_llsc_reserved && (r_dcache_llsc_addr_save == tlb_dpaddr) && r_dcache_buf_unc_valid)
+			{
+                            r_dcache_buf_unc_valid = false;
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+			}
+			else
+			{
+			    r_dcache_llsc_reserved = true;
+			    r_dcache_llsc_addr_save = tlb_dpaddr;
+                            r_dcache_unc_req = true;
+                            r_dcache_fsm = DCACHE_UNC_WAIT;
+			}
+			break;
+                    case iss_t::DATA_SC:
+			if (r_dcache_llsc_reserved && (r_dcache_llsc_addr_save == tlb_dpaddr))
+			{
+			    r_dcache_llsc_reserved = false;
+                            r_dcache_unc_req = true;
+                            r_dcache_fsm = DCACHE_UNC_WAIT;
+			}
+			else
+			{   
+			    if ( r_dcache_buf_unc_valid )
+			    {                         
+			        r_dcache_llsc_reserved = false;
+			        r_dcache_buf_unc_valid = false;
+                                drsp.valid = true;
+                                drsp.rdata = dcache_rdata;
+			    }
+                            r_dcache_fsm = DCACHE_IDLE;
+			}			
+			break;
+*/
+                    case iss_t::DATA_WRITE:
+                        m_cpt_write++;
+                        if ( dcache_cached ) m_cpt_write_cached++;
+
+                        if ( dcache_hit_c && dcache_cached )    // cache update required
+                        {
+                            r_dcache_fsm = DCACHE_WRITE_UPDT;
+                        } 
+                        else if ( !dcache_pte_info.d && (r_mmu_mode.read() & DATA_TLB_MASK) )   // dirty bit update required
+                        {
+                            if ( dcache_tlb.getpagesize(dcache_tlb_way, dcache_tlb_set) )	// 2M page size, one level page table 
+                            {
+                                r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
+                                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                                r_dcache_tlb_ll_dirty_req = true;
+                                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                                m_cpt_data_tlb_write_dirty++;
+                            }
+                            else	// 4k page size, two levels page table 
+                            {   
+                                if (dcache_hit_p) 
+                                {
+                                    r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
+                                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save | (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                                    r_dcache_tlb_ll_dirty_req = true;
+                                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                                    m_cpt_data_tlb_write_dirty++;
+                                }
+                                else    // get PTBA to calculate the physical address of PTE
+                                {
+                                    r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
+                                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                                    r_dcache_tlb_ptba_read = true;
+                                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                                }
+                            }
+                            m_cost_data_tlb_miss_frz++;
+                        }
+                        else                                    // no cache update, not dirty bit update
+                        {
+                            r_dcache_fsm = DCACHE_WRITE_REQ;
+                            drsp.valid = true;
+                            drsp.rdata = 0;
+                        }
+                        break;
+                    default:
+                        break;
+                } // end switch dreq.type
+            } // end if next states
+
+            // save values for the next states
+            r_dcache_paddr_save   = tlb_dpaddr;
+            r_dcache_type_save    = dreq.type;
+            r_dcache_wdata_save   = dreq.wdata;
+            r_dcache_be_save      = dreq.be;
+            r_dcache_rdata_save   = dcache_rdata;
+            r_dcache_cached_save  = dcache_cached;
+            r_dcache_dirty_save   = dcache_pte_info.d;
+            r_dcache_tlb_set_save = dcache_tlb_set;
+            r_dcache_tlb_way_save = dcache_tlb_way;
+
+        } // end if dreq.valid
+        else 
+        {   
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+
+        // processor request are not accepted in the WRITE_REQ state 
+        // when the write buffer is not writeable
+
+        if ((r_dcache_fsm == DCACHE_WRITE_REQ) && 
+            (r_dcache_write_req || !r_wbuf.wok(r_dcache_paddr_save))) 
+        {
+            drsp.valid = false;
+        }
+        break;
+    }
+    /////////////////
+    case DCACHE_BIS:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        data_t  dcache_rdata = 0;
+        bool    dcache_hit_c = false;
+        bool    dcache_hit_t = false;
+        paddr_t tlb_dpaddr   = 0;
+
+	dcache_hit_t = dcache_tlb.translate(dreq.addr, &tlb_dpaddr);
+
+	if ( (tlb_dpaddr == r_dcache_paddr_save.read()) && dreq.valid && dcache_hit_t ) 
+	{
+	    // acces always cached in this state
+	    dcache_hit_c = r_dcache.read(r_dcache_paddr_save, &dcache_rdata);
+	    
+	    if ( dreq.type == iss_t::DATA_READ )  // cached read
+	    {
+	        m_cpt_read++;
+	        if ( !dcache_hit_c ) 
+	        {
+	            r_dcache_miss_req = true;
+	            r_dcache_fsm = DCACHE_MISS_WAIT;
+	            m_cpt_data_miss++;
+	            m_cost_data_miss_frz++;
+	        }
+	        else
+	        {
+	            r_dcache_fsm = DCACHE_IDLE;
+	        }
+	        drsp.valid = dcache_hit_c;
+	        drsp.error = false;
+	        drsp.rdata = dcache_rdata;
+	    }
+	    else    // cached write
+	    {
+	        m_cpt_write++;
+	        m_cpt_write_cached++;
+	        if ( dcache_hit_c )    // cache update required
+	        {
+	            r_dcache_rdata_save = dcache_rdata;
+	            r_dcache_fsm = DCACHE_WRITE_UPDT;
+	        } 
+	        else if (!r_dcache_dirty_save && (r_mmu_mode.read() & DATA_TLB_MASK))   // dirty bit update required
+	        {
+	            if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save)) 
+	            {
+	                r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+	                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+	                r_dcache_tlb_ll_dirty_req = true;
+	                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+	                m_cpt_data_tlb_write_dirty++;
+	            }
+	            else
+	            {   
+	                if (r_dcache_hit_p_save) 
+	                {
+	                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+	                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+	                    r_dcache_tlb_ll_dirty_req = true;
+	                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+	                    m_cpt_data_tlb_write_dirty++;
+	                }
+	                else
+	                {
+	                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+	                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+	                    r_dcache_tlb_ptba_read = true;
+	                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+	                }
+	            }
+	            m_cost_data_tlb_miss_frz++;
+	        }
+	        else                                    // no cache update, not dirty bit update
+	        {
+	            r_dcache_fsm = DCACHE_WRITE_REQ;
+	            drsp.valid = true;
+	            drsp.rdata = 0;
+	        }
+	    }
+	}
+	else
+	{
+            drsp.valid = false;
+            drsp.error = false;
+            drsp.rdata = 0;
+            r_dcache_fsm = DCACHE_IDLE;
+	}
+        break;
+    }
+    //////////////////////////
+    case DCACHE_LL_DIRTY_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_tlb_ll_dirty_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+		if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save)) 
+		{
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;     
+		}
+		else
+		{
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;     
+		}
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+            }
+	    else
+	    {
+		if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+		    if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
+		    { 
+			r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;       
+		    }
+		    else
+		    {
+			r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;       
+	  	    }
+                    r_dcache_bad_vaddr = dreq.addr;
+                    r_dcache_fsm = DCACHE_ERROR;
+
+		    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+	        }
+        	else if ( r_dcache_inval_tlb_rsp )
+        	{
+        	    r_dcache_inval_tlb_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	    m_cost_data_tlb_miss_frz++;
+        	}
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+		else
+		{
+		    r_dcache_tlb_sc_dirty_req = true;
+		    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
+                    r_dcache_fsm = DCACHE_SC_DIRTY_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    //////////////////////////
+    case DCACHE_SC_DIRTY_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_tlb_sc_dirty_req )
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+	        if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
+	        {
+	            r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;    
+	        }
+	        else
+	        {
+	            r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;    
+	        }
+	        r_dcache_bad_vaddr = dreq.addr;
+	        r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;		 		         }
+	    else 
+	    {
+                // Using tlb entry is invalidated 
+                if ( r_dcache_inval_tlb_rsp )
+                {
+                    r_dcache_inval_tlb_rsp = false;
+                    r_dcache_fsm = DCACHE_IDLE;
+                    m_cost_data_tlb_miss_frz++;
+                }
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+		else if ( r_dcache_tlb_ll_dirty_req )
+	        {
+	            r_dcache_fsm = DCACHE_LL_DIRTY_WAIT; 
+	        }
+		else
+		{
+	            r_dcache_fsm = DCACHE_WRITE_DIRTY; 
+		}
+	    }
+	}
+	break;
+    }
+    ////////////////////////////
+    case DCACHE_DTLB1_READ_CACHE:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        data_t tlb_data = 0;
+	bool write_hit = false;
+        bool tlb_hit_cache = r_dcache.read(r_dcache_tlb_paddr, &tlb_data);
+
+        // DTLB request hit in cache
+        if ( tlb_hit_cache )
+        {
+	    if ( !(tlb_data >> PTE_V_SHIFT) )	// unmapped
+	    {
+                r_dcache_ptba_ok    = false;
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
+                }  
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (tlb_data & PTE_T_MASK) >> PTE_T_SHIFT )	// PTD
+	    {
+                r_dcache_ptba_ok   = true;
+                r_dcache_ptba_save = (paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS;  
+                r_dcache_id1_save  = dreq.addr >> PAGE_M_NBITS;
+                r_dcache_tlb_paddr = (paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                     (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
+                if ( r_dcache_tlb_ptba_read )
+                {
+                    r_dcache_tlb_ptba_read = false;
+                    write_hit = r_dcache.write(((paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                                (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3)), r_dcache_pte_update);
+                    assert(write_hit && "Write on miss ignores data");
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {
+                    r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
+                }
+	    }
+	    else	// PTE
+	    {
+                r_dcache_ptba_ok = false;
+	        if ( (m_srcid >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (tlb_data & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+                        r_dcache_fsm = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_L_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (tlb_data & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+                        r_dcache_fsm = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_R_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        else
+        {
+            // DTLB request miss in cache and walk page table level 1
+            r_dcache_tlb_read_req = true;
+            r_dcache_fsm = DCACHE_TLB1_READ;
+        }
+        break;
+    }
+    ///////////////////////
+    case DCACHE_TLB1_LL_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_tlb_ll_acc_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;		 
+            }
+	    else
+	    {
+		if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+               	    if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+               	    {
+               	        r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
+               	    }
+               	    else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+               	    {
+               	        r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
+               	    }  
+                    r_dcache_bad_vaddr  = dreq.addr;
+                    r_dcache_fsm        = DCACHE_ERROR;
+
+		    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	        }
+       		else if ( r_dcache_inval_tlb_rsp )
+       		{
+       		    r_dcache_inval_tlb_rsp = false;
+       		    r_dcache_fsm = DCACHE_IDLE;
+       		    m_cost_data_tlb_miss_frz++;
+       		}
+		else if ( r_dcache_inval_rsp )
+       		{
+       		    r_dcache_inval_rsp = false;
+       		    r_dcache_fsm = DCACHE_IDLE;
+       		}
+		else
+		{
+		    r_dcache_tlb_sc_acc_req = true;
+		    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
+                    r_dcache_fsm = DCACHE_TLB1_SC_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    ///////////////////////
+    case DCACHE_TLB1_SC_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_tlb_sc_acc_req )
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
+                } 
+	        r_dcache_bad_vaddr = dreq.addr;
+	        r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	    }
+	    else
+	    {
+        	// Using tlb entry is invalidated 
+        	if ( r_dcache_inval_tlb_rsp )
+        	{
+        	    r_dcache_inval_tlb_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	    m_cost_data_tlb_miss_frz++;
+        	}
+		else if ( r_dcache_inval_rsp )
+        	{
+        	    r_dcache_inval_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	}
+	    	else if ( r_dcache_tlb_ll_acc_req )
+	    	{
+	    	    r_dcache_fsm = DCACHE_TLB1_LL_WAIT; 
+	    	}
+	    	else 
+	    	{
+	    	    r_dcache_fsm = DCACHE_TLB1_UPDT; 
+	    	}
+	    }
+	}
+	break;
+    }
+    //////////////////////
+    case DCACHE_TLB1_READ:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+	if ( !r_dcache_tlb_read_req )
+	{	
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+		break;
+            }
+
+            if ( r_dcache_inval_tlb_rsp )  // TLB miss response and invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_tlb_rsp = false;
+		break;
+            }
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+		break;	    
+	    }
+	    // TLB miss response and no invalidation
+	    r_dcache_fsm = DCACHE_TLB1_READ_UPDT;
+	}
+        break;
+    }
+    //////////////////////////
+    case DCACHE_TLB1_READ_UPDT:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        // Using tlb entry is in the invalidated cache line  
+        if ( r_dcache_inval_rsp )
+        {
+            r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if ( !r_dcache_cleanup_req ) // Miss update and no invalidation
+        {
+            // update dcache
+            data_t   rsp_dtlb_miss = 0;
+            paddr_t  victim_index = 0;
+	    bool write_hit = false;
+            size_t way = 0;
+            size_t set = 0;
+
+            bool cleanup_req = r_dcache.find(r_dcache_tlb_paddr, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+            
+	    if ( cleanup_req )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+	    r_dcache.update(r_dcache_tlb_paddr, way, set, r_dcache_miss_buf);
+            r_dcache.read(r_dcache_tlb_paddr, &rsp_dtlb_miss);	
+
+	    if ( !(rsp_dtlb_miss >> PTE_V_SHIFT) )	// unmapped
+	    {
+                r_dcache_ptba_ok    = false;
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
+                } 
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (rsp_dtlb_miss & PTE_T_MASK) >> PTE_T_SHIFT ) // PTD
+	    {
+                r_dcache_ptba_ok   = true;
+                r_dcache_ptba_save = (paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS;  
+                r_dcache_id1_save  = dreq.addr >> PAGE_M_NBITS;
+                r_dcache_tlb_paddr = (paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                     (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
+                if ( r_dcache_tlb_ptba_read )
+                {
+                    r_dcache_tlb_ptba_read = false;
+                    write_hit = r_dcache.write(((paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                                (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3)),r_dcache_pte_update);
+                    assert(write_hit && "Write on miss ignores data");
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {
+                    r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
+                }
+	    }
+	    else	// PTE
+	    {
+                r_dcache_ptba_ok = false;
+	        if ( (m_srcid >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (rsp_dtlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+                        r_dcache_fsm        = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_L_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm        = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (rsp_dtlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+                        r_dcache_fsm        = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_R_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm        = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        break;
+    }
+    //////////////////////
+    case DCACHE_TLB1_UPDT: 
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        if ( !r_dcache_inval_tlb_rsp && !r_dcache_inval_rsp )
+        {
+            paddr_t victim_index = 0;
+            if (dcache_tlb.update(r_dcache_pte_update,dreq.addr,(r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index))
+            {
+                r_dcache.setinbit((paddr_t)victim_index*m_dcache_words*2, r_dcache_in_dtlb, false);
+            }
+            r_dcache.setinbit(r_dcache_tlb_paddr, r_dcache_in_dtlb, true);
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        else  
+        {
+            if ( r_dcache_inval_tlb_rsp ) r_dcache_inval_tlb_rsp = false;
+            if ( r_dcache_inval_rsp ) r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        break;
+    }
+    /////////////////////////////
+    case DCACHE_DTLB2_READ_CACHE:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        data_t tlb_data = 0;
+        data_t tlb_data_ppn = 0;
+	bool write_hit = false;
+        bool tlb_hit_cache = r_dcache.read(r_dcache_tlb_paddr, &tlb_data);
+
+	if ( tlb_hit_cache )
+	{
+            bool tlb_hit_ppn = r_dcache.read(r_dcache_tlb_paddr.read()+4, &tlb_data_ppn);
+	    assert(tlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+	}
+
+        // DTLB request hit in cache
+        if ( tlb_hit_cache )
+        {
+	    if ( !(tlb_data >> PTE_V_SHIFT) )	// unmapped
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
+                } 
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (tlb_data & PTE_T_MASK) >> PTE_T_SHIFT ) //PTD
+	    {
+                r_dcache_pte_update = tlb_data;
+	        r_dcache_ppn_update = tlb_data_ppn;
+		r_dcache_fsm = DCACHE_TLB2_UPDT;
+	    }
+	    else 
+	    {
+	        if ( (m_srcid >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (tlb_data & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_L_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (tlb_data & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_R_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        else
+        {
+            // DTLB request miss in cache and walk page table level 2
+            r_dcache_tlb_read_req = true;
+            r_dcache_fsm = DCACHE_TLB2_READ;
+        }
+        break;
+    }
+    ///////////////////////
+    case DCACHE_TLB2_LL_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_tlb_ll_acc_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+            }
+	    else
+	    {
+	        if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+               	    if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+               	    {
+               	        r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
+               	    }
+               	    else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+               	    {
+               	        r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
+               	    } 
+                    r_dcache_bad_vaddr = dreq.addr;
+                    r_dcache_fsm = DCACHE_ERROR;
+
+		    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+	        }
+        	else if ( r_dcache_inval_tlb_rsp )
+        	{
+        	    r_dcache_inval_tlb_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	    m_cost_data_tlb_miss_frz++;
+        	}
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+		else
+		{
+		    r_dcache_tlb_sc_acc_req = true;
+		    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
+                    r_dcache_fsm = DCACHE_TLB2_SC_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    ///////////////////////
+    case DCACHE_TLB2_SC_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_tlb_sc_acc_req )
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
+                } 
+	        r_dcache_bad_vaddr = dreq.addr;
+	        r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	    }
+	    else
+	    { 
+                // Using tlb entry is invalidated 
+                if ( r_dcache_inval_tlb_rsp )
+                {
+                    r_dcache_inval_tlb_rsp = false;
+                    r_dcache_fsm = DCACHE_IDLE;
+                    m_cost_data_tlb_miss_frz++;
+                }
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+	        else if ( r_dcache_tlb_ll_acc_req )
+	        {
+	            r_dcache_fsm = DCACHE_TLB2_LL_WAIT; 
+	        }
+	        else 
+	        {
+	            r_dcache_fsm = DCACHE_TLB2_UPDT; 
+	        }
+	    }
+	}
+	break;
+    }
+    /////////////////////
+    case DCACHE_TLB2_READ:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+	if ( !r_dcache_tlb_read_req )
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            }	
+
+            if ( r_dcache_inval_tlb_rsp )  // TLB miss response and invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE; 
+                r_dcache_inval_tlb_rsp = false;
+		break;
+            }   
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+		break;	    
+	    }
+	    // TLB miss response and no invalidation
+	    r_dcache_fsm = DCACHE_TLB2_READ_UPDT; 
+	}	
+        break;
+    }
+    //////////////////////////
+    case DCACHE_TLB2_READ_UPDT:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        // Using tlb entry is in the invalidated cache line  
+        if ( r_dcache_inval_rsp )
+        {
+            r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if ( !r_dcache_cleanup_req )
+        {
+            // update cache
+            data_t rsp_dtlb_miss;
+            data_t tlb_data_ppn;
+	    bool write_hit = false;
+            paddr_t  victim_index = 0;
+            size_t way = 0;
+            size_t set = 0;
+
+            bool cleanup_req = r_dcache.find(r_dcache_tlb_paddr, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+
+	    if ( cleanup_req )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+	    r_dcache.update(r_dcache_tlb_paddr, way, set, r_dcache_miss_buf);
+	    r_dcache.read(r_dcache_tlb_paddr, &rsp_dtlb_miss);
+
+	    bool tlb_hit_ppn = r_dcache.read(r_dcache_tlb_paddr.read()+4, &tlb_data_ppn);
+	    assert(tlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+
+	    if ( !(rsp_dtlb_miss >> PTE_V_SHIFT) )	// unmapped
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
+                }  
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (rsp_dtlb_miss & PTE_T_MASK) >> PTE_T_SHIFT ) // PTD
+	    {
+                r_dcache_pte_update = rsp_dtlb_miss;
+	        r_dcache_ppn_update = tlb_data_ppn;
+		r_dcache_fsm = DCACHE_TLB2_UPDT;
+	    }
+	    else
+	    {
+	        if ( (m_srcid >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (rsp_dtlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_L_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (rsp_dtlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_R_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        break;
+    }
+    //////////////////////
+    case DCACHE_TLB2_UPDT:  
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        if ( !r_dcache_inval_tlb_rsp && !r_dcache_inval_rsp )
+        {
+            paddr_t victim_index = 0;
+            if (dcache_tlb.update(r_dcache_pte_update,r_dcache_ppn_update,dreq.addr,(r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index))
+            {
+                r_dcache.setinbit((paddr_t)victim_index*m_dcache_words*2, r_dcache_in_dtlb, false);
+            }
+            r_dcache.setinbit(r_dcache_tlb_paddr, r_dcache_in_dtlb, true);
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        else  
+        {
+            if ( r_dcache_inval_tlb_rsp ) r_dcache_inval_tlb_rsp = false;
+            if ( r_dcache_inval_rsp ) r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        break;
+    }
+    ///////////////////////
+    case DCACHE_CTXT_SWITCH:
+    {
+        // TLB flush leads to cleanup corresponding data cache line 
+        m_cost_data_tlb_sw_frz++;
+
+        paddr_t victim_index = 0;
+        size_t way = 0;
+        size_t set = 0;
+
+        if ( r_dcache_itlb_cleanup_req )
+        {    
+            r_dcache.setinbit(((paddr_t)r_dcache_itlb_cleanup_line.read()*m_dcache_words*2), r_dcache_in_itlb, false);
+            r_dcache_itlb_cleanup_req = false;
+	}
+
+        for ( way = 0; way < m_dtlb_ways; way++)
+        {
+            for ( set = 0; set < m_dtlb_sets; set++)
+            {
+                if(dcache_tlb.checkcleanup(way, set, &victim_index))
+                {
+                    r_dcache.setinbit((paddr_t)(victim_index << (m_dcache_words+2)), r_dcache_in_dtlb, false); 
+                }
+            }
+        }
+
+        if ((way == m_dtlb_ways) && (set == m_dtlb_sets) && (!r_dcache_xtn_req))
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            r_dtlb_translation_valid = false;
+            r_dcache_ptba_ok = false;
+            drsp.valid = true;
+        }
+        break;
+    }
+    ////////////////////////
+    case DCACHE_ICACHE_FLUSH:
+    case DCACHE_ICACHE_INVAL:
+    case DCACHE_ITLB_INVAL:
+    {
+        if ( !r_dcache_xtn_req ) 
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            drsp.valid = true;
+        }
+        break;
+    }
+    ////////////////////////
+    case DCACHE_DCACHE_FLUSH:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )
+        {
+            r_tgt_dcache_req = false;
+        }   
+
+        size_t way = r_dcache_way;
+        size_t set = r_dcache_set;
+        bool clean = false;
+        
+        m_cost_data_cache_flush_frz++;
+
+        // cache flush and send cleanup to external
+        if ( !r_dcache_cleanup_req )
+        {
+            paddr_t victim_index = 0;
+            for ( ; way < m_dcache_ways; way++ )
+            {    
+                for ( ; set < m_dcache_sets; set++ )
+                {  
+                    if ( r_dcache.flush(way, set, &victim_index) )
+                    {
+                        clean = true;
+                        r_dcache_cleanup_req = true;
+                        r_dcache_cleanup_line = victim_index;
+                        r_dcache_way = way + ((set+1)/m_dcache_sets);
+                        r_dcache_set = (set+1) % m_dcache_sets;
+                        break;
+                    }
+                }
+                if (clean) break;
+            }
+
+            if ((way == m_dcache_ways) && (set == m_dcache_sets) && !r_dcache_xtn_req ) 
+            {
+                // data TLB flush 
+                dcache_tlb.flush(true);      // global entries are not invalidated
+
+                for (size_t line = 0; line < m_dcache_ways*m_dcache_sets; line++)
+                {
+                    r_dcache_in_itlb[line] = false;
+                    r_dcache_in_dtlb[line] = false;
+                }
+
+                r_dcache_fsm = DCACHE_IDLE;
+                drsp.valid = true;
+                break;
+            }
+        }
+	break;
+    }
+    //////////////////////
+    case DCACHE_DTLB_INVAL: 
+    {
+        paddr_t victim_index = 0;
+        // clean indicate data tlb bit
+        if ( dcache_tlb.inval(r_dcache_wdata_save, &victim_index) )
+        {  
+            r_dcache.setinbit((paddr_t)(victim_index << (m_dcache_words+2)), r_dcache_in_dtlb, false); 
+        }
+        r_dtlb_translation_valid = false;
+        r_dcache_ptba_ok = false;
+        r_dcache_fsm = DCACHE_IDLE;
+        drsp.valid = true;
+        break;
+    }
+    ////////////////////////
+    case DCACHE_DCACHE_INVAL:
+    {
+        m_cpt_dcache_dir_read += m_dcache_ways;
+        vaddr_t invadr = dreq.wdata;
+        paddr_t dpaddr = 0;
+        bool dcache_hit_t = false; 
+        size_t way = 0;
+        size_t set = 0;
+
+	if ( !r_dcache_cleanup_req )
+	{
+            if ( r_mmu_mode.read() & DATA_TLB_MASK ) 
+            {
+                dcache_hit_t = dcache_tlb.translate(invadr, &dpaddr); 
+            } 
+            else 
+            {
+                dpaddr = invadr;  
+                dcache_hit_t = true;
+            }
+
+            if ( dcache_hit_t )
+            {
+		r_dcache_cleanup_req = r_dcache.inval(dpaddr, &way, &set);
+		r_dcache_cleanup_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+		
+		if ( r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[way*m_dcache_sets+set] ) 
+		{	
+		    // ins tlb invalidate verification
+		    r_dcache_itlb_inval_req = r_dcache_in_itlb[way*m_dcache_sets+set];
+		    r_dcache_itlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+		    r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+		
+		    // data tlb invalidate verification
+		    r_dcache_dtlb_inval_req = r_dcache_in_dtlb[way*m_dcache_sets+set];
+		    r_dcache_dtlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+		    r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+		    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+		    r_dcache_fsm_save = r_dcache_fsm;
+		    break;
+		}
+            }
+            r_dcache_fsm = DCACHE_IDLE;
+            drsp.valid = true;
+	}
+        break;
+    }
+    /////////////////////////
+    case DCACHE_DCACHE_SYNC:
+    {
+        if ( !r_dcache_write_req ) 
+        {
+            r_dcache_write_req = r_wbuf.rok();
+            drsp.valid = true;
+            r_dcache_fsm = DCACHE_IDLE;
+        }    
+        break;
+    }
+    /////////////////////
+    case DCACHE_MISS_WAIT:
+    {
+        m_cost_data_miss_frz++; 
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_miss_req )
+	{
+            if ( r_vci_rsp_data_error ) 
+            {
+                r_dcache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            } 
+
+            if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_tlb_rsp = false;
+		break;
+            }	
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+		break;	    
+	    }
+	    // Miss read response and no tlb invalidation
+	    r_dcache_fsm = DCACHE_MISS_UPDT;
+	}	
+        break;
+    }
+    /////////////////////
+    case DCACHE_MISS_UPDT:
+    {
+        m_cost_data_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        if ( r_dcache_inval_tlb_rsp ) // tlb invalidation
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        // Using tlb entry is in the invalidated cache line  
+        if ( r_dcache_inval_rsp )
+        {
+            r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if (!r_dcache_cleanup_req ) // Miss update and no invalidation
+        {
+            paddr_t  victim_index = 0;
+            size_t way = 0;
+            size_t set = 0;
+
+	    m_cpt_dcache_data_write++;
+            m_cpt_dcache_dir_write++;
+
+            bool cleanup_req = r_dcache.find(r_dcache_paddr_save.read(), r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+
+	    if ( cleanup_req )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+	    r_dcache.update(r_dcache_paddr_save.read(), way, set, r_dcache_miss_buf);
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+	break;
+    }
+    //////////////////////
+    case DCACHE_UNC_WAIT:
+    {
+        m_cost_unc_read_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_unc_req )
+	{
+            if ( r_vci_rsp_data_error ) 
+            {
+                r_dcache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		//if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            }
+
+            if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_tlb_rsp = false;
+		break;
+            }
+/*
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+
+		if ((dreq.type == iss_t::DATA_LL) || (dreq.type == iss_t::DATA_SC))
+		{
+        	    r_dcache_buf_unc_valid = false;
+		    r_dcache_llsc_reserved = false;
+		}
+		break;	    
+	    }
+*/  
+            if(dreq.type == iss_t::DATA_SC) 
+	    {
+                // Simulate an invalidate request
+                r_dcache.inval(r_dcache_paddr_save);
+            }		
+            r_dcache_buf_unc_valid = true;
+	    r_dcache_fsm = DCACHE_IDLE;
+	}	
+        break;
+    }
+    ///////////////////////
+    case DCACHE_WRITE_UPDT:
+    {
+        m_cost_write_frz++;
+        size_t way = 0;
+        size_t set = 0;
+	bool write_hit = false;
+        data_t mask = vci_param::be2mask(r_dcache_be_save.read());
+        data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
+        write_hit = r_dcache.write(r_dcache_paddr_save, wdata, &way, &set);
+        assert(write_hit && "Write on miss ignores data");
+        
+        if (r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[m_dcache_sets*way+set])
+        {
+	    // ins tlb invalidate verification    
+            r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+            r_dcache_itlb_inval_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
+            r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+            // data tlb invalidate verification
+            r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+            r_dcache_dtlb_inval_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
+            r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+            r_dcache_cleanup_req = true; 
+            r_dcache_cleanup_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
+	    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+            r_dcache_fsm_save = r_dcache_fsm;
+            break;
+	}
+
+        if ( !r_dcache_dirty_save && (r_mmu_mode.read() & DATA_TLB_MASK) )   
+        {
+            if ( dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save) )	// 2M page size, one level page table 
+            {
+                r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                //write_hit = r_dcache.write((paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2), 
+                //                     (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
+                //assert(write_hit && "Write on miss ignores data");
+                r_dcache_tlb_ll_dirty_req = true;
+                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                m_cpt_data_tlb_write_dirty++;
+            }
+            else
+            {   
+                if (r_dcache_hit_p_save) 
+                {
+                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                    //write_hit = r_dcache.write(((paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3)), 
+                    //                 (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
+                    //assert(write_hit && "Write on miss ignores data");
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {
+                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                    r_dcache_tlb_ptba_read = true;
+                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                }
+            }
+        }
+        else
+        {
+            r_dcache_fsm = DCACHE_WRITE_REQ;
+            drsp.valid = true;
+            drsp.rdata = 0;
+        }
+        break;
+    }
+    ////////////////////////
+    case DCACHE_WRITE_DIRTY:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            r_dcache_inval_tlb_rsp = false;
+	    break;
+        }
+
+	if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	{
+            r_dcache_fsm = DCACHE_IDLE; 
+            r_dcache_inval_rsp = false;
+	    break;	    
+	}
+
+        r_dcache.write(r_dcache_tlb_paddr, r_dcache_pte_update);
+        dcache_tlb.setdirty(r_dcache_tlb_way_save, r_dcache_tlb_set_save);
+        r_dcache_fsm = DCACHE_WRITE_REQ;
+        drsp.valid = true;
+        drsp.rdata = 0;
+        break;
+    }
+    /////////////////
+    case DCACHE_ERROR:
+    {
+        r_vci_rsp_data_error = false;
+        drsp.valid = true;
+        drsp.error = true;
+        drsp.rdata = 0;
+        r_dcache_fsm = DCACHE_IDLE;
+        break;
+    }   
+    ////////////////////// 
+    case DCACHE_ITLB_READ:
+    {
+        m_cost_data_waste_wait_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+    	if ( !r_dcache_itlb_read_req ) // vci response ok
+        {  
+            if ( r_vci_rsp_data_error )
+            {
+                r_dcache_rsp_itlb_error = true;	
+                r_itlb_read_dcache_req = false;
+                r_vci_rsp_data_error = false;
+                r_dcache_fsm = DCACHE_IDLE;
+
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            }
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+		break;	    
+	    }
+            r_dcache_fsm = DCACHE_ITLB_UPDT;
+        }
+	break;    	
+    }
+    //////////////////////
+    case DCACHE_ITLB_UPDT:
+    {
+        m_cost_data_waste_wait_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        // Using tlb entry is in the invalidated cache line  
+        if ( r_dcache_inval_rsp )
+        {
+            r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if ( !r_dcache_cleanup_req )
+        {
+            data_t rsp_itlb_miss = 0;
+	    data_t rsp_itlb_ppn = 0;
+
+            paddr_t  victim_index = 0;
+            size_t way = 0;
+            size_t set = 0;
+            
+            bool cleanup = r_dcache.find(r_icache_paddr_save, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+
+	    if ( cleanup )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+            r_dcache.update(r_icache_paddr_save, way, set, r_dcache_miss_buf);
+
+            r_dcache.setinbit(r_icache_paddr_save, r_dcache_in_itlb, true);
+            bool itlb_hit_dcache = r_dcache.read(r_icache_paddr_save, &rsp_itlb_miss);	
+ 
+	    if ( (r_icache_fsm == ICACHE_TLB2_READ) && itlb_hit_dcache )
+	    {	
+            	bool itlb_hit_ppn = r_dcache.read(r_icache_paddr_save.read()+4, &rsp_itlb_ppn);
+		assert(itlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+	    }
+
+            r_dcache_rsp_itlb_miss = rsp_itlb_miss;
+            r_dcache_rsp_itlb_ppn = rsp_itlb_ppn;
+            r_dcache_rsp_itlb_error = false;	
+            r_itlb_read_dcache_req = false;
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        break;
+    }
+    //////////////////////////
+    case DCACHE_ITLB_LL_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_itlb_ll_acc_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                r_dcache_rsp_itlb_error = true;  
+                r_vci_rsp_data_error = false;
+                r_itlb_acc_dcache_req = false;
+		r_dcache_fsm = DCACHE_IDLE;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+            }
+	    else
+	    {
+	        if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+                    r_dcache_rsp_itlb_error = true;  
+                    r_itlb_acc_dcache_req = false;
+		    r_dcache_fsm = DCACHE_IDLE;	
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	        }
+       		else if ( r_dcache_inval_rsp )
+       		{
+       		    r_dcache_inval_rsp = false;
+       		    r_dcache_fsm = DCACHE_IDLE;
+       		    m_cost_data_tlb_miss_frz++;
+       		}
+		else
+		{
+		    r_dcache_itlb_sc_acc_req = true;
+		    r_icache_pte_update = r_dcache_miss_buf[0] | r_icache_pte_update.read();	
+                    r_dcache_fsm = DCACHE_ITLB_SC_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    //////////////////////////
+    case DCACHE_ITLB_SC_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+	
+        if ( !r_dcache_itlb_sc_acc_req ) 
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+	        r_dcache_rsp_itlb_error = true;  
+	        r_vci_rsp_data_error = false;
+	        r_itlb_acc_dcache_req = false;
+	        r_dcache_fsm = DCACHE_IDLE;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;		
+	    }
+	    else
+	    {
+	        if ( r_dcache_inval_rsp )
+	        {
+	            r_dcache_inval_rsp = false;
+	            r_dcache_fsm = DCACHE_IDLE;
+	            m_cost_data_tlb_miss_frz++;
+	        }
+	        else if ( r_dcache_itlb_ll_acc_req )
+	        {
+	            r_dcache_fsm = DCACHE_ITLB_LL_WAIT; 
+	        }
+	        else 
+	        {
+	            r_itlb_acc_dcache_req = false;
+	            r_dcache_fsm = DCACHE_IDLE; 
+	        }
+	    }
+	}
+	break;
+    }
+    /////////////////////
+    case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        m_cpt_dcache_dir_read += m_dcache_ways;
+        m_cpt_dcache_data_read += m_dcache_ways;
+
+        data_t dcache_rdata = 0;
+        size_t way = 0;
+        size_t set = 0;
+
+        bool dcache_hit = r_dcache.read(r_tgt_addr.read(), &dcache_rdata, &way, &set);
+
+        if ( dcache_hit )
+        {
+            if ( r_dcache_in_dtlb[m_dcache_sets*way+set] || r_dcache_in_itlb[m_dcache_sets*way+set] )
+	    {
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = r_tgt_addr.read() >> (uint32_log2(m_dcache_words)+2);
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = r_tgt_addr.read() >> (uint32_log2(m_dcache_words)+2);
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+		
+		r_dcache_cc_check = true;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+		break;
+	    }
+
+            if(( /*( r_dcache_fsm_save == DCACHE_UNC_WAIT ) ||*/
+	         ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) && 
+               ( (r_dcache_paddr_save.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1)))) 
+            {
+	        r_dcache_inval_rsp = true;
+            } 
+
+            if(( ( r_dcache_fsm_save == DCACHE_TLB1_READ )      || ( r_dcache_fsm_save == DCACHE_TLB2_READ )      ||
+		 ( r_dcache_fsm_save == DCACHE_TLB1_READ_UPDT ) || ( r_dcache_fsm_save == DCACHE_TLB2_READ_UPDT ) ||
+                 ( r_dcache_fsm_save == DCACHE_TLB1_UPDT )      || ( r_dcache_fsm_save == DCACHE_TLB2_UPDT )	  ||
+		 ( r_dcache_fsm_save == DCACHE_TLB1_LL_WAIT )   || ( r_dcache_fsm_save == DCACHE_TLB2_LL_WAIT )   ||
+		 ( r_dcache_fsm_save == DCACHE_TLB1_SC_WAIT )   || ( r_dcache_fsm_save == DCACHE_TLB2_SC_WAIT )   ||
+		 ( r_dcache_fsm_save == DCACHE_LL_DIRTY_WAIT )  || ( r_dcache_fsm_save == DCACHE_SC_DIRTY_WAIT )  ||
+		 ( r_dcache_fsm_save == DCACHE_WRITE_DIRTY ) ) && 
+               ( (r_dcache_tlb_paddr.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1))) ) 
+            {
+                r_dcache_inval_rsp = true;
+            }
+
+            if(( ( r_dcache_fsm_save == DCACHE_ITLB_READ ) || ( r_dcache_fsm_save == DCACHE_ITLB_UPDT ) ||
+                 ( r_dcache_fsm_save == DCACHE_ITLB_LL_WAIT ) || ( r_dcache_fsm_save == DCACHE_ITLB_SC_WAIT ) ) && 
+               ( (r_icache_paddr_save.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1))) ) 
+            {
+                r_dcache_inval_rsp = true;
+            }
+
+            if ( r_tgt_update ) // update 
+            {
+                r_dcache_fsm = DCACHE_CC_UPDT;
+            } 
+            else                // invalidate 
+            {
+                r_dcache_fsm = DCACHE_CC_INVAL;
+            }
+        }
+        else                    // nothing
+        {
+            r_dcache_fsm = DCACHE_CC_NOP;
+        }
+        break;
+    }
+    ///////////////////
+    case DCACHE_CC_UPDT:    // update directory and data cache        
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        m_cpt_dcache_dir_write++;
+        m_cpt_dcache_data_write++;
+        data_t* buf = r_tgt_buf;
+        for( size_t i = 0; i < m_dcache_words; i++ )
+        {
+            if( r_tgt_val[i] ) r_dcache.write( r_tgt_addr.read() + i*4, buf[i] );
+        }
+           
+        r_tgt_dcache_req = false;
+        r_dcache_fsm = r_dcache_fsm_save;
+        break;
+    }
+    /////////////////////
+    case DCACHE_CC_INVAL:   // invalidate a cache line
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        r_tgt_dcache_rsp = r_dcache.inval(r_tgt_addr.read());
+        r_tgt_dcache_req = false;
+        r_dcache_fsm = r_dcache_fsm_save;
+        break;
+    }
+    ///////////////////
+    case DCACHE_CC_NOP:     // no external hit
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        r_tgt_dcache_req = false;
+        r_dcache_fsm = r_dcache_fsm_save;
+        break;
+    }   
+    /////////////////////////
+    case DCACHE_TLB_CC_INVAL:
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+	if ( r_dcache_itlb_inval_req || r_dcache_dtlb_inval_req ) break;
+
+        if( (( r_dcache_fsm_save == DCACHE_TLB1_READ )        || ( r_dcache_fsm_save == DCACHE_TLB2_READ )        ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_READ_UPDT )   || ( r_dcache_fsm_save == DCACHE_TLB2_READ_UPDT )   ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_LL_WAIT )     || ( r_dcache_fsm_save == DCACHE_TLB2_LL_WAIT )     ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_SC_WAIT )     || ( r_dcache_fsm_save == DCACHE_TLB2_SC_WAIT )     ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_UPDT )        || ( r_dcache_fsm_save == DCACHE_TLB2_UPDT )        ||
+             ( r_dcache_fsm_save == DCACHE_DTLB1_READ_CACHE ) || ( r_dcache_fsm_save == DCACHE_DTLB2_READ_CACHE ) ||
+             ( r_dcache_fsm_save == DCACHE_LL_DIRTY_WAIT )    || ( r_dcache_fsm_save == DCACHE_SC_DIRTY_WAIT )    ||
+	     ( r_dcache_fsm_save == DCACHE_WRITE_DIRTY )) && 
+            (((r_dcache_tlb_paddr.read() & ~((m_dcache_words<<2)-1)) >> (uint32_log2(m_dcache_words) + 2)) == r_dcache_dtlb_inval_line.read()) ) 
+        {
+            r_dcache_inval_tlb_rsp = true;
+        } 
+
+        if (((r_dcache_fsm_save == DCACHE_BIS)||(r_dcache_fsm_save == DCACHE_MISS_WAIT) ||
+             (r_dcache_fsm_save == DCACHE_UNC_WAIT)||(r_dcache_fsm_save == DCACHE_MISS_UPDT)) && 
+             (r_dcache_tlb_nline == r_dcache_dtlb_inval_line))
+        {
+            r_dcache_inval_tlb_rsp = true;
+        }
+
+	if ( !r_dcache_cc_check )
+	{
+            r_dcache_fsm = r_dcache_fsm_save;
+	}
+	else
+	{
+            r_dcache_fsm = DCACHE_CC_CHECK;
+	    r_dcache_cc_check = false;
+	}
+        break;
+    }
+    /////////////////////////
+    case DCACHE_ITLB_CLEANUP:
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        r_dcache.setinbit(((paddr_t)r_dcache_itlb_cleanup_line.read()*m_dcache_words*2), r_dcache_in_itlb, false);
+        r_dcache_itlb_cleanup_req = false;
+        r_dcache_fsm = DCACHE_IDLE;
+        break;
+    }
+    } // end switch r_dcache_fsm
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout << name() << " Data Response: " << drsp << std::endl;
+#endif
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //      INVAL DTLB CHECK FSM 
+    ////////////////////////////////////////////////////////////////////////////////////////
+    switch(r_inval_dtlb_fsm) {
+    /////////////////////
+    case INVAL_DTLB_IDLE:
+    {
+        if ( r_dcache_dtlb_inval_req ) 
+        {
+            r_ccinval_dtlb_way = 0;
+            r_ccinval_dtlb_set = 0;
+            r_inval_dtlb_fsm = INVAL_DTLB_CHECK;    
+            m_cost_data_tlb_inval_frz++;
+        }   
+        break;
+    }
+    ////////////////////////////
+    case INVAL_DTLB_CHECK:
+    {
+        m_cost_data_tlb_inval_frz++;
+
+        size_t way = r_ccinval_dtlb_way; 
+        size_t set = r_ccinval_dtlb_set;
+        bool end = false;        
+        bool tlb_hit = dcache_tlb.cccheck(r_dcache_dtlb_inval_line.read(), way, set, &way, &set, &end); 
+    
+        if ( tlb_hit )
+        {
+            r_ccinval_dtlb_way = way; 
+            r_ccinval_dtlb_set = set;
+            r_dtlb_cc_check_end = end;
+            r_inval_dtlb_fsm = INVAL_DTLB_INVAL;
+            m_cpt_data_tlb_inval++;    
+        }        
+        else
+        {
+            r_inval_dtlb_fsm = INVAL_DTLB_CLEAR;    
+        }
+        break;
+    }
+    /////////////////////////
+    case INVAL_DTLB_INVAL:
+    {
+        m_cost_data_tlb_inval_frz++;
+
+        dcache_tlb.ccinval(r_ccinval_dtlb_way, r_ccinval_dtlb_set);
+
+        if ( !r_dtlb_cc_check_end )
+        {
+            r_inval_dtlb_fsm = INVAL_DTLB_CHECK; 
+        }
+        else
+        {
+            r_inval_dtlb_fsm = INVAL_DTLB_CLEAR;    
+        }
+        break;
+    }
+    ////////////////////
+    case INVAL_DTLB_CLEAR:
+    {
+        r_dcache_dtlb_inval_req = false;
+        r_dtlb_cc_check_end = false;
+        r_ccinval_dtlb_way = 0; 
+        r_ccinval_dtlb_set = 0; 
+        r_inval_dtlb_fsm = INVAL_DTLB_IDLE;   
+        m_cpt_data_tlb_inval++;    
+        break;
+    }
+    } // end switch r_inval_itlb_fsm
+
+    /////////// execute one iss cycle /////////////////////////////////
+    {
+    uint32_t it = 0;
+    for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if(p_irq[i].read()) it |= (1<<i);
+    m_iss.executeNCycles(1, irsp, drsp, it);
+    }
+
+    ////////////// number of frozen cycles //////////////////////////
+    if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) )
+    {
+        m_cpt_frz_cycles++;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    //     VCI_CMD FSM 
+    //
+    // This FSM handles requests from both the DCACHE controler
+    // (request registers) and the ICACHE controler (request registers).
+    // There is 10 VCI transaction types :
+    // - INS_TLB_READ
+    // - INS_TLB_WRITE
+    // - INS_MISS
+    // - INS_UNC_MISS
+    // - DATA_TLB_READ
+    // - DATA_TLB_WRITE
+    // - DATA_TLB_DIRTY
+    // - DATA_MISS
+    // - DATA_UNC 
+    // - DATA_WRITE
+    // The ICACHE requests have the highest priority.
+    // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM and RSP_FSM
+    // exit simultaneously the IDLE state.
+    //////////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_cmd_fsm) {
+    
+    case CMD_IDLE:
+        if (r_vci_rsp_fsm != RSP_IDLE)
+            break;
+
+        r_vci_cmd_cpt = 0;
+
+        if (r_dcache_itlb_read_req)           
+        {            
+            r_vci_cmd_fsm = CMD_ITLB_READ;
+            m_cpt_itlbmiss_transaction++; 
+        } 
+	else if (r_dcache_itlb_ll_acc_req)
+	{
+	    r_vci_cmd_fsm = CMD_ITLB_ACC_LL;
+            m_cpt_itlb_write_transaction++; 
+	}
+	else if (r_dcache_itlb_sc_acc_req)
+	{
+	    r_vci_cmd_fsm = CMD_ITLB_ACC_SC;
+            m_cpt_itlb_write_transaction++; 
+	}
+        else if (r_icache_miss_req) 
+        {    
+            r_vci_cmd_fsm = CMD_INS_MISS;
+            m_cpt_imiss_transaction++; 
+        }
+        else if (r_icache_unc_req) 
+        {    
+            r_vci_cmd_fsm = CMD_INS_UNC;
+            m_cpt_imiss_transaction++; 
+        }  
+        else if (r_dcache_tlb_read_req) 
+        {            
+            r_vci_cmd_fsm = CMD_DTLB_READ;
+            m_cpt_dtlbmiss_transaction++; 
+        } 
+        else if (r_dcache_tlb_ll_acc_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_ACC_LL;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_tlb_sc_acc_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_ACC_SC;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_tlb_ll_dirty_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_DIRTY_LL;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_tlb_sc_dirty_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_DIRTY_SC;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_write_req)
+        {
+            r_vci_cmd_fsm = CMD_DATA_WRITE;
+            r_vci_cmd_cpt = r_wbuf.getMin();
+            r_vci_cmd_min = r_wbuf.getMin();
+            r_vci_cmd_max = r_wbuf.getMax(); 
+            m_cpt_write_transaction++; 
+            m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1);
+        }
+        else if (r_dcache_miss_req)  
+        {
+            r_vci_cmd_fsm = CMD_DATA_MISS;
+            m_cpt_dmiss_transaction++; 
+        }
+        else if (r_dcache_unc_req)  
+        {
+            r_vci_cmd_fsm = CMD_DATA_UNC;
+            m_cpt_unc_transaction++; 
+        }
+        else if (r_icache_cleanup_req)
+        {
+            r_vci_cmd_fsm = CMD_INS_CLEANUP;
+        }
+        else if (r_dcache_cleanup_req)
+        {
+            r_vci_cmd_fsm = CMD_DATA_CLEANUP;
+        }
+        break;
+
+    case CMD_DATA_WRITE:
+        if ( p_vci_ini.cmdack.read() ) 
+        {
+            r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
+            if (r_vci_cmd_cpt == r_vci_cmd_max) 
+            {
+                r_vci_cmd_fsm = CMD_IDLE;
+                r_wbuf.reset();
+            }
+        }
+        break;
+
+    default:
+        if ( p_vci_ini.cmdack.read() )
+        {  
+            r_vci_cmd_fsm = CMD_IDLE;
+        }
+        break;
+
+    } // end  switch r_vci_cmd_fsm
+
+    //////////////////////////////////////////////////////////////////////////
+    //      VCI_RSP FSM 
+    //
+    // This FSM is synchronized with the VCI_CMD FSM, as both FSMs exit the
+    // IDLE state simultaneously.
+    //////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_rsp_fsm) {
+
+    case RSP_IDLE:
+        assert( ! p_vci_ini.rspval.read() && "Unexpected response" );
+
+        if (r_vci_cmd_fsm != CMD_IDLE)
+            break;
+
+        r_vci_rsp_cpt = 0;
+        if (r_dcache_itlb_read_req)          // ITLB miss response
+        {            
+            r_vci_rsp_fsm = RSP_ITLB_READ;
+        } 
+        else if (r_dcache_itlb_ll_acc_req)   // ITLB linked load response
+        {   
+            r_vci_rsp_fsm = RSP_ITLB_ACC_LL;
+        } 
+        else if (r_dcache_itlb_sc_acc_req)   // ITLB store conditional response
+        {   
+            r_vci_rsp_fsm = RSP_ITLB_ACC_SC;
+        } 
+        else if (r_icache_miss_req)          // ICACHE cached miss response
+        {   
+            r_vci_rsp_fsm = RSP_INS_MISS;
+        }
+        else if (r_icache_unc_req)           // ICACHE uncached miss response
+        {   
+            r_vci_rsp_fsm = RSP_INS_UNC;
+        }  
+        else if (r_dcache_tlb_read_req)      // ITLB miss response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_READ; 
+        }
+        else if (r_dcache_tlb_ll_acc_req)    // DTLB access bits linked load response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_ACC_LL; 
+        }
+        else if (r_dcache_tlb_sc_acc_req)    // DTLB access bits store conditional response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_ACC_SC; 
+        }
+        else if (r_dcache_tlb_ll_dirty_req)  // DTLB dirty bit linked load response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_DIRTY_LL; 
+        }
+        else if (r_dcache_tlb_sc_dirty_req)  // DTLB dirty bit store conditional response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_DIRTY_SC; 
+        }
+        else if (r_dcache_write_req)         // DCACHE write response
+        {
+            r_vci_rsp_fsm = RSP_DATA_WRITE;
+        }
+        else if (r_dcache_miss_req)          // DCACHE read response
+        {
+            r_vci_rsp_fsm = RSP_DATA_MISS;
+        }
+        else if (r_dcache_unc_req)           // DCACHE uncached read response
+        {
+            r_vci_rsp_fsm = RSP_DATA_UNC;
+        }
+        else if (r_icache_cleanup_req)	     // ICACHE cleanup response 
+        {
+            r_vci_rsp_fsm = RSP_INS_CLEANUP;
+        }
+        else if (r_dcache_cleanup_req)	     // DCACHE cleanup response
+        {
+            r_vci_rsp_fsm = RSP_DATA_CLEANUP;
+        }
+        break;
+
+    case RSP_ITLB_READ:
+        m_cost_itlbmiss_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini.rdata.read();
+        if ( p_vci_ini.reop.read() ) 
+        {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                    "illegal VCI response packet for data read miss");
+            r_dcache_itlb_read_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        } 
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_data_error = true;
+        }
+        break;
+
+    case RSP_ITLB_ACC_LL:
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for ll tlb");
+
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else
+	{
+	    r_dcache_miss_buf[0] = (data_t)p_vci_ini.rdata.read();
+	}
+        r_dcache_itlb_ll_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_ITLB_ACC_SC:
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for sc tlb");
+
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else if ( p_vci_ini.rdata.read() == 1 ) // store conditional is not successful
+	{
+	    r_dcache_itlb_ll_acc_req = true;
+	}
+        r_dcache_itlb_sc_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_INS_MISS:
+        m_cost_imiss_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert( (r_vci_rsp_cpt < m_icache_words) && 
+               "The VCI response packet for instruction miss is too long");
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini.rdata.read();
+
+        if ( p_vci_ini.reop.read() ) 
+        {
+            assert( (r_vci_rsp_cpt == m_icache_words - 1) &&
+                       "The VCI response packet for instruction miss is too short");
+            r_icache_miss_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+                
+        } 
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_ins_error = true;
+        }
+        break;
+
+    case RSP_INS_UNC:
+        m_cost_imiss_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for uncached instruction");
+
+        r_icache_miss_buf[0] = (data_t)p_vci_ini.rdata.read();
+        r_icache_buf_unc_valid = true;
+        r_icache_unc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_ins_error = true;
+        }
+        break;
+
+    case RSP_DTLB_READ:
+        m_cost_dtlbmiss_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini.rdata.read();
+        if ( p_vci_ini.reop.read() ) 
+        {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                    "illegal VCI response packet for data read miss");
+            r_dcache_tlb_read_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        } 
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_data_error = true;
+        }
+        break;
+
+    case RSP_DTLB_ACC_LL:
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for ll tlb");
+
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else
+	{
+	    r_dcache_miss_buf[0] = (data_t)p_vci_ini.rdata.read();
+	}
+        r_dcache_tlb_ll_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DTLB_ACC_SC:
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for sc tlb");
+
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else if ( p_vci_ini.rdata.read() == 1 ) // store conditional is not successful
+	{
+	    r_dcache_tlb_ll_acc_req = true;
+	}
+        r_dcache_tlb_sc_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DTLB_DIRTY_LL:
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for ll tlb");
+
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else
+	{
+	    r_dcache_miss_buf[0] = (data_t)p_vci_ini.rdata.read();
+	}
+        r_dcache_tlb_ll_dirty_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DTLB_DIRTY_SC:
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for sc tlb");
+
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else if ( p_vci_ini.rdata.read() == 1 ) // store conditional is not successful
+	{
+	    r_dcache_tlb_ll_dirty_req = true;
+	}
+        r_dcache_tlb_sc_dirty_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DATA_UNC:
+        m_cost_unc_transaction++;
+        if ( ! p_vci_ini.rspval.read() ) 
+            break;
+
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for data read uncached");
+
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+        else
+        {
+            r_dcache_miss_buf[0] = (data_t)p_vci_ini.rdata.read();
+            r_dcache_buf_unc_valid = true;
+        }
+        r_dcache_unc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+        break;
+
+    case RSP_DATA_MISS:
+        m_cost_dmiss_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini.rdata.read();
+        if ( p_vci_ini.reop.read() ) 
+        {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                    "illegal VCI response packet for data read miss");
+            r_dcache_miss_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        } 
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_data_error = true;
+        }
+        break;
+
+    case RSP_DATA_WRITE:
+        m_cost_write_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+
+        if ( p_vci_ini.reop.read() ) 
+        {
+            r_vci_rsp_fsm = RSP_IDLE;
+            r_dcache_write_req = false;
+        }
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            m_iss.setWriteBerr();
+        }
+        break;
+
+    case RSP_INS_CLEANUP:
+    case RSP_DATA_CLEANUP:
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+        assert( p_vci_ini.reop.read() &&
+                "illegal VCI response packet for icache cleanup");
+        assert( (p_vci_ini.rerror.read() == vci_param::ERR_NORMAL) &&
+                "error in response packet for icache cleanup");
+
+        if ( r_vci_rsp_fsm == RSP_INS_CLEANUP ) 
+        {
+            r_icache_cleanup_req = false;
+        }
+        else
+        {                                    
+            r_dcache_cleanup_req = false;
+        }
+        r_vci_rsp_fsm = RSP_IDLE;
+        break;
+
+    } // end switch r_vci_rsp_fsm
+} // end transition()
+
+///////////////////////
+tmpl(void)::genMoore()
+///////////////////////
+{
+    // VCI initiator response
+
+    p_vci_ini.rspack = true;
+
+    // VCI initiator command
+
+    p_vci_ini.pktid  = 0;
+    p_vci_ini.srcid  = m_srcid;
+    p_vci_ini.cons   = false;
+    p_vci_ini.wrap   = false;
+    p_vci_ini.contig = true;
+    p_vci_ini.clen   = 0;
+    p_vci_ini.cfixed = false;
+
+    switch (r_vci_cmd_fsm) {
+
+    case CMD_IDLE:
+        p_vci_ini.cmdval  = false;
+        p_vci_ini.address = 0;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0;
+        p_vci_ini.trdid   = 0;
+        p_vci_ini.plen    = 0;
+        p_vci_ini.cmd     = vci_param::CMD_NOP;
+        p_vci_ini.eop     = false;
+        break;
+
+    case CMD_ITLB_READ:     
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_icache_paddr_save.read() & m_dcache_yzmask;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 1; // via data cache cached read
+        p_vci_ini.plen    = m_dcache_words << 2;
+        p_vci_ini.cmd     = vci_param::CMD_READ;
+        p_vci_ini.eop     = true;
+        break;
+
+    case CMD_ITLB_ACC_LL:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_icache_paddr_save.read() & ~0x3;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 0; // data cache uncached read
+        p_vci_ini.plen    = 4;
+        p_vci_ini.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini.eop     = true;
+	break;
+
+    case CMD_ITLB_ACC_SC:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_icache_paddr_save.read() & ~0x3;
+        p_vci_ini.wdata   = r_icache_pte_update.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 0; // data cache uncached read
+        p_vci_ini.plen    = 4;
+        p_vci_ini.cmd     = vci_param::CMD_STORE_COND;
+        p_vci_ini.eop     = true;
+	break;	
+
+    case CMD_INS_MISS:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_icache_paddr_save.read() & m_icache_yzmask;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 3; // ins cache cached read
+        p_vci_ini.plen    = m_icache_words << 2;
+        p_vci_ini.cmd     = vci_param::CMD_READ;
+        p_vci_ini.eop     = true;
+        break;
+
+    case CMD_INS_UNC:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_icache_paddr_save.read() & ~0x3;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 2; // ins cache uncached read
+        p_vci_ini.plen    = 4;
+        p_vci_ini.cmd     = vci_param::CMD_READ;
+        p_vci_ini.eop     = true;
+        break;
+
+    case CMD_DTLB_READ:     
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_dcache_tlb_paddr.read() & m_dcache_yzmask;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 1; // via dcache cached read
+        p_vci_ini.plen    = m_dcache_words << 2;
+        p_vci_ini.cmd     = vci_param::CMD_READ;
+        p_vci_ini.eop     = true;
+        break;
+
+    case CMD_DTLB_ACC_LL:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 0; // data cache uncached read
+        p_vci_ini.plen    = 4;
+        p_vci_ini.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini.eop     = true;
+	break;
+
+    case CMD_DTLB_ACC_SC:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini.wdata   = r_dcache_pte_update.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 0; // data cache uncached read
+        p_vci_ini.plen    = 4;
+        p_vci_ini.cmd     = vci_param::CMD_STORE_COND;
+        p_vci_ini.eop     = true;
+	break;	
+
+    case CMD_DTLB_DIRTY_LL:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 0; // data cache uncached read
+        p_vci_ini.plen    = 4;
+        p_vci_ini.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini.eop     = true;
+	break;
+
+    case CMD_DTLB_DIRTY_SC:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini.wdata   = r_dcache_pte_update.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 0; // data cache uncached read
+        p_vci_ini.plen    = 4;
+        p_vci_ini.cmd     = vci_param::CMD_STORE_COND;
+        p_vci_ini.eop     = true;
+	break;	
+
+    case CMD_DATA_UNC:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_dcache_paddr_save.read() & ~0x3;
+        p_vci_ini.trdid   = 0; // data cache uncached read
+        p_vci_ini.plen    = 4;
+        p_vci_ini.eop     = true;
+        switch(r_dcache_type_save) {
+        case iss_t::DATA_READ:
+            p_vci_ini.wdata = 0;
+            p_vci_ini.be    = r_dcache_be_save.read();
+            p_vci_ini.cmd   = vci_param::CMD_READ;
+            break;
+        case iss_t::DATA_LL:
+            p_vci_ini.wdata = 0;
+            p_vci_ini.be    = 0xF;
+            p_vci_ini.cmd   = vci_param::CMD_LOCKED_READ;
+            break;
+        case iss_t::DATA_SC:
+            p_vci_ini.wdata = r_dcache_wdata_save.read();
+            p_vci_ini.be    = 0xF;
+            p_vci_ini.cmd   = vci_param::CMD_STORE_COND;
+            break;
+        default:
+            assert("this should not happen");
+        }
+        break;
+
+    case CMD_DATA_WRITE:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_wbuf.getAddress(r_vci_cmd_cpt);
+        p_vci_ini.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
+        p_vci_ini.be      = r_wbuf.getBe(r_vci_cmd_cpt);
+        p_vci_ini.trdid   = 0; // data cache write
+        p_vci_ini.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
+        p_vci_ini.cmd     = vci_param::CMD_WRITE;
+        p_vci_ini.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
+        break;
+
+    case CMD_DATA_MISS:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_dcache_paddr_save.read() & m_dcache_yzmask;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = 1; // data cache cached read
+        p_vci_ini.plen    = m_dcache_words << 2;
+        p_vci_ini.cmd     = vci_param::CMD_READ;
+        p_vci_ini.eop     = true;
+        break;
+
+    case CMD_INS_CLEANUP:
+    case CMD_DATA_CLEANUP:
+        p_vci_ini.cmdval = true;
+        if ( r_vci_cmd_fsm == CMD_INS_CLEANUP ) p_vci_ini.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
+        else                                    p_vci_ini.address = r_dcache_cleanup_line.read() * (m_dcache_words<<2);
+        p_vci_ini.wdata  = 0;
+        p_vci_ini.be     = 0;
+        p_vci_ini.trdid  = 1; // cleanup for distinguish from a write
+        p_vci_ini.plen   = 4;
+        p_vci_ini.cmd    = vci_param::CMD_WRITE;
+        p_vci_ini.contig = false;
+        p_vci_ini.eop    = true;
+        break;
+
+    } // end switch r_vci_cmd_fsm
+
+    // VCI_TGT
+    switch ( r_vci_tgt_fsm.read() ) {
+
+    case TGT_IDLE:
+    case TGT_UPDT_WORD:
+    case TGT_UPDT_DATA:
+        p_vci_tgt.cmdack  = true;
+        p_vci_tgt.rspval  = false;
+        break;
+
+    case TGT_RSP_BROADCAST:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
+        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+        p_vci_tgt.rpktid  = r_tgt_pktid.read();
+        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = true;
+        break;
+
+    case TGT_RSP_DCACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = !r_tgt_dcache_req.read();
+        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+        p_vci_tgt.rpktid  = r_tgt_pktid.read();
+        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = true;
+        break;
+
+    case TGT_REQ_BROADCAST:
+    case TGT_REQ_DCACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = false;
+        break;
+
+    } // end switch TGT_FSM
+
+#ifdef SOCLIB_MODULE_DEBUG 
+   std::cout << name() 
+      	     << "Moore:" << std::hex
+      	     << " p_vci_ini.cmdval: " << p_vci_ini.cmdval
+      	     << " p_vci_ini.address: " << p_vci_ini.address
+      	     << " p_vci_ini.wdata: " << p_vci_ini.wdata
+      	     << " p_vci_ini.cmd: " << p_vci_ini.cmd
+      	     << " p_vci_ini.eop: " << p_vci_ini.eop
+      	     << std::endl;
+#endif
+}
+
+}}
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
+
+
+
+
+
Index: trunk/modules/vci_cc_vcache_wrapper2_ring/caba/metadata/vci_cc_vcache_wrapper2_ring.sd
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper2_ring/caba/metadata/vci_cc_vcache_wrapper2_ring.sd	(revision 2)
+++ trunk/modules/vci_cc_vcache_wrapper2_ring/caba/metadata/vci_cc_vcache_wrapper2_ring.sd	(revision 2)
@@ -0,0 +1,61 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_cc_vcache_wrapper2_ring',
+	classname = 'soclib::caba::VciCcVCacheWrapper2Ring',
+	   tmpl_parameters = [
+	parameter.Module('vci_param', default = 'caba:vci_param'),
+	parameter.Module('iss_t'),
+	],
+	header_files = [
+	'../source/include/vci_cc_vcache_wrapper2_ring.h',
+	],
+	implementation_files = [
+	'../source/src/vci_cc_vcache_wrapper2_ring.cpp',
+	],
+	uses = [
+	Uses('caba:base_module'),
+	Uses('caba:write_buffer'),
+	Uses('caba:generic_tlb', addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', parameter.Reference('addr_size'))),
+	Uses('caba:generic_cache', addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', parameter.Reference('addr_size'))),
+	Uses('common:address_masking_table', data_t = parameter.StringExt('sc_dt::sc_uint<%d> ', parameter.Reference('addr_size'))),
+	Uses('common:iss2'),
+	Uses('common:mapping_table'),
+	],
+	ports = [
+	Port('caba:vci_initiator', 'p_vci_ini_rw'),
+	Port('caba:vci_initiator', 'p_vci_ini_c'),
+	Port('caba:vci_target', 'p_vci_tgt'),
+	Port('caba:bit_in','p_irq', parameter.Constant('n_irq')),
+	Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+	Port('caba:clock_in', 'p_clk', auto = 'clock'),
+	],
+	instance_parameters = [
+	parameter.Int('proc_id'),
+	parameter.Module('mt', 'common:mapping_table', auto='env:mapping_table'),
+	parameter.IntTab('initiator_rw_index'),
+	parameter.IntTab('initiator_c_index'),
+	parameter.IntTab('target_index'),
+    	parameter.Int('itlb_ways'),
+    	parameter.Int('itlb_sets'),
+    	parameter.Int('dtlb_ways'),
+    	parameter.Int('dtlb_sets'),
+    	parameter.Int('icache_ways'),
+    	parameter.Int('icache_sets'),
+    	parameter.Int('icache_words'),
+    	parameter.Int('dcache_ways'),
+    	parameter.Int('dcache_sets'),
+    	parameter.Int('dcache_words'),
+    	parameter.Int('write_buf_size'),
+	],
+	   extensions = [
+	'dsx:get_ident=initiator_index:p_vci_ini_rw',
+	'dsx:cpu=wrapper:iss_t',
+	'dsx:mapping_type=processor:proc_id',
+   ],
+)
+
+
Index: trunk/modules/vci_cc_vcache_wrapper2_ring/caba/source/include/vci_cc_vcache_wrapper2_ring.h
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper2_ring/caba/source/include/vci_cc_vcache_wrapper2_ring.h	(revision 2)
+++ trunk/modules/vci_cc_vcache_wrapper2_ring/caba/source/include/vci_cc_vcache_wrapper2_ring.h	(revision 2)
@@ -0,0 +1,563 @@
+/* -*- c++ -*-
+ * File : vci_cc_vcache_wrapper2_ring.h
+ * Copyright (c) UPMC, Lip6, SoC
+ * Authors : Alain GREINER, Yang GAO
+ *
+ * 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
+ */
+ 
+#ifndef SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER2_RING_H
+#define SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER2_RING_H
+
+#include <inttypes.h>
+#include <systemc>
+#include "caba_base_module.h"
+#include "write_buffer.h"
+#include "generic_cache.h"
+#include "vci_initiator.h"
+#include "vci_target.h"
+#include "mapping_table.h"
+#include "generic_tlb.h"
+#include "static_assert.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+////////////////////////////////////////////
+template<typename vci_param, typename iss_t>
+class VciCcVCacheWrapper2Ring
+////////////////////////////////////////////
+    : public soclib::caba::BaseModule
+{
+    typedef uint32_t vaddr_t;
+    typedef uint32_t data_t;
+    typedef uint32_t tag_t;
+    typedef uint32_t type_t;
+    typedef typename iss_t::DataOperationType data_op_t;
+
+    typedef typename vci_param::addr_t  paddr_t;
+    typedef typename vci_param::be_t    vci_be_t;
+	typedef typename vci_param::srcid_t vci_srcid_t;
+	typedef typename vci_param::trdid_t vci_trdid_t;
+	typedef typename vci_param::pktid_t vci_pktid_t;
+	typedef typename vci_param::plen_t  vci_plen_t;
+
+    enum icache_fsm_state_e {  
+        ICACHE_IDLE,                // 00
+        ICACHE_BIS,                 // 01
+        ICACHE_TLB1_READ,           // 02
+        ICACHE_TLB1_WRITE,          // 03
+        ICACHE_TLB1_UPDT,           // 04
+        ICACHE_TLB2_READ,           // 05
+        ICACHE_TLB2_WRITE,          // 06
+        ICACHE_TLB2_UPDT,           // 07
+        ICACHE_SW_FLUSH,            // 08
+        ICACHE_CACHE_FLUSH,         // 09
+        ICACHE_TLB_INVAL,           // 0a
+        ICACHE_CACHE_INVAL,         // 0b
+        ICACHE_MISS_WAIT,           // 0c
+        ICACHE_UNC_WAIT,            // 0d
+        ICACHE_MISS_UPDT,           // 0e
+        ICACHE_ERROR,               // 0f
+        ICACHE_CC_INVAL,            // 10
+        ICACHE_TLB_CC_INVAL,        // 11
+        ICACHE_TLB_FLUSH,           // 12
+    };
+
+    enum dcache_fsm_state_e {  
+        DCACHE_IDLE,                // 00
+        DCACHE_BIS,                 // 01
+        DCACHE_DTLB1_READ_CACHE,    // 02
+        DCACHE_TLB1_LL_WAIT,        // 03
+        DCACHE_TLB1_SC_WAIT,        // 04
+        DCACHE_TLB1_READ,           // 05
+        DCACHE_TLB1_READ_UPDT,      // 06
+        DCACHE_TLB1_UPDT,           // 07
+        DCACHE_DTLB2_READ_CACHE,    // 08
+        DCACHE_TLB2_LL_WAIT,        // 09
+        DCACHE_TLB2_SC_WAIT,        // 0a
+        DCACHE_TLB2_READ,           // 0b
+        DCACHE_TLB2_READ_UPDT,      // 0c
+        DCACHE_TLB2_UPDT,           // 0d
+        DCACHE_CTXT_SWITCH,         // 0e
+        DCACHE_ICACHE_FLUSH,        // 0f
+        DCACHE_DCACHE_FLUSH,        // 10
+        DCACHE_ITLB_INVAL,          // 11
+        DCACHE_DTLB_INVAL,          // 12
+        DCACHE_ICACHE_INVAL,        // 13
+        DCACHE_DCACHE_INVAL,        // 14
+        DCACHE_DCACHE_SYNC,         // 15
+        DCACHE_LL_DIRTY_WAIT,       // 16
+        DCACHE_SC_DIRTY_WAIT,       // 17
+        DCACHE_WRITE_UPDT,          // 18
+        DCACHE_WRITE_DIRTY,         // 19
+        DCACHE_WRITE_REQ,           // 1a
+        DCACHE_MISS_WAIT,           // 1b
+        DCACHE_MISS_UPDT,           // 1c
+        DCACHE_UNC_WAIT,            // 1d
+        DCACHE_ERROR,               // 1e
+        DCACHE_ITLB_READ,           // 1f
+        DCACHE_ITLB_UPDT,           // 20
+        DCACHE_ITLB_LL_WAIT,        // 21
+        DCACHE_ITLB_SC_WAIT,        // 22
+        DCACHE_CC_CHECK,            // 23
+        DCACHE_CC_INVAL,            // 24
+        DCACHE_CC_UPDT,             // 25
+        DCACHE_CC_NOP,              // 26
+        DCACHE_TLB_CC_INVAL,        // 27
+        DCACHE_ITLB_CLEANUP,        // 28
+    };
+
+    enum cmd_fsm_state_e {      
+        CMD_IDLE,                   // 00
+        CMD_ITLB_READ,              // 01
+        CMD_ITLB_ACC_LL,            // 02
+        CMD_ITLB_ACC_SC,            // 03
+        CMD_INS_MISS,               // 04
+        CMD_INS_UNC,                // 05
+        CMD_DTLB_READ,              // 06
+        CMD_DTLB_ACC_LL,            // 07
+        CMD_DTLB_ACC_SC,            // 08
+        CMD_DTLB_DIRTY_LL,          // 09
+        CMD_DTLB_DIRTY_SC,          // 0a
+        CMD_DATA_UNC,               // 0b
+        CMD_DATA_MISS,              // 0c
+        CMD_DATA_WRITE,             // 0d
+    };
+
+    enum rsp_fsm_state_e {       
+        RSP_IDLE,                   // 00
+        RSP_ITLB_READ,              // 01
+        RSP_ITLB_ACC_LL,            // 02
+        RSP_ITLB_ACC_SC,            // 03
+        RSP_INS_MISS,               // 04
+        RSP_INS_UNC,                // 05
+        RSP_DTLB_READ,              // 06
+        RSP_DTLB_ACC_LL,            // 07
+        RSP_DTLB_ACC_SC,            // 08
+        RSP_DTLB_DIRTY_LL,          // 09
+        RSP_DTLB_DIRTY_SC,          // 0a
+        RSP_DATA_MISS,              // 0b
+        RSP_DATA_UNC,               // 0c
+        RSP_DATA_WRITE,             // 0d
+    };
+
+    enum cmd_cleanup_fsm_state_e {      
+        CMD_CLEANUP_INS_IDLE,       // 00
+        CMD_CLEANUP_DATA_IDLE,      // 00
+        CMD_CLEANUP_INS,            // 01
+        CMD_CLEANUP_DATA,           // 02
+    };
+
+    enum rsp_cleanup_fsm_state_e {       
+        RSP_CLEANUP_INS_IDLE,       // 00
+        RSP_CLEANUP_DATA_IDLE,      // 00
+        RSP_CLEANUP_INS,            // 01
+        RSP_CLEANUP_DATA,           // 02
+    };
+
+    enum tgt_fsm_state_e {  
+        TGT_IDLE,                   // 00
+        TGT_UPDT_WORD,              // 01
+        TGT_UPDT_DATA,              // 02
+        TGT_REQ_BROADCAST,          // 03
+        TGT_REQ_DCACHE,             // 04
+        TGT_RSP_BROADCAST,          // 05
+        TGT_RSP_DCACHE,             // 06
+    };
+
+    enum inval_itlb_fsm_state_e {
+        INVAL_ITLB_IDLE,            // 00
+        INVAL_ITLB_CHECK,           // 01
+        INVAL_ITLB_INVAL,           // 02
+        INVAL_ITLB_CLEAR,           // 03
+    };
+
+    enum inval_dtlb_fsm_state_e {
+        INVAL_DTLB_IDLE,            // 00
+        INVAL_DTLB_CHECK,           // 01
+        INVAL_DTLB_INVAL,           // 02
+        INVAL_DTLB_CLEAR,           // 03
+    };
+
+    // TLB Mode ITLB / DTLB / ICACHE / DCACHE
+    enum {          
+        ALL_DEACTIVE = 0x0000,   // TLBs disactive caches disactive
+        INS_TLB_MASK    = 0x8,
+        DATA_TLB_MASK   = 0x4,
+        INS_CACHE_MASK  = 0x2,
+        DATA_CACHE_MASK = 0x1,
+    };
+
+    // Error Type
+    enum mmu_error_type_e {
+        MMU_NONE                      = 0x0000, // None
+        MMU_WRITE_PT1_UNMAPPED 	      = 0x0001, // Write access of Page fault on Page Table 1          (non fatal error)
+        MMU_WRITE_PT2_UNMAPPED 	      = 0x0002, // Write access of Page fault on Page Table 2          (non fatal error)
+        MMU_WRITE_PRIVILEGE_VIOLATION = 0x0004, // Write access of Protected access in user mode       (user error)
+        MMU_WRITE_ACCES_VIOLATION 	  = 0x0008, // Write access of write access to a non writable page (user error)
+        MMU_WRITE_UNDEFINED_XTN 	  = 0x0020, // Write access of undefined external access address   (user error)
+        MMU_WRITE_PT1_ILLEGAL_ACCESS  = 0x0040, // Write access of Bus Error accessing Table 1         (kernel error)
+        MMU_WRITE_PT2_ILLEGAL_ACCESS  = 0x0080, // Write access of Bus Error accessing Table 2         (kernel error)
+        MMU_WRITE_DATA_ILLEGAL_ACCESS = 0x0100, // Write access of Bus Error in cache access           (kernel error)
+        MMU_READ_PT1_UNMAPPED 	      = 0x1001, // Read access of Page fault on Page Table 1  	       (non fatal error)
+        MMU_READ_PT2_UNMAPPED 	      = 0x1002, // Read access of Page fault on Page Table 2  	       (non fatal error)
+        MMU_READ_PRIVILEGE_VIOLATION  = 0x1004, // Read access of Protected access in user mode 	   (user error)
+        MMU_READ_EXEC_VIOLATION 	  = 0x1010, // Exec access to a non exec page                      (user error)
+        MMU_READ_UNDEFINED_XTN 	      = 0x1020, // Read access of Undefined external access address    (user error)
+        MMU_READ_PT1_ILLEGAL_ACCESS   = 0x1040, // Read access of Bus Error in Table1 access           (kernel error)
+        MMU_READ_PT2_ILLEGAL_ACCESS   = 0x1080, // Read access of Bus Error in Table2 access 	       (kernel error)
+        MMU_READ_DATA_ILLEGAL_ACCESS  = 0x1100, // Read access of Bus Error in cache access 	       (kernel error)
+    };
+
+public:
+    sc_in<bool>                             p_clk;
+    sc_in<bool>                             p_resetn;
+    sc_in<bool>                             p_irq[iss_t::n_irq];
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_rw;
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_c;
+    soclib::caba::VciTarget<vci_param>      p_vci_tgt;
+
+private:
+    // STRUCTURAL PARAMETERS
+    soclib::common::AddressDecodingTable<uint32_t, bool>    m_cacheability_table;
+    const soclib::common::Segment                           m_segment;
+    iss_t                                                   m_iss;   
+    const vci_srcid_t                                       m_srcid_rw;
+    const vci_srcid_t                                       m_srcid_c;
+
+    const size_t  m_itlb_ways;
+    const size_t  m_itlb_sets;
+
+    const size_t  m_dtlb_ways;
+    const size_t  m_dtlb_sets;
+
+    const size_t  m_icache_ways;
+    const size_t  m_icache_sets;
+    const size_t  m_icache_yzmask;
+    const size_t  m_icache_words;
+
+    const size_t  m_dcache_ways;
+    const size_t  m_dcache_sets;
+    const size_t  m_dcache_yzmask;
+    const size_t  m_dcache_words;
+
+    const size_t  m_write_buf_size;  
+    const size_t  m_paddr_nbits;  
+
+    // instruction and data vcache tlb instances 
+    soclib::caba::GenericCcTlb<paddr_t>    icache_tlb;
+    soclib::caba::GenericCcTlb<paddr_t>    dcache_tlb;
+
+    sc_signal<vaddr_t>      r_mmu_ptpr;             // page table pointer register
+    sc_signal<int>          r_mmu_mode;             // tlb mode register
+
+    // DCACHE FSM REGISTERS
+    sc_signal<int>          r_dcache_fsm;               // state register
+    sc_signal<paddr_t>      r_dcache_paddr_save;        // physical address
+    sc_signal<data_t>       r_dcache_wdata_save;        // write data
+    sc_signal<data_t>       r_dcache_rdata_save;        // read data
+    sc_signal<type_t>       r_dcache_type_save;         // access type
+    sc_signal<vci_be_t>     r_dcache_be_save;           // byte enable
+    sc_signal<bool>         r_dcache_cached_save;       // used by the write buffer
+    sc_signal<paddr_t>      r_dcache_tlb_paddr;         // physical address of tlb miss
+    sc_signal<bool>         r_dcache_dirty_save;        // used for TLB dirty bit update
+    sc_signal<size_t>       r_dcache_tlb_set_save;      // used for TLB dirty bit update
+    sc_signal<size_t>       r_dcache_tlb_way_save;      // used for TLB dirty bit update
+    sc_signal<vaddr_t>      r_dcache_id1_save;          // used by the PT1 bypass
+    sc_signal<paddr_t>      r_dcache_ptba_save;         // used by the PT1 bypass
+    sc_signal<bool>         r_dcache_ptba_ok;           // used by the PT1 bypass
+    sc_signal<data_t>       r_dcache_pte_update;        // used for page table update
+    sc_signal<data_t>       r_dcache_ppn_update;        // used for physical page number update 
+    sc_signal<tag_t>        r_dcache_ppn_save;          // used for speculative cache access
+    sc_signal<tag_t>        r_dcache_vpn_save;          // used for speculative cache access
+    sc_signal<bool>         r_dtlb_translation_valid;   // used for speculative address
+    sc_signal<bool>         r_dcache_buf_unc_valid;     // used for uncached read
+    sc_signal<bool>         r_dcache_hit_p_save;        // used to save hit_p in case BIS
+
+    sc_signal<data_t>       r_dcache_error_type;        // software visible register
+    sc_signal<vaddr_t>      r_dcache_bad_vaddr;         // software visible register 
+
+    sc_signal<bool>         r_dcache_miss_req;          // used for cached read miss
+    sc_signal<bool>         r_dcache_unc_req;           // used for uncached read miss
+    sc_signal<bool>         r_dcache_write_req;         // used for write 
+    sc_signal<bool>         r_dcache_tlb_read_req;      // used for tlb ptba or pte read 
+    sc_signal<bool>         r_dcache_llsc_reserved;     // used for check address reserved
+    sc_signal<paddr_t>      r_dcache_llsc_addr_save;    // used for save llsc address
+ 
+    sc_signal<bool>         r_dcache_tlb_ll_acc_req;    // used for tlb access bit update
+    sc_signal<bool>         r_dcache_tlb_sc_acc_req;    // used for tlb access bit update
+    sc_signal<bool>         r_dcache_tlb_ll_dirty_req;  // used for tlb dirty bit update 
+    sc_signal<bool>         r_dcache_tlb_sc_dirty_req;  // used for tlb dirty bit update 
+    sc_signal<bool>         r_dcache_tlb_ptba_read;     // used for tlb ptba read when write dirty bit 
+    sc_signal<bool>         r_dcache_xtn_req;           // used for xtn write for ICACHE
+
+    bool                    *r_dcache_in_itlb;          // indicates some words of dcache line in ins TLB 
+    bool                    *r_dcache_in_dtlb;          // indicates some words of dcache line in data TLB 
+
+    // coherence registers
+    sc_signal<int>          r_dcache_fsm_save;          // state save register
+    sc_signal<size_t>       r_dcache_way;
+    sc_signal<size_t>       r_dcache_set;
+    sc_signal<bool>         r_dcache_cleanup_req;       // data cleanup request
+    sc_signal<data_t>       r_dcache_cleanup_line;      // data cleanup NLINE
+    sc_signal<bool>         r_dcache_inval_rsp;         // data cache invalidate
+
+    // ICACHE FSM REGISTERS
+    sc_signal<int>          r_icache_fsm;               // state register
+    sc_signal<paddr_t>      r_icache_paddr_save;        // physical address
+    sc_signal<vaddr_t>      r_icache_id1_save;          // used by the PT1 bypass
+    sc_signal<paddr_t>      r_icache_ptba_save;         // used by the PT1 bypass
+    sc_signal<bool>         r_icache_ptba_ok;           // used by the PT1 bypass
+    sc_signal<data_t>       r_icache_pte_update;        // used for page table update
+    sc_signal<tag_t>        r_icache_ppn_save;          // used for speculative cache access
+    sc_signal<tag_t>        r_icache_vpn_save;          // used for speculative cache access
+    sc_signal<bool>         r_itlb_translation_valid;   // used for speculative physical address
+    sc_signal<bool>         r_icache_buf_unc_valid;     // used for uncached read
+
+    sc_signal<data_t>       r_icache_error_type;        // software visible registers
+    sc_signal<vaddr_t>      r_icache_bad_vaddr;         // software visible registers
+
+    sc_signal<bool>         r_icache_miss_req;          // used for cached read miss
+    sc_signal<bool>         r_icache_unc_req;           // used for uncached read miss
+    sc_signal<bool>         r_dcache_itlb_read_req;     // used for tlb ptba or pte read 
+    sc_signal<bool>         r_dcache_itlb_ll_acc_req;   // used for tlb access bit update
+    sc_signal<bool>         r_dcache_itlb_sc_acc_req;   // used for tlb access bit update
+
+    sc_signal<bool>	        r_itlb_read_dcache_req;     // used for instruction tlb miss, request in data cache
+    sc_signal<bool>	        r_itlb_acc_dcache_req;      // used for itlb update entry type bits via dcache
+    sc_signal<bool>	        r_dcache_rsp_itlb_error;    // used for data cache rsp error when itlb miss
+    sc_signal<data_t>	    r_dcache_rsp_itlb_miss;	    // used for dcache rsp data when itlb miss
+    sc_signal<data_t>	    r_dcache_rsp_itlb_ppn;	    // used for dcache rsp ppn when itlb miss
+
+    // coherence registers
+    sc_signal<int>          r_icache_fsm_save;          // state save register
+    sc_signal<size_t>       r_icache_way;
+    sc_signal<size_t>       r_icache_set;
+    sc_signal<bool>         r_icache_cleanup_req;       // ins cleanup request
+    sc_signal<data_t>       r_icache_cleanup_line;      // ins cleanup NLINE
+    sc_signal<bool>         r_icache_inval_rsp;         // ins cache invalidate
+
+    // VCI_CMD FSM REGISTERS
+    sc_signal<int>          r_vci_cmd_fsm;
+    sc_signal<size_t>       r_vci_cmd_min;       
+    sc_signal<size_t>       r_vci_cmd_max;       
+    sc_signal<size_t>       r_vci_cmd_cpt;     
+
+    // VCI_RSP FSM REGISTERS
+    sc_signal<int>          r_vci_rsp_fsm;
+    sc_signal<size_t>       r_vci_rsp_cpt;
+    sc_signal<bool>         r_vci_rsp_ins_error;
+    sc_signal<bool>         r_vci_rsp_data_error;
+
+    data_t                  *r_icache_miss_buf;    
+    data_t                  *r_dcache_miss_buf;  
+
+    // VCI CLEANUP FSM REGISTERS
+    sc_signal<int>          r_vci_cmd_cleanup_fsm;
+    sc_signal<int>          r_vci_rsp_cleanup_fsm;
+
+    // VCI_TGT FSM REGISTERS
+    data_t                  *r_tgt_buf;
+    bool                    *r_tgt_val;
+
+    sc_signal<int>          r_vci_tgt_fsm;
+    sc_signal<paddr_t>      r_tgt_addr;
+    sc_signal<size_t>       r_tgt_word;
+    sc_signal<bool>         r_tgt_update;
+    sc_signal<vci_srcid_t>  r_tgt_srcid;
+    sc_signal<vci_pktid_t>  r_tgt_pktid;
+    sc_signal<vci_trdid_t>  r_tgt_trdid;
+    sc_signal<vci_plen_t>   r_tgt_plen;
+    sc_signal<bool>         r_tgt_req;
+    sc_signal<bool>         r_tgt_icache_req;
+    sc_signal<bool>         r_tgt_dcache_req;
+    sc_signal<bool>         r_tgt_icache_rsp;
+    sc_signal<bool>         r_tgt_dcache_rsp;
+
+    // INVAL CHECK FSM
+    sc_signal<int>          r_inval_itlb_fsm;          
+    sc_signal<bool>         r_dcache_itlb_inval_req;
+    sc_signal<paddr_t>      r_dcache_itlb_inval_line;
+    sc_signal<bool>         r_itlb_cc_check_end;
+    sc_signal<size_t>       r_ccinval_itlb_way; 
+    sc_signal<size_t>       r_ccinval_itlb_set; 
+    sc_signal<bool>         r_icache_inval_tlb_rsp;
+    sc_signal<paddr_t>      r_icache_tlb_nline;
+
+    sc_signal<int>          r_inval_dtlb_fsm;          
+    sc_signal<bool>         r_dcache_dtlb_inval_req;
+    sc_signal<paddr_t>      r_dcache_dtlb_inval_line;
+    sc_signal<bool>         r_dtlb_cc_check_end;
+    sc_signal<size_t>       r_ccinval_dtlb_way; 
+    sc_signal<size_t>       r_ccinval_dtlb_set; 
+    sc_signal<bool>         r_dcache_inval_tlb_rsp;
+    sc_signal<paddr_t>      r_dcache_tlb_nline;
+
+    sc_signal<bool>         r_dcache_itlb_cleanup_req;
+    sc_signal<paddr_t>      r_dcache_itlb_cleanup_line;
+
+    sc_signal<bool>         r_dcache_dtlb_cleanup_req;
+    sc_signal<paddr_t>      r_dcache_dtlb_cleanup_line;
+
+    sc_signal<bool>         r_itlb_inval_req;
+    sc_signal<bool>         r_dcache_cc_check;
+
+    WriteBuffer<paddr_t>     r_wbuf;
+    GenericCache<paddr_t>    r_icache;
+    GenericCache<paddr_t>    r_dcache;
+
+    // Activity counters
+    uint32_t m_cpt_dcache_data_read;        // DCACHE DATA READ
+    uint32_t m_cpt_dcache_data_write;       // DCACHE DATA WRITE
+    uint32_t m_cpt_dcache_dir_read;         // DCACHE DIR READ
+    uint32_t m_cpt_dcache_dir_write;        // DCACHE DIR WRITE
+
+    uint32_t m_cpt_icache_data_read;        // ICACHE DATA READ
+    uint32_t m_cpt_icache_data_write;       // ICACHE DATA WRITE
+    uint32_t m_cpt_icache_dir_read;         // ICACHE DIR READ
+    uint32_t m_cpt_icache_dir_write;        // ICACHE DIR WRITE
+
+    uint32_t m_cpt_frz_cycles;	            // number of cycles where the cpu is frozen
+    uint32_t m_cpt_total_cycles;	        // total number of cycles 
+
+    // Cache activity counters
+    uint32_t m_cpt_read;                    // total number of read data
+    uint32_t m_cpt_write;                   // total number of write data
+    uint32_t m_cpt_data_miss;               // number of read miss
+    uint32_t m_cpt_ins_miss;                // number of instruction miss
+    uint32_t m_cpt_unc_read;                // number of read uncached
+    uint32_t m_cpt_write_cached;            // number of cached write
+    uint32_t m_cpt_ins_read;                // number of instruction read
+
+    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
+    uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
+    uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
+    uint32_t m_cost_ins_miss_frz;           // number of frozen cycles related to ins miss
+
+    uint32_t m_cpt_imiss_transaction;       // number of VCI instruction miss transactions
+    uint32_t m_cpt_dmiss_transaction;       // number of VCI data miss transactions
+    uint32_t m_cpt_unc_transaction;         // number of VCI uncached read transactions
+    uint32_t m_cpt_write_transaction;       // number of VCI write transactions
+
+    uint32_t m_cost_imiss_transaction;      // cumulated duration for VCI IMISS transactions
+    uint32_t m_cost_dmiss_transaction;      // cumulated duration for VCI DMISS transactions
+    uint32_t m_cost_unc_transaction;        // cumulated duration for VCI UNC transactions
+    uint32_t m_cost_write_transaction;      // cumulated duration for VCI WRITE transactions
+    uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions
+
+    // TLB activity counters
+    uint32_t m_cpt_ins_tlb_read;            // number of instruction tlb read
+    uint32_t m_cpt_ins_tlb_miss;            // number of instruction tlb miss
+    uint32_t m_cpt_ins_tlb_write_et;        // number of instruction tlb write ET
+
+    uint32_t m_cpt_data_tlb_read;           // number of data tlb read
+    uint32_t m_cpt_data_tlb_miss;           // number of data tlb miss
+    uint32_t m_cpt_data_tlb_write_et;       // number of data tlb write ET
+    uint32_t m_cpt_data_tlb_write_dirty;    // number of data tlb write dirty
+    
+    uint32_t m_cost_ins_tlb_miss_frz;       // number of frozen cycles related to instruction tlb miss
+    uint32_t m_cost_data_tlb_miss_frz;      // number of frozen cycles related to data tlb miss
+
+    uint32_t m_cost_ins_waste_wait_frz;     // number of frozen cycles related to ins wait coherence operate 
+    uint32_t m_cost_ins_tlb_sw_frz;         // number of frozen cycles related to ins context switch
+    uint32_t m_cost_ins_cache_flush_frz;    // number of frozen cycles related to ins cache flush 
+
+    uint32_t m_cpt_ins_tlb_cleanup;         // number of ins tlb cleanup 
+    uint32_t m_cost_data_waste_wait_frz;    // number of frozen cycles related to data wait coherence operate
+    uint32_t m_cost_data_tlb_sw_frz;        // number of frozen cycles related to data context switch
+    uint32_t m_cost_data_cache_flush_frz;   // number of frozen cycles related to data cache flush
+
+    uint32_t m_cpt_itlbmiss_transaction;    // number of itlb miss transactions
+    uint32_t m_cpt_itlb_write_transaction;  // number of itlb write ET transactions
+    uint32_t m_cpt_dtlbmiss_transaction;    // number of dtlb miss transactions
+    uint32_t m_cpt_dtlb_write_transaction;  // number of dtlb write ET and dirty transactions
+
+    uint32_t m_cost_itlbmiss_transaction;   // cumulated duration for VCI instruction TLB miss transactions
+    uint32_t m_cost_itlb_write_transaction; // cumulated duration for VCI instruction TLB write ET transactions
+    uint32_t m_cost_dtlbmiss_transaction;   // cumulated duration for VCI data TLB miss transactions
+    uint32_t m_cost_dtlb_write_transaction; // cumulated duration for VCI data TLB write transactions
+
+    uint32_t m_cpt_cc_update;               // number of coherence update packets 
+    uint32_t m_cpt_cc_inval;                // number of coherence inval packets
+    uint32_t m_cpt_cc_broadcast;            // number of coherence broadcast packets
+
+    uint32_t m_cost_ins_tlb_inval_frz;      // number of frozen cycles related to checking ins tlb invalidate
+    uint32_t m_cpt_ins_tlb_inval;           // number of ins tlb invalidate
+
+    uint32_t m_cost_data_tlb_inval_frz;     // number of frozen cycles related to checking data tlb invalidate    
+    uint32_t m_cpt_data_tlb_inval;          // number of data tlb invalidate
+
+protected:
+    SC_HAS_PROCESS(VciCcVCacheWrapper2Ring);
+
+public:
+    VciCcVCacheWrapper2Ring(
+        sc_module_name insname,
+        int proc_id,
+        const soclib::common::MappingTable &mtp,
+        const soclib::common::MappingTable &mtc,
+        const soclib::common::IntTab &initiator_index_rw,
+        const soclib::common::IntTab &initiator_index_c,
+        const soclib::common::IntTab &target_index,
+        size_t itlb_ways,
+        size_t itlb_sets,
+        size_t dtlb_ways,
+        size_t dtlb_sets,
+        size_t icache_ways,
+        size_t icache_sets,
+        size_t icache_words,
+        size_t dcache_ways,
+        size_t dcache_sets,
+        size_t dcache_words,
+        size_t write_buf_size );
+
+    ~VciCcVCacheWrapper2Ring();
+
+    void print_cpi();
+    void print_stats();
+
+private:
+    void transition();
+    void genMoore();
+
+    soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC);
+    soclib_static_assert((int)iss_t::SC_NOT_ATOMIC == (int)vci_param::STORE_COND_NOT_ATOMIC);
+};
+
+}}
+
+#endif /* SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER2_RING_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
+
Index: trunk/modules/vci_cc_vcache_wrapper2_ring/caba/source/src/vci_cc_vcache_wrapper2_ring.cpp
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper2_ring/caba/source/src/vci_cc_vcache_wrapper2_ring.cpp	(revision 2)
+++ trunk/modules/vci_cc_vcache_wrapper2_ring/caba/source/src/vci_cc_vcache_wrapper2_ring.cpp	(revision 2)
@@ -0,0 +1,5545 @@
+/* -*- c++ -*-
+ * File : vci_cc_vcache_wrapper2_ring.cpp
+ * Copyright (c) UPMC, Lip6, SoC
+ * Authors : Alain GREINER, Yang GAO
+ *
+ * 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
+ */
+
+#include <cassert>
+#include "arithmetics.h"
+#include "../include/vci_cc_vcache_wrapper2_ring.h"
+
+namespace soclib { 
+namespace caba {
+
+#ifdef SOCLIB_MODULE_DEBUG
+namespace {
+const char *icache_fsm_state_str[] = {
+        "ICACHE_IDLE",
+        "ICACHE_BIS",       
+        "ICACHE_TLB1_READ",  
+        "ICACHE_TLB1_WRITE",  
+        "ICACHE_TLB1_UPDT",  
+        "ICACHE_TLB2_READ",  
+        "ICACHE_TLB2_WRITE",  
+        "ICACHE_TLB2_UPDT",  
+        "ICACHE_SW_FLUSH", 
+        "ICACHE_CACHE_FLUSH", 
+        "ICACHE_TLB_INVAL",  
+        "ICACHE_CACHE_INVAL",
+        "ICACHE_MISS_WAIT",
+        "ICACHE_UNC_WAIT",  
+        "ICACHE_MISS_UPDT",  
+        "ICACHE_ERROR", 	
+        "ICACHE_CC_INVAL", 
+        "ICACHE_TLB_CC_INVAL",        
+        "ICACHE_TLB_FLUSH",
+    };
+const char *dcache_fsm_state_str[] = {
+        "DCACHE_IDLE",       
+        "DCACHE_BIS",   
+        "DCACHE_DTLB1_READ_CACHE",
+	"DCACHE_TLB1_LL_WAIT",
+	"DCACHE_TLB1_SC_WAIT",    
+        "DCACHE_TLB1_READ",
+        "DCACHE_TLB1_READ_UPDT",  
+        "DCACHE_TLB1_UPDT", 
+        "DCACHE_DTLB2_READ_CACHE", 
+	"DCACHE_TLB2_LL_WAIT",
+	"DCACHE_TLB2_SC_WAIT",   
+        "DCACHE_TLB2_READ",
+        "DCACHE_TLB2_READ_UPDT",  
+        "DCACHE_TLB2_UPDT",   
+        "DCACHE_CTXT_SWITCH",   
+        "DCACHE_ICACHE_FLUSH", 
+        "DCACHE_DCACHE_FLUSH", 
+        "DCACHE_ITLB_INVAL",
+        "DCACHE_DTLB_INVAL",
+        "DCACHE_ICACHE_INVAL",
+        "DCACHE_DCACHE_INVAL",
+	"DCACHE_DCACHE_SYNC",
+	"DCACHE_LL_DIRTY_WAIT",
+	"DCACHE_SC_DIRTY_WAIT",
+        "DCACHE_WRITE_UPDT", 
+        "DCACHE_WRITE_DIRTY",
+        "DCACHE_WRITE_REQ",  
+        "DCACHE_MISS_WAIT",  
+        "DCACHE_MISS_UPDT",  
+        "DCACHE_UNC_WAIT",   
+        "DCACHE_ERROR", 
+        "DCACHE_ITLB_READ",
+        "DCACHE_ITLB_UPDT",
+        "DCACHE_ITLB_LL_WAIT",        
+        "DCACHE_ITLB_SC_WAIT",        
+        "DCACHE_CC_CHECK",
+        "DCACHE_CC_INVAL",
+        "DCACHE_CC_UPDT",
+        "DCACHE_CC_NOP",
+        "DCACHE_TLB_CC_INVAL",
+        "DCACHE_ITLB_CLEANUP",
+    };
+const char *cmd_fsm_state_str[] = {
+        "CMD_IDLE",           
+        "CMD_ITLB_READ", 
+        "CMD_ITLB_ACC_LL",                
+        "CMD_ITLB_ACC_SC",                
+        "CMD_INS_MISS",     
+        "CMD_INS_UNC",     
+        "CMD_DTLB_READ",   
+        "CMD_DTLB_ACC_LL",            
+        "CMD_DTLB_ACC_SC",            
+        "CMD_DTLB_DIRTY_LL",          
+        "CMD_DTLB_DIRTY_SC",          
+        "CMD_DATA_UNC",     
+        "CMD_DATA_MISS",    
+        "CMD_DATA_WRITE", 
+    };
+const char *rsp_fsm_state_str[] = {
+        "RSP_IDLE",                  
+        "RSP_ITLB_READ",             
+        "RSP_ITLB_ACC_LL",                
+        "RSP_ITLB_ACC_SC",                
+        "RSP_INS_MISS",   
+        "RSP_INS_UNC",           
+        "RSP_DTLB_READ",            
+        "RSP_DTLB_ACC_LL",            
+        "RSP_DTLB_ACC_SC",            
+        "RSP_DTLB_DIRTY_LL",          
+        "RSP_DTLB_DIRTY_SC",          
+        "RSP_DATA_MISS",             
+        "RSP_DATA_UNC",              
+        "RSP_DATA_WRITE",  
+    };
+const char *cmd_cleanup_fsm_state_str[] = {
+        "CMD_CLEANUP_INS_IDLE",           
+        "CMD_CLEANUP_DATA_IDLE",           
+        "CMD_CLEANUP_INS",    
+        "CMD_CLEANUP_DATA",      
+    };
+const char *rsp_cleanup_fsm_state_str[] = {
+        "RSP_CLEANUP_INS_IDLE",                  
+        "RSP_CLEANUP_DATA_IDLE",                  
+        "RSP_CLEANUP_INS",    
+        "RSP_CLEANUP_DATA",        
+    };
+const char *tgt_fsm_state_str[] = {
+        "TGT_IDLE",
+        "TGT_UPDT_WORD",
+        "TGT_UPDT_DATA",
+        "TGT_REQ_BROADCAST",
+        "TGT_REQ_DCACHE",
+        "TGT_RSP_BROADCAST",
+        "TGT_RSP_DCACHE",
+    };	
+const char *inval_itlb_fsm_state_str[] = {
+        "INVAL_ITLB_IDLE",        
+        "INVAL_ITLB_CHECK"  , 
+        "INVAL_ITLB_INVAL",      
+        "INVAL_ITLB_CLEAR",           
+    };
+const char *inval_dtlb_fsm_state_str[] = {
+        "INVAL_DTLB_IDLE",        
+        "INVAL_DTLB_CHECK", 
+        "INVAL_DTLB_INVAL",    
+        "INVAL_DTLB_CLEAR",         
+    };
+}
+#endif
+
+#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcVCacheWrapper2Ring<vci_param, iss_t>
+
+using soclib::common::uint32_log2;
+
+/***********************************************/
+tmpl(/**/)::VciCcVCacheWrapper2Ring(
+    sc_module_name name,
+    int proc_id,
+    const soclib::common::MappingTable &mtp,
+    const soclib::common::MappingTable &mtc,
+    const soclib::common::IntTab &initiator_index_rw,
+    const soclib::common::IntTab &initiator_index_c,
+    const soclib::common::IntTab &target_index,
+    size_t itlb_ways,
+    size_t itlb_sets,
+    size_t dtlb_ways,
+    size_t dtlb_sets,
+    size_t icache_ways,
+    size_t icache_sets,
+    size_t icache_words,
+    size_t dcache_ways,
+    size_t dcache_sets,
+    size_t dcache_words,    
+    size_t write_buf_size )
+/***********************************************/
+    : soclib::caba::BaseModule(name),
+
+      p_clk("clk"),
+      p_resetn("resetn"),
+      p_vci_ini_rw("vci_ini_rw"),
+      p_vci_ini_c("vci_ini_c"),
+      p_vci_tgt("vci_tgt"),
+
+      m_cacheability_table(mtp.getCacheabilityTable()),
+      m_segment(mtc.getSegment(target_index)),
+      m_iss(this->name(), proc_id),
+      m_srcid_rw(mtp.indexForId(initiator_index_rw)),
+      m_srcid_c(mtc.indexForId(initiator_index_c)),
+
+      m_itlb_ways(itlb_ways),
+      m_itlb_sets(itlb_sets),
+
+      m_dtlb_ways(dtlb_ways),
+      m_dtlb_sets(dtlb_sets),
+
+      m_icache_ways(icache_ways),
+      m_icache_sets(icache_sets),
+      m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
+      m_icache_words(icache_words),
+
+      m_dcache_ways(dcache_ways),
+      m_dcache_sets(dcache_sets),
+      m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
+      m_dcache_words(dcache_words),
+
+      m_write_buf_size(write_buf_size),	
+      m_paddr_nbits(vci_param::N),
+
+      icache_tlb(itlb_ways,itlb_sets,vci_param::N),
+      dcache_tlb(dtlb_ways,dtlb_sets,vci_param::N),
+
+      r_dcache_fsm("r_dcache_fsm"),
+      r_dcache_paddr_save("r_dcache_paddr_save"),
+      r_dcache_wdata_save("r_dcache_wdata_save"),
+      r_dcache_rdata_save("r_dcache_rdata_save"),
+      r_dcache_type_save("r_dcache_type_save"),
+      r_dcache_be_save("r_dcache_be_save"),
+      r_dcache_cached_save("r_dcache_cached_save"),
+      r_dcache_tlb_paddr("r_dcache_tlb_paddr"),
+      r_dcache_miss_req("r_dcache_miss_req"),
+      r_dcache_unc_req("r_dcache_unc_req"),
+      r_dcache_write_req("r_dcache_write_req"),
+      r_dcache_tlb_read_req("r_dcache_tlb_read_req"),
+      r_dcache_tlb_ll_acc_req("r_dcache_tlb_ll_acc_req"),       
+      r_dcache_tlb_sc_acc_req("r_dcache_tlb_sc_acc_req"),       
+      r_dcache_tlb_ll_dirty_req("r_dcache_tlb_ll_dirty_req"),    
+      r_dcache_tlb_sc_dirty_req("r_dcache_tlb_sc_dirty_req"), 
+      r_dcache_tlb_ptba_read("r_dcache_tlb_ptba_read"),
+      r_dcache_xtn_req("r_dcache_xtn_req"),
+
+      r_dcache_fsm_save("r_dcache_fsm_save"),
+      r_dcache_cleanup_req("r_dcache_cleanup_req"),
+      r_dcache_inval_rsp("r_dcache_inval_rsp"),
+
+      r_icache_fsm("r_icache_fsm"),
+      r_icache_paddr_save("r_icache_paddr_save"),
+      r_icache_miss_req("r_icache_miss_req"),
+      r_icache_unc_req("r_icache_unc_req"),
+      r_dcache_itlb_read_req("r_dcache_itlb_read_req"),
+      r_dcache_itlb_ll_acc_req("r_dcache_itlb_ll_acc_req"),     
+      r_dcache_itlb_sc_acc_req("r_dcache_itlb_sc_acc_req"),
+      r_itlb_read_dcache_req("r_itlb_read_dcache_req"),
+      r_itlb_acc_dcache_req("r_itlb_acc_dcache_req"),
+      r_dcache_rsp_itlb_error("r_dcache_rsp_itlb_error"),
+
+      r_icache_fsm_save("r_icache_fsm_save"),
+      r_icache_cleanup_req("r_icache_cleanup_req"),
+      r_icache_inval_rsp("r_icache_inval_rsp"),
+
+      r_vci_cmd_fsm("r_vci_cmd_fsm"),
+      r_vci_cmd_min("r_vci_cmd_min"),
+      r_vci_cmd_max("r_vci_cmd_max"),
+      r_vci_cmd_cpt("r_vci_cmd_cpt"),
+
+      r_vci_rsp_fsm("r_vci_rsp_fsm"),
+      r_vci_rsp_cpt("r_vci_rsp_cpt"),
+      r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
+      r_vci_rsp_data_error("r_vci_rsp_data_error"),
+
+      r_vci_cmd_cleanup_fsm("r_vci_cmd_cleanup_fsm"),
+      r_vci_rsp_cleanup_fsm("r_vci_rsp_cleanup_fsm"),
+
+      r_vci_tgt_fsm("r_vci_tgt_fsm"),
+      r_tgt_addr("r_tgt_addr"),
+      r_tgt_word("r_tgt_word"),
+      r_tgt_update("r_tgt_update"),
+      r_tgt_srcid("r_tgt_srcid"),
+      r_tgt_pktid("r_tgt_pktid"),
+      r_tgt_trdid("r_tgt_trdid"),
+      r_tgt_icache_req("r_tgt_icache_req"),
+      r_tgt_dcache_req("r_tgt_dcache_req"),
+
+      r_inval_itlb_fsm("r_inval_itlb_fsm"),          
+      r_dcache_itlb_inval_req("r_dcache_itlb_inval_req"),
+      r_dcache_itlb_inval_line("r_dcache_itlb_inval_line"),
+      r_itlb_cc_check_end("r_itlb_cc_check_end"),
+      r_ccinval_itlb_way("r_ccinval_itlb_way"), 
+      r_ccinval_itlb_set("r_ccinval_itlb_set"), 
+      r_icache_inval_tlb_rsp("r_icache_inval_tlb_rsp"),
+      r_icache_tlb_nline("r_icache_tlb_nline"),
+
+      r_inval_dtlb_fsm("r_inval_dtlb_fsm"),          
+      r_dcache_dtlb_inval_req("r_dcache_dtlb_inval_req"),
+      r_dcache_dtlb_inval_line("r_dcache_dtlb_inval_line"),
+      r_dtlb_cc_check_end("r_dtlb_cc_check_end"),
+      r_ccinval_dtlb_way("r_ccinval_dtlb_way"), 
+      r_ccinval_dtlb_set("r_ccinval_dtlb_set"), 
+      r_dcache_inval_tlb_rsp("r_dcache_inval_tlb_rsp"),
+      r_dcache_tlb_nline("r_dcache_tlb_nline"),
+
+      r_dcache_itlb_cleanup_req("r_dcache_itlb_cleanup_req"),
+      r_dcache_itlb_cleanup_line("r_dcache_itlb_cleanup_line"),
+
+      r_dcache_dtlb_cleanup_req("r_dcache_dtlb_cleanup_req"),
+      r_dcache_dtlb_cleanup_line("r_dcache_dtlb_cleanup_line"),
+
+      r_wbuf("wbuf", write_buf_size ),
+      r_icache("icache", icache_ways, icache_sets, icache_words),
+      r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
+{
+    r_icache_miss_buf = new data_t[icache_words];
+    r_dcache_miss_buf = new data_t[dcache_words];
+    r_tgt_buf         = new data_t[dcache_words];
+    r_tgt_val         = new bool[dcache_words];
+    r_dcache_in_itlb  = new bool[dcache_ways*dcache_sets];           
+    r_dcache_in_dtlb  = new bool[dcache_ways*dcache_sets];          
+
+    SC_METHOD(transition);
+    dont_initialize();
+    sensitive << p_clk.pos();
+  
+    SC_METHOD(genMoore);
+    dont_initialize();
+    sensitive << p_clk.neg();
+
+    typename iss_t::CacheInfo cache_info;
+    cache_info.has_mmu = true;
+    cache_info.icache_line_size = icache_words*sizeof(data_t);
+    cache_info.icache_assoc = icache_ways;
+    cache_info.icache_n_lines = icache_sets;
+    cache_info.dcache_line_size = dcache_words*sizeof(data_t);
+    cache_info.dcache_assoc = dcache_ways;
+    cache_info.dcache_n_lines = dcache_sets;
+    m_iss.setCacheInfo(cache_info);
+}
+
+/////////////////////////////////////
+tmpl(/**/)::~VciCcVCacheWrapper2Ring()
+/////////////////////////////////////
+{
+    delete [] r_icache_miss_buf;
+    delete [] r_dcache_miss_buf;
+    delete [] r_tgt_val;
+    delete [] r_tgt_buf;
+    delete [] r_dcache_in_itlb;           
+    delete [] r_dcache_in_dtlb;          
+}
+
+////////////////////////
+tmpl(void)::print_cpi()
+////////////////////////
+{
+    std::cout << name() << " CPI = " 
+        << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
+}
+
+////////////////////////
+tmpl(void)::print_stats()
+////////////////////////
+{
+    float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
+    std::cout << name() << std::endl
+              << "- CPI                    = " << (float)m_cpt_total_cycles/run_cycles << std::endl 
+              << "- READ RATE              = " << (float)m_cpt_read/run_cycles << std::endl 
+              << "- WRITE RATE             = " << (float)m_cpt_write/run_cycles << std::endl
+              << "- UNCACHED READ RATE     = " << (float)m_cpt_unc_read/m_cpt_read << std::endl 
+              << "- CACHED WRITE RATE      = " << (float)m_cpt_write_cached/m_cpt_write << std::endl 
+              << "- IMISS_RATE             = " << (float)m_cpt_ins_miss/m_cpt_ins_read << std::endl    
+              << "- DMISS RATE             = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl 
+              << "- INS MISS COST          = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl
+              << "- IMISS TRANSACTION      = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl
+              << "- DMISS COST             = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl
+              << "- DMISS TRANSACTION      = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl
+              << "- UNC COST               = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl
+              << "- UNC TRANSACTION        = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl
+              << "- WRITE COST             = " << (float)m_cost_write_frz/m_cpt_write << std::endl
+              << "- WRITE TRANSACTION      = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl
+              << "- WRITE LENGTH           = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl
+              << "- INS TLB MISS RATE      = " << (float)m_cpt_ins_tlb_miss/m_cpt_ins_tlb_read << std::endl
+              << "- DATA TLB MISS RATE     = " << (float)m_cpt_data_tlb_miss/m_cpt_data_tlb_read << std::endl
+              << "- ITLB MISS TRANSACTION  = " << (float)m_cost_itlbmiss_transaction/m_cpt_itlbmiss_transaction << std::endl
+              << "- ITLB WRITE TRANSACTION = " << (float)m_cost_itlb_write_transaction/m_cpt_itlb_write_transaction << std::endl
+              << "- ITLB MISS COST         = " << (float)m_cost_ins_tlb_miss_frz/(m_cpt_ins_tlb_miss+m_cpt_ins_tlb_write_et) << std::endl
+              << "- DTLB MISS TRANSACTION  = " << (float)m_cost_dtlbmiss_transaction/m_cpt_dtlbmiss_transaction << std::endl
+              << "- DTLB WRITE TRANSACTION = " << (float)m_cost_dtlb_write_transaction/m_cpt_dtlb_write_transaction << std::endl
+              << "- DTLB MISS COST         = " << (float)m_cost_data_tlb_miss_frz/(m_cpt_data_tlb_miss+m_cpt_data_tlb_write_et+m_cpt_data_tlb_write_dirty) << std::endl;
+}
+
+/*************************************************/
+tmpl(void)::transition()
+/*************************************************/
+{
+    if ( ! p_resetn.read() ) 
+    {
+        m_iss.reset();
+
+        r_dcache_fsm = DCACHE_IDLE;
+        r_icache_fsm = ICACHE_IDLE;
+        r_vci_cmd_fsm = CMD_IDLE;
+        r_vci_rsp_fsm = RSP_IDLE;
+        r_vci_cmd_cleanup_fsm = CMD_CLEANUP_INS_IDLE;
+        r_vci_rsp_cleanup_fsm = RSP_CLEANUP_INS_IDLE;
+        r_vci_tgt_fsm = TGT_IDLE;
+        r_inval_itlb_fsm = INVAL_ITLB_IDLE;          
+        r_inval_dtlb_fsm = INVAL_DTLB_IDLE;          
+
+        // write buffer & caches
+        r_wbuf.reset();
+        r_icache.reset();
+        r_dcache.reset();
+
+        icache_tlb.reset();    
+        dcache_tlb.reset();    
+
+        std::memset(r_dcache_in_itlb, 0, sizeof(*r_dcache_in_itlb)*m_icache_ways*m_icache_sets);
+        std::memset(r_dcache_in_dtlb, 0, sizeof(*r_dcache_in_dtlb)*m_dcache_ways*m_dcache_sets);
+
+        r_mmu_mode = ALL_DEACTIVE;
+
+        r_icache_miss_req         = false;
+        r_icache_unc_req          = false;
+        r_dcache_itlb_read_req    = false;
+
+        r_itlb_read_dcache_req 	  = false;      
+        r_itlb_acc_dcache_req     = false;   
+        r_dcache_rsp_itlb_error   = false;
+ 
+        r_dcache_miss_req         = false;
+        r_dcache_unc_req          = false;
+        r_dcache_write_req        = false;
+        r_dcache_tlb_read_req     = false;
+        r_dcache_tlb_ptba_read    = false;
+        r_dcache_xtn_req          = false;
+	r_dcache_llsc_reserved    = false;
+
+        r_dcache_tlb_ll_acc_req   = false;    
+        r_dcache_tlb_sc_acc_req   = false;    
+        r_dcache_tlb_ll_dirty_req = false;   
+        r_dcache_tlb_sc_dirty_req = false;   
+        r_dcache_itlb_ll_acc_req  = false;   
+        r_dcache_itlb_sc_acc_req  = false;   
+
+        r_icache_cleanup_req      = false;
+        r_dcache_cleanup_req      = false;
+
+        r_tgt_icache_req          = false;
+        r_tgt_dcache_req          = false;
+
+        r_icache_inval_rsp        = false;
+        r_dcache_inval_rsp        = false;
+
+        r_dcache_dirty_save       = false;
+        r_dcache_hit_p_save       = false;
+
+        r_icache_buf_unc_valid    = false;
+        r_dcache_buf_unc_valid    = false;
+
+        r_vci_rsp_ins_error       = false;
+        r_vci_rsp_data_error      = false;
+
+        r_icache_id1_save         = 0;
+        r_icache_ppn_save         = 0;
+        r_icache_vpn_save         = 0;
+        r_itlb_translation_valid  = false;
+
+        r_dcache_id1_save         = 0;
+        r_dcache_ppn_save         = 0;
+        r_dcache_vpn_save         = 0;
+        r_dtlb_translation_valid  = false;
+
+        r_icache_ptba_ok          = false;
+        r_dcache_ptba_ok          = false;
+
+        r_icache_error_type       = MMU_NONE;
+        r_dcache_error_type       = MMU_NONE;
+
+        // coherence registers
+        r_icache_way              = 0;
+        r_icache_set              = 0;
+        r_icache_cleanup_req      = false;
+        r_icache_inval_rsp        = false;
+
+        r_dcache_way              = 0;
+        r_dcache_set              = 0;
+        r_dcache_cleanup_req      = false;
+        r_dcache_inval_rsp        = false;
+
+	r_itlb_inval_req 	  = false;
+        r_dcache_itlb_inval_req   = false;
+        r_itlb_cc_check_end       = false;
+        r_ccinval_itlb_way        = 0; 
+        r_ccinval_itlb_set        = 0; 
+        r_icache_inval_tlb_rsp    = false;
+
+        r_dcache_dtlb_inval_req   = false;
+        r_dtlb_cc_check_end       = false;
+        r_ccinval_dtlb_way        = 0; 
+        r_ccinval_dtlb_set        = 0; 
+        r_dcache_inval_tlb_rsp    = false;
+
+        r_dcache_itlb_cleanup_req = false;
+        r_dcache_dtlb_cleanup_req = false;
+
+	r_dcache_cc_check         = false;
+
+        // activity counters
+        m_cpt_dcache_data_read  = 0;
+        m_cpt_dcache_data_write = 0;
+        m_cpt_dcache_dir_read   = 0;
+        m_cpt_dcache_dir_write  = 0;
+        m_cpt_icache_data_read  = 0;
+        m_cpt_icache_data_write = 0;
+        m_cpt_icache_dir_read   = 0;
+        m_cpt_icache_dir_write  = 0;
+
+	m_cpt_frz_cycles   = 0;
+        m_cpt_total_cycles = 0;
+
+        m_cpt_read         = 0;
+        m_cpt_write        = 0;
+        m_cpt_data_miss    = 0;
+        m_cpt_ins_miss     = 0;
+        m_cpt_unc_read     = 0;
+        m_cpt_write_cached = 0;
+        m_cpt_ins_read     = 0;
+
+        m_cost_write_frz     = 0;
+        m_cost_data_miss_frz = 0;
+        m_cost_unc_read_frz  = 0;
+        m_cost_ins_miss_frz  = 0;
+
+        m_cpt_imiss_transaction = 0;
+        m_cpt_dmiss_transaction = 0;
+        m_cpt_unc_transaction   = 0;
+        m_cpt_write_transaction = 0;
+
+        m_cost_imiss_transaction   = 0;
+        m_cost_dmiss_transaction   = 0;
+        m_cost_unc_transaction     = 0;
+        m_cost_write_transaction   = 0;
+        m_length_write_transaction = 0;
+
+        m_cpt_ins_tlb_read         = 0;             
+        m_cpt_ins_tlb_miss         = 0;             
+        m_cpt_ins_tlb_write_et     = 0;         
+
+        m_cpt_data_tlb_read        = 0;           
+        m_cpt_data_tlb_miss        = 0;           
+        m_cpt_data_tlb_write_et    = 0;       
+        m_cpt_data_tlb_write_dirty = 0;    
+
+        m_cost_ins_tlb_miss_frz    = 0;      
+        m_cost_data_tlb_miss_frz   = 0;      
+
+        m_cpt_itlbmiss_transaction   = 0;    
+        m_cpt_itlb_write_transaction = 0;  
+        m_cpt_dtlbmiss_transaction   = 0;  
+        m_cpt_dtlb_write_transaction = 0;  
+ 
+        m_cost_itlbmiss_transaction   = 0;   
+        m_cost_itlb_write_transaction = 0;  
+        m_cost_dtlbmiss_transaction   = 0;   
+        m_cost_dtlb_write_transaction = 0;   
+        return;
+    }
+
+
+#ifdef SOCLIB_MODULE_DEBUG
+std::cout << name() << "cycle = " << m_cpt_total_cycles  
+       	  << " tgt fsm: " << tgt_fsm_state_str[r_vci_tgt_fsm]
+       	  << " dcache fsm: " << dcache_fsm_state_str[r_dcache_fsm]
+       	  << " icache fsm: " << icache_fsm_state_str[r_icache_fsm]
+       	  << " cmd fsm: " << cmd_fsm_state_str[r_vci_cmd_fsm]
+       	  << " rsp fsm: " << rsp_fsm_state_str[r_vci_rsp_fsm] 
+       	  << " cmd cleanup fsm: " << cmd_cleanup_fsm_state_str[r_vci_cmd_cleanup_fsm]
+       	  << " rsp cleanup fsm: " << rsp_cleanup_fsm_state_str[r_vci_rsp_cleanup_fsm] 
+       	  << " inval itlb fsm: " << inval_itlb_fsm_state_str[r_inval_itlb_fsm] 
+       	  << " inval dtlb fsm: " << inval_dtlb_fsm_state_str[r_inval_dtlb_fsm] << std::endl;
+#endif
+    m_cpt_total_cycles++;
+
+    typename iss_t::InstructionRequest ireq = ISS_IREQ_INITIALIZER;
+    typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
+
+    typename iss_t::DataRequest dreq = ISS_DREQ_INITIALIZER;
+    typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
+
+    m_iss.getRequests( ireq, dreq );
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout << name() << " Instruction Request: " << ireq << std::endl;
+    std::cout << name() << " Data Request: " << dreq << std::endl;
+#endif
+
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_FSM controls the following ressources:
+    // - r_vci_tgt_fsm
+    // - r_tgt_buf[nwords]
+    // - r_tgt_val[nwords]
+    // - r_tgt_update
+    // - r_tgt_word
+    // - r_tgt_addr
+    // - r_tgt_srcid
+    // - r_tgt_trdid
+    // - r_tgt_pktid
+    // All VCI commands must be CMD_WRITE.
+    // If the VCI address offset is null, the command is an invalidate 
+    // request. It is an update request otherwise.
+    // The VCI_TGT FSM stores the external request arguments in the
+    // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 
+    // & r_tgt_dcache_req flip-flops to signal the external request to 
+    // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
+    // of the update or invalidate request in the RSP state.
+    // -  for an invalidate request the VCI packet length is 1 word.
+    // The WDATA field contains the line index (i.e. the Z & Y fields).
+    // -  for an update request the VCI packet length is (n+2) words.
+    // The WDATA field of the first VCI word contains the line number.
+    // The WDATA field of the second VCI word contains the word index.
+    // The WDATA field of the n following words contains the values.
+    // -  for both invalidate & update requests, the VCI response
+    // is one single word.
+    // In case of errors in the VCI command packet, the simulation
+    // is stopped with an error message.
+    /////////////////////////////////////////////////////////////////////
+    
+    switch(r_vci_tgt_fsm) {
+    //////////////
+    case TGT_IDLE:
+    {
+        if ( p_vci_tgt.cmdval.read() ) 
+        {
+            paddr_t address = p_vci_tgt.address.read();
+
+            if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the received VCI command is not a write" << std::endl;
+                exit(0);
+            }
+
+            // multi-update or multi-invalidate for data type
+            if ( ( address != 0x3 ) && ( ! m_segment.contains(address)) ) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "out of segment VCI command received for a multi-updt or multi-inval request" << std::endl;
+                exit(0);
+            }
+
+            r_tgt_srcid = p_vci_tgt.srcid.read();
+            r_tgt_trdid = p_vci_tgt.trdid.read();
+            r_tgt_pktid = p_vci_tgt.pktid.read();
+            r_tgt_plen  = p_vci_tgt.plen.read(); // todo: wait L2 modification
+            r_tgt_addr = (paddr_t)p_vci_tgt.wdata.read() * m_dcache_words * 4; 
+
+            if ( address == 0x3 ) // broadcast invalidate for data or instruction type
+            {
+                if ( ! p_vci_tgt.eop.read() ) 
+                {
+                    std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                    std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
+                    exit(0);
+                }
+                r_tgt_update = false; 
+                r_vci_tgt_fsm = TGT_REQ_BROADCAST;
+                m_cpt_cc_broadcast++;
+            }
+            else                // multi-update or multi-invalidate for data type
+            {
+                paddr_t cell = address - m_segment.baseAddress();   
+
+                if (cell == 0)                      // invalidate   
+                {                         
+                    if ( ! p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_update = false; 
+                    r_vci_tgt_fsm = TGT_REQ_DCACHE;
+                    m_cpt_cc_inval++ ;
+                } 
+                else                                // update
+                {                                
+                    if ( p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_update = true; 
+                    r_vci_tgt_fsm = TGT_UPDT_WORD;
+                    m_cpt_cc_update++ ;
+                }     
+            } // end if address    
+        } // end if cmdval
+        break;
+    }
+    ////////////////////
+    case TGT_UPDT_WORD:
+    {
+        if (p_vci_tgt.cmdval.read()) 
+        {
+            if ( p_vci_tgt.eop.read() ) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                exit(0);
+            }
+            for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_val[i] = false;
+            r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
+            r_vci_tgt_fsm = TGT_UPDT_DATA;
+        }
+        break;
+    }
+    ////////////////////
+    case TGT_UPDT_DATA:
+    {
+        if (p_vci_tgt.cmdval.read()) 
+        {
+            size_t word = r_tgt_word.read();
+            if (word >= m_dcache_words) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
+                exit(0);
+            }
+            r_tgt_buf[word] = p_vci_tgt.wdata.read();
+            if(p_vci_tgt.be.read())    r_tgt_val[word] = true;
+            r_tgt_word = word + 1;
+            if (p_vci_tgt.eop.read())  r_vci_tgt_fsm = TGT_REQ_DCACHE;
+        }
+        break;
+    }
+    ///////////////////////
+    case TGT_REQ_BROADCAST:
+    {
+        if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_RSP_BROADCAST; 
+            r_tgt_icache_req = true;
+            r_tgt_dcache_req = true;
+        }
+        break;
+    }
+    ////////////////////
+    case TGT_REQ_DCACHE:
+    {
+        if ( !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_RSP_DCACHE; 
+            r_tgt_dcache_req = true;
+        }
+        break;
+    }
+    ///////////////////////
+    case TGT_RSP_BROADCAST:
+    {
+        // no response
+        if ( !r_tgt_icache_rsp.read() && !r_tgt_dcache_rsp.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
+        {
+            r_vci_tgt_fsm = TGT_IDLE;
+            break;
+        }
+
+        if ( p_vci_tgt.rspack.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+        {
+            // one response
+            if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
+            {
+                r_vci_tgt_fsm = TGT_IDLE; 
+                r_tgt_icache_rsp = false;
+                r_tgt_dcache_rsp = false;
+            }
+
+            // if data and instruction have the inval line, need two responses  
+            if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
+            {
+                r_tgt_icache_rsp = false; // only reset one for respond the second time 
+            }
+        }
+        break;
+    }
+    ////////////////////
+    case TGT_RSP_DCACHE:
+    {
+        if ( p_vci_tgt.rspack.read() && !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_IDLE;
+            r_tgt_dcache_rsp = false; 
+        }
+        break;
+    }
+    } // end switch TGT_FSM
+
+    ////////////////////////////////////////////////////////////////////////////////////////
+    //      ICACHE_FSM
+    //
+    // There is 9 mutually exclusive conditions to exit the IDLE state.
+    // Four configurations corresponding to an XTN request from processor,
+    // - Flush TLB (in case of Context switch) => TLB_FLUSH state 
+    // - Flush cache => CACHE_FLUSH state 
+    // - Invalidate a TLB entry => TLB_INVAL state
+    // - Invalidate a cache line => CACHE_INVAL state
+    // Five configurations corresponding to various TLB or cache MISS :
+    // - TLB miss(in case hit_p miss) => TLB1_READ state
+    // - TLB miss(in case hit_p hit) => TLB2_READ state
+    // - Hit in TLB but VPN changed => BIS state
+    // - Cached read miss => MISS_REQ state
+    // - Uncache read miss => UNC_REQ state
+    // 
+    // In case of MISS, the controller writes a request in the r_icache_paddr_save register 
+    // and sets the corresponding request flip-flop : r_dcache_itlb_read_req, r_icache_miss_req 
+    // or r_icache_unc_req. These request flip-flops are reset by the VCI_RSP controller 
+    // when the response is ready in the ICACHE buffer.
+    //
+    // The DCACHE FSM signals XTN processor requests using the r_dcache_xtn_req flip-flop. 
+    // The request opcod and the address to be invalidated are transmitted
+    // in the r_dcache_paddr_save & r_dcache_wdata_save registers respectively.
+    // The request flip-flop is reset by the ICACHE_FSM when the operation is completed.
+    //
+    // The r_vci_rsp_ins_error flip-flop is set by the VCI_RSP FSM and reset
+    // by the ICACHE-FSM in the ICACHE_ERROR state.
+    //
+    //----------------------------------------------------------------------------------- 
+    // Instruction TLB: 
+    //  
+    // - int        ET          (00: unmapped; 01: unused or PTD)
+    //                          (10: PTE new;  11: PTE old      )
+    // - bool       cachable    (cached bit)
+    // - bool       writable    (** not used alwayse false) 
+    // - bool       executable  (executable bit)
+    // - bool       user        (access in user mode allowed)
+    // - bool       global      (PTE not invalidated by a TLB flush)
+    // - bool       dirty       (** not used alwayse false) 
+    // - uint32_t   vpn         (virtual page number)
+    // - uint32_t   ppn         (physical page number)
+    ////////////////////////////////////////////////////////////////////////////////////////
+
+    switch(r_icache_fsm) {
+
+    ////////////////
+    case ICACHE_IDLE:
+    {
+        pte_info_t  icache_pte_info;
+        paddr_t     tlb_ipaddr       = 0;    	// physical address obtained from TLB                         
+        paddr_t     spc_ipaddr       = 0;    	// physical adress obtained from PPN_save (speculative)       
+        data_t      icache_ins       = 0;    	// read instruction
+        bool        icache_hit_c     = false;	// Cache hit
+        bool        icache_cached    = false;	// cacheable access (read)
+        bool        icache_hit_t     = false;	// hit on TLB
+        bool        icache_hit_x     = false;	// VPN unmodified (can use spc_dpaddr)
+        bool        icache_hit_p     = false;	// PTP unmodified (can skip first level page table walk)
+        size_t      icache_tlb_way   = 0;    	// selected way (in case of cache hit)
+        size_t      icache_tlb_set   = 0;    	// selected set (Y field in address)
+        paddr_t     icache_tlb_nline = 0;  	// TLB NLINE 
+
+        // Decoding processor XTN requests
+        // They are sent by DCACHE FSM  
+
+        if (r_dcache_xtn_req)
+        {
+            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+            
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_PTPR )  
+            {
+                r_icache_way = 0;
+                r_icache_set = 0;
+                r_icache_fsm = ICACHE_SW_FLUSH;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_ICACHE_FLUSH)
+            {
+                r_icache_way = 0;
+                r_icache_set = 0;
+                r_icache_fsm = ICACHE_CACHE_FLUSH;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_ITLB_INVAL) 
+            {
+                r_icache_fsm = ICACHE_TLB_INVAL;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_ICACHE_INVAL) 
+            {
+                r_icache_fsm = ICACHE_CACHE_INVAL;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_DCACHE_FLUSH )  
+            {
+                // special for ins tlb miss via data cache
+                r_icache_fsm = ICACHE_TLB_FLUSH;   
+                break;
+            }
+        } // end if xtn_req
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            break;
+        }
+
+        // icache_hit_t_m, icache_hit_t_k, icache_hit_x, icache_hit_p 
+        // icache_pte_info, icache_tlb_way, icache_tlb_set & ipaddr & cacheability 
+        // - If MMU activated : cacheability is defined by the cachable bit in the TLB
+        // - If MMU not activated : cacheability is defined by the segment table.
+
+        if ( !(r_mmu_mode.read() & INS_TLB_MASK) )   // MMU not activated 
+        {
+            icache_hit_t  = true;         
+            icache_hit_x  = true;         
+            icache_hit_p  = true;         
+            tlb_ipaddr    = ireq.addr;
+            spc_ipaddr    = ireq.addr;
+            icache_cached = m_cacheability_table[ireq.addr];
+        } 
+        else                                                                // MMU activated
+        { 
+            m_cpt_ins_tlb_read++;
+            icache_hit_t  = icache_tlb.cctranslate(ireq.addr, &tlb_ipaddr, &icache_pte_info, 
+                                                   &icache_tlb_nline, &icache_tlb_way, &icache_tlb_set); 
+            icache_hit_x  = (((vaddr_t)r_icache_vpn_save << PAGE_K_NBITS) == (ireq.addr & ~PAGE_K_MASK)) && r_itlb_translation_valid;
+            icache_hit_p  = (((ireq.addr >> PAGE_M_NBITS) == r_icache_id1_save) && r_icache_ptba_ok); 
+            spc_ipaddr    = ((paddr_t)r_icache_ppn_save << PAGE_K_NBITS) | (paddr_t)(ireq.addr & PAGE_K_MASK);
+            icache_cached = icache_pte_info.c; 
+        }
+
+        if ( !(r_mmu_mode.read() & INS_CACHE_MASK) )   // cache not actived
+        {
+            icache_cached = false;
+        }
+
+        if ( ireq.valid ) 
+        {
+            m_cpt_icache_dir_read += m_icache_ways;
+            m_cpt_icache_data_read += m_icache_ways;
+
+            // icache_hit_c & icache_ins
+            if ( icache_cached )    // using speculative physical address for cached access
+            {
+                icache_hit_c = r_icache.read(spc_ipaddr, &icache_ins);
+            }
+            else                    // using actual physical address for uncached access
+            {
+                icache_hit_c = ( r_icache_buf_unc_valid && (tlb_ipaddr == (paddr_t)r_icache_paddr_save) );
+                icache_ins = r_icache_miss_buf[0];
+            }
+
+            if ( r_mmu_mode.read() & INS_TLB_MASK ) 
+            {
+                if ( icache_hit_t ) 
+                {
+                    // check access rights
+                    if ( !icache_pte_info.u && (ireq.mode == iss_t::MODE_USER)) 
+                    {
+                        r_icache_error_type = MMU_READ_PRIVILEGE_VIOLATION;  
+                        r_icache_bad_vaddr = ireq.addr;
+                        irsp.valid = true;
+                        irsp.error = true;
+                        irsp.instruction = 0;
+                        break;
+                    }
+                    if ( !icache_pte_info.x ) 
+                    {
+                        r_icache_error_type = MMU_READ_EXEC_VIOLATION;  
+                        r_icache_bad_vaddr = ireq.addr;
+                        irsp.valid = true;
+                        irsp.error = true;
+                        irsp.instruction = 0;
+                        break;
+                    }
+                }
+
+                // update LRU, save ppn, vpn and page type
+                if ( icache_hit_t )
+                {  
+                    icache_tlb.setlru(icache_tlb_way,icache_tlb_set);     
+                    r_icache_ppn_save = tlb_ipaddr >> PAGE_K_NBITS;
+                    r_icache_vpn_save = ireq.addr >> PAGE_K_NBITS;
+                    r_icache_tlb_nline = icache_tlb_nline;
+                    r_itlb_translation_valid = true;
+                }
+                else
+                {
+                    r_itlb_translation_valid = false;
+                }
+
+            } // end if MMU activated
+
+            // compute next state 
+            if ( !icache_hit_t && !icache_hit_p )      // TLB miss
+            {
+                // walk page table  level 1
+                r_icache_paddr_save = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((ireq.addr>>PAGE_M_NBITS)<<2);
+                r_itlb_read_dcache_req = true;
+                r_icache_fsm = ICACHE_TLB1_READ;
+                m_cpt_ins_tlb_miss++;
+                m_cost_ins_tlb_miss_frz++;
+            }
+            else if ( !icache_hit_t && icache_hit_p )  // TLB Miss with possibility of bypass first level page
+            {
+                // walk page table level 2
+                r_icache_paddr_save = (paddr_t)r_icache_ptba_save | 
+                                      (paddr_t)(((ireq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                r_itlb_read_dcache_req = true;
+                r_icache_fsm = ICACHE_TLB2_READ;
+                m_cpt_ins_tlb_miss++;
+                m_cost_ins_tlb_miss_frz++;
+            }
+            else if ( icache_hit_t && !icache_hit_x && icache_cached ) // cached access with an ucorrect speculative physical address
+            {
+                r_icache_paddr_save = tlb_ipaddr;   // save actual physical address for BIS
+                r_icache_fsm = ICACHE_BIS;
+                m_cost_ins_miss_frz++;
+            }
+            else    // cached or uncached access with a correct speculative physical address 
+            {        
+                m_cpt_ins_read++; 
+                if ( !icache_hit_c ) 
+                {
+                    m_cpt_ins_miss++;
+                    m_cost_ins_miss_frz++;
+                    if ( icache_cached ) 
+                    {
+                        r_icache_miss_req = true;
+                    	r_icache_paddr_save = spc_ipaddr; 
+                        r_icache_fsm = ICACHE_MISS_WAIT;
+                    } 
+                    else 
+                    {
+                        r_icache_unc_req = true;
+                        r_icache_buf_unc_valid = false;
+                    	r_icache_paddr_save = tlb_ipaddr; 
+                        r_icache_fsm = ICACHE_UNC_WAIT;
+                    } 
+                } 
+                else 
+                {
+                    r_icache_buf_unc_valid = false;
+                    r_icache_fsm = ICACHE_IDLE;
+                }
+                irsp.valid = icache_hit_c;
+                irsp.instruction = icache_ins;
+            } // end if next states
+            
+        } // end if ireq.valid
+        break;
+    }
+    ////////////////
+    case ICACHE_BIS: 
+    {
+        m_cost_ins_miss_frz++;
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+      
+        // using page is invalidated 
+        if ( r_icache_inval_tlb_rsp )
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+            m_cost_ins_tlb_miss_frz++;
+            break;
+        }
+ 
+        data_t  icache_ins = 0;
+        bool    icache_hit = false;
+
+        // acces is always cached in this state
+        icache_hit = r_icache.read(r_icache_paddr_save, &icache_ins);
+
+        m_cpt_ins_read++;
+        if ( !icache_hit )
+        {
+            r_icache_miss_req = true;
+            r_icache_fsm = ICACHE_MISS_WAIT;
+            m_cpt_ins_miss++;
+        } 
+        else
+        {
+            r_icache_fsm = ICACHE_IDLE; 
+        }
+
+        irsp.valid = icache_hit;
+        irsp.error = false;
+        irsp.instruction = icache_ins;
+        break;
+    }
+    //////////////////////
+    case ICACHE_TLB1_READ:
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( !r_itlb_read_dcache_req && !r_icache_inval_tlb_rsp ) // TLB miss read response and no invalidation
+        {
+            if ( !r_dcache_rsp_itlb_error ) // vci response ok
+            {  
+		if ( !(r_dcache_rsp_itlb_miss >> PTE_V_SHIFT) ) // unmapped
+		{
+            	    r_icache_ptba_ok    = false;	
+                    r_icache_error_type = MMU_READ_PT1_UNMAPPED;  
+                    r_icache_bad_vaddr  = ireq.addr;
+                    r_icache_fsm        = ICACHE_ERROR;
+		}
+		else if ( (r_dcache_rsp_itlb_miss & PTE_T_MASK ) >> PTE_T_SHIFT ) // PTD
+		{
+            	    r_icache_ptba_ok       = true;	
+                    r_icache_ptba_save     = (paddr_t)(r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS; 
+                    r_icache_id1_save      = ireq.addr >> PAGE_M_NBITS;
+                    r_icache_paddr_save    = (paddr_t)(r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
+                                             (paddr_t)(((ireq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3); 
+                    r_itlb_read_dcache_req = true;
+                    r_icache_fsm           = ICACHE_TLB2_READ;
+		}	
+		else
+		{
+            	    r_icache_ptba_ok = false;
+	
+		    if ( (m_srcid_rw >> 4) == ((r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		    {
+			if ( (r_dcache_rsp_itlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+			{
+                            r_icache_pte_update = r_dcache_rsp_itlb_miss;
+                            r_icache_fsm        = ICACHE_TLB1_UPDT;
+			}
+			else
+			{
+                            r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_L_MASK;
+                            r_itlb_acc_dcache_req = true;
+                            r_icache_fsm          = ICACHE_TLB1_WRITE;
+                            m_cpt_ins_tlb_write_et++;
+			}
+    	            }
+		    else // remotely
+		    {
+			if ( (r_dcache_rsp_itlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+			{
+                            r_icache_pte_update = r_dcache_rsp_itlb_miss;
+                            r_icache_fsm        = ICACHE_TLB1_UPDT;
+			}
+			else
+			{
+                            r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_R_MASK;
+                            r_itlb_acc_dcache_req = true;
+                            r_icache_fsm          = ICACHE_TLB1_WRITE;
+                            m_cpt_ins_tlb_write_et++;
+			}
+		    }
+		}
+            }
+            else                        // vci response error
+            {  
+                r_icache_fsm = ICACHE_ERROR;
+                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;    
+                r_icache_bad_vaddr = ireq.addr;
+            }
+        }
+
+        if ( !r_itlb_read_dcache_req && r_icache_inval_tlb_rsp ) // TLB miss read response and invalidation
+        {
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;    
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;  
+            } 
+        }
+        break;
+    }
+    ///////////////////////
+    case ICACHE_TLB1_WRITE:  
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if (!r_itlb_acc_dcache_req && !r_icache_inval_tlb_rsp ) // TLB access bits write response and no invalidation        
+        { 
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;  
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else  
+            {
+                r_icache_fsm = ICACHE_TLB1_UPDT;  
+            }
+        } 
+
+        if (!r_itlb_acc_dcache_req && r_icache_inval_tlb_rsp) // TLB ET write response and invalidation     
+        {   
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;  
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else  
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;    
+            }
+        }
+        break;
+    }
+    //////////////////////
+    case ICACHE_TLB1_UPDT:
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req ) 
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // TLB update and invalidate different PTE
+        if ( !r_dcache_itlb_cleanup_req && !r_icache_inval_tlb_rsp )  
+        {
+            paddr_t victim_index = 0;
+            r_dcache_itlb_cleanup_req = icache_tlb.update(r_icache_pte_update,ireq.addr,(r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index);
+            r_dcache_itlb_cleanup_line = victim_index;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+
+        // TLB update and invalidate same PTE
+        if ( r_icache_inval_tlb_rsp )                                 
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB2_READ:
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( !r_itlb_read_dcache_req && !r_icache_inval_tlb_rsp ) // TLB miss read response 
+        {
+            if ( !r_dcache_rsp_itlb_error ) // VCI response ok        
+            {
+		if ( !(r_dcache_rsp_itlb_miss >> PTE_V_SHIFT) ) // unmapped
+		{
+                    r_icache_error_type = MMU_READ_PT2_UNMAPPED;  
+                    r_icache_bad_vaddr  = ireq.addr;
+                    r_icache_fsm = ICACHE_ERROR;
+		}
+		else
+		{
+		    if ( (m_srcid_rw >> 4) == ((r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		    {
+			if ( (r_dcache_rsp_itlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+			{
+                    	    r_icache_fsm        = ICACHE_TLB2_UPDT;
+                    	    r_icache_pte_update = r_dcache_rsp_itlb_miss;
+			}
+			else
+			{
+                    	    r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_L_MASK;
+                    	    r_itlb_acc_dcache_req = true;
+                    	    r_icache_fsm          = ICACHE_TLB2_WRITE;
+                     	    m_cpt_ins_tlb_write_et++;
+			}
+    	            }
+		    else // remotely
+		    {
+			if ( (r_dcache_rsp_itlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+			{
+                    	    r_icache_fsm        = ICACHE_TLB2_UPDT;
+                    	    r_icache_pte_update = r_dcache_rsp_itlb_miss;
+			}
+			else
+			{
+                    	    r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_R_MASK;
+                    	    r_itlb_acc_dcache_req = true;
+                    	    r_icache_fsm          = ICACHE_TLB2_WRITE;
+                    	    m_cpt_ins_tlb_write_et++;
+			}
+		    }
+		}
+            }
+            else                            // VCI response error        
+            {
+                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            }
+        }
+
+        if ( !r_itlb_read_dcache_req && r_icache_inval_tlb_rsp ) // TLB miss read response and invalidation
+        {
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;    
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;  
+            } 
+        }
+        break;
+    }
+    /////////////////////////
+    case ICACHE_TLB2_WRITE:
+    {  
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if (!r_itlb_acc_dcache_req && !r_icache_inval_tlb_rsp ) // TLB access bits write response          
+        {
+            if ( r_dcache_rsp_itlb_error )             
+            {
+                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;  
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else  
+            {
+                r_icache_fsm = ICACHE_TLB2_UPDT;  
+            }
+        } 
+        if (!r_itlb_acc_dcache_req && r_icache_inval_tlb_rsp) // TLB ET write response and invalidation     
+        {   
+            if ( r_dcache_rsp_itlb_error ) 
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;  
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+            } 
+            else  
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;    
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB2_UPDT: 
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req ) 
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // TLB update and invalidate different PTE
+        if ( !r_dcache_itlb_cleanup_req && !r_icache_inval_tlb_rsp ) 
+        {
+            paddr_t victim_index = 0;
+            r_dcache_itlb_cleanup_req = icache_tlb.update(r_icache_pte_update,r_dcache_rsp_itlb_ppn,ireq.addr,(r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index);
+            r_dcache_itlb_cleanup_line = victim_index;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        // TLB update and invalidate same PTE
+        if ( r_icache_inval_tlb_rsp )                            
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    /////////////////////////////
+    case ICACHE_SW_FLUSH:
+    {
+        size_t way = r_icache_way;
+        size_t set = r_icache_set;
+        bool clean = false;
+
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+        m_cost_ins_tlb_sw_frz++;
+
+        // 4K page size TLB flush leads to cleanup req to data cache 
+        if ( !r_dcache_itlb_cleanup_req )    // last cleanup finish
+        {
+            paddr_t victim_index = 0;
+            for ( ; way < m_itlb_ways; way++)
+            {
+                for ( ; set < m_itlb_sets; set++)
+                {
+                    if(icache_tlb.checkcleanup(way, set, &victim_index))
+                    {
+                        clean = true;
+                        r_dcache_itlb_cleanup_req = true;
+                        r_dcache_itlb_cleanup_line = victim_index;
+                        r_icache_way = way + ((set+1)/m_itlb_sets);
+                        r_icache_set = (set+1) % m_itlb_sets;
+                        break;
+                    }
+                }
+                if (clean) break;
+            }
+
+            if ((way == m_itlb_ways) && (set == m_itlb_sets))
+            {
+                r_dcache_xtn_req = false;
+                r_icache_fsm = ICACHE_IDLE;
+                break;
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB_FLUSH:
+    {   
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+
+        // data cache flush leads to ins tlb flush, flush all tlb entry 
+        icache_tlb.flush(true);    // global entries are invalidated
+        r_dcache_xtn_req = false;
+        r_icache_fsm = ICACHE_IDLE;
+        break;
+    }
+    ////////////////////////
+    case ICACHE_CACHE_FLUSH:
+    {
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_tgt_icache_req = false;
+        }
+
+        size_t way = r_icache_way;
+        size_t set = r_icache_set;
+        bool clean = false;
+
+        m_cost_ins_cache_flush_frz++;
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+
+        // cache flush and send cleanup to external
+        if ( !r_icache_cleanup_req )
+        {
+            paddr_t victim_index = 0;
+            for ( ; way < m_icache_ways; way++ )
+            {    
+                for ( ; set < m_icache_sets; set++ )
+                {    
+                    if ( r_icache.flush(way, set, &victim_index) )
+                    {
+                        clean = true;
+                        r_icache_cleanup_req = true;
+                        r_icache_cleanup_line = victim_index;
+                        r_icache_way = way + ((set+1)/m_icache_sets);
+                        r_icache_set = (set+1) % m_icache_sets;
+                        break;
+                    }
+                }
+                if (clean) break;
+            }
+            if ((way == m_icache_ways) && (set == m_icache_sets))
+            {
+                r_dcache_xtn_req = false;
+                r_icache_fsm = ICACHE_IDLE;
+                break;
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB_INVAL:  
+    {
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+        paddr_t victim_index = 0;
+
+        if ( !r_dcache_itlb_cleanup_req )
+        {
+            r_dcache_itlb_cleanup_req = icache_tlb.inval(r_dcache_wdata_save, &victim_index);
+            r_dcache_itlb_cleanup_line = victim_index;
+            r_dcache_xtn_req = false;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    ////////////////////////
+    case ICACHE_CACHE_INVAL:
+    {	
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+
+        paddr_t ipaddr = 0;                     
+        bool    icache_hit_t = false;
+
+        if ( !r_icache_cleanup_req )
+        {    
+            if ( r_mmu_mode.read() & INS_TLB_MASK ) 
+            {
+                icache_hit_t = icache_tlb.translate(r_dcache_wdata_save, &ipaddr); 
+            } 
+            else 
+            {
+                ipaddr = (paddr_t)r_dcache_wdata_save;
+                icache_hit_t = true;
+            }
+            if ( icache_hit_t )
+            {
+                // invalidate and cleanup if necessary
+                r_icache_cleanup_req = r_icache.inval(ipaddr);
+                r_icache_cleanup_line = ipaddr >> (uint32_log2(m_icache_words) + 2);   
+            }
+            r_dcache_xtn_req = false; 
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    ///////////////////////
+    case ICACHE_MISS_WAIT:
+    {
+        m_cost_ins_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )     
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+       
+	if ( !r_icache_miss_req )
+	{
+	    if ( r_vci_rsp_ins_error ) 
+            {
+                r_icache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+
+            	if ( r_icache_inval_tlb_rsp ) r_icache_inval_tlb_rsp = false;
+            	if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
+		break;
+            }
+
+            if ( r_icache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_icache_fsm = ICACHE_IDLE;
+                r_icache_inval_tlb_rsp = false;
+                m_cost_ins_tlb_miss_frz++;
+                break;
+            }
+	
+            if ( r_icache_inval_rsp ) // Miss read response and tlb invalidation
+            {
+                r_icache_fsm = ICACHE_IDLE;
+                r_icache_inval_rsp = false;
+                break;
+            }
+            r_icache_fsm = ICACHE_MISS_UPDT;  
+	}	
+        break;
+    }
+    ////////////////////
+    case ICACHE_UNC_WAIT:
+    {
+        m_cost_ins_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req ) 
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_icache_unc_req )
+	{
+	    if ( r_vci_rsp_ins_error ) 
+            {
+                r_icache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS;    
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+
+            	if ( r_icache_inval_tlb_rsp ) r_icache_inval_tlb_rsp = false;
+            	//if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
+		break;
+            }
+
+	    if ( r_icache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;
+		break;
+            }
+/*	    
+	    if ( r_icache_inval_rsp ) // Miss read response and cache invalidation
+            {
+                r_icache_inval_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;
+		break;
+            }
+*/
+	    // Miss read response and no invalidation
+            r_icache_buf_unc_valid = true;
+            r_icache_fsm = ICACHE_IDLE;
+	}	
+        break;
+    }
+    //////////////////////
+    case ICACHE_MISS_UPDT:
+    {
+        m_cost_ins_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )   
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( r_icache_inval_tlb_rsp ) // tlb invalidation
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+            m_cost_ins_tlb_miss_frz++;
+            break;
+        }
+
+        if ( r_icache_inval_rsp ) // invalidation
+        {
+            r_icache_inval_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+            break;
+        } 
+
+        if ( !r_icache_cleanup_req ) // Miss update and no invalidation
+        {
+            data_t* buf = r_icache_miss_buf;
+            paddr_t  victim_index = 0;
+            m_cpt_icache_dir_write++;
+            m_cpt_icache_data_write++;
+
+            r_icache_cleanup_req = r_icache.update(r_icache_paddr_save.read(), buf, &victim_index);
+            r_icache_cleanup_line = victim_index;            
+
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    ///////////////////
+    case ICACHE_ERROR:
+    {
+        r_vci_rsp_ins_error = false;
+        r_dcache_rsp_itlb_error = false;
+        irsp.valid = true;
+        irsp.error = true;
+        irsp.instruction = 0; 
+        r_icache_fsm = ICACHE_IDLE;
+        break;
+    }
+    /////////////////////
+    case ICACHE_CC_INVAL:  
+    {                       
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+        m_cpt_icache_dir_read += m_icache_ways;
+
+        // invalidate cache
+        if( (( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT ) /*|| 
+             ( r_icache_fsm_save == ICACHE_UNC_WAIT )*/ ) && 
+            ((r_icache_paddr_save.read() & ~((m_icache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_icache_words<<2)-1))) ) 
+        {
+            r_icache_inval_rsp = true;
+        } 
+        else 
+        {
+            r_tgt_icache_rsp = r_icache.inval(r_tgt_addr.read());
+        }
+        r_tgt_icache_req = false;
+        r_icache_fsm = r_icache_fsm_save;
+        break;
+    }
+    /////////////////////////
+    case ICACHE_TLB_CC_INVAL:
+    {
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;        
+
+	if ( r_itlb_inval_req ) break;
+
+        // invalidate cache
+        if( (( r_icache_fsm_save == ICACHE_TLB1_READ ) || ( r_icache_fsm_save == ICACHE_TLB2_READ )  ||
+             ( r_icache_fsm_save == ICACHE_TLB1_WRITE )|| ( r_icache_fsm_save == ICACHE_TLB2_WRITE ) ||
+             ( r_icache_fsm_save == ICACHE_TLB1_UPDT ) || ( r_icache_fsm_save == ICACHE_TLB2_UPDT )) && 
+            (((r_icache_paddr_save.read() & ~((m_icache_words<<2)-1)) >> (uint32_log2(m_icache_words) + 2) ) == r_dcache_itlb_inval_line.read()) ) 
+        {
+            r_icache_inval_tlb_rsp = true;
+        } 
+        else if (((r_icache_fsm_save == ICACHE_BIS)||(r_icache_fsm_save == ICACHE_MISS_WAIT) ||
+                 (r_icache_fsm_save == ICACHE_UNC_WAIT)||(r_icache_fsm_save == ICACHE_MISS_UPDT)) && 
+                (r_icache_tlb_nline == r_dcache_itlb_inval_line))
+        {
+            r_icache_inval_tlb_rsp = true;
+        }
+	r_dcache_itlb_inval_req = false;
+        r_icache_fsm = r_icache_fsm_save;
+        break;
+    }
+    } // end switch r_icache_fsm
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout << name() << " Instruction Response: " << irsp << std::endl;
+#endif
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //      INVAL ITLB CHECK FSM 
+    ////////////////////////////////////////////////////////////////////////////////////////
+    switch(r_inval_itlb_fsm) {
+    /////////////////////
+    case INVAL_ITLB_IDLE:
+    {
+        if ( r_itlb_inval_req )
+        {
+            r_ccinval_itlb_way = 0; 
+            r_ccinval_itlb_set = 0;
+            r_inval_itlb_fsm = INVAL_ITLB_CHECK;   
+            m_cost_ins_tlb_inval_frz++; 
+        }   
+        break;
+    }
+    ////////////////////////////
+    case INVAL_ITLB_CHECK:
+    {
+        m_cost_ins_tlb_inval_frz++; 
+
+        size_t way = r_ccinval_itlb_way; 
+        size_t set = r_ccinval_itlb_set;
+        bool end = false;        
+        bool tlb_hit = icache_tlb.cccheck(r_dcache_itlb_inval_line.read(), way, set, &way, &set, &end); 
+    
+        if ( tlb_hit )
+        {
+            r_ccinval_itlb_way = way; 
+            r_ccinval_itlb_set = set;
+            r_itlb_cc_check_end = end;
+            r_inval_itlb_fsm = INVAL_ITLB_INVAL; 
+            m_cpt_ins_tlb_inval++;   
+        }        
+        else
+        {
+            r_inval_itlb_fsm = INVAL_ITLB_CLEAR;    
+        }
+        break;
+    }
+    /////////////////////////
+    case INVAL_ITLB_INVAL:
+    {
+        m_cost_ins_tlb_inval_frz++;
+ 
+        icache_tlb.ccinval(r_ccinval_itlb_way, r_ccinval_itlb_set);
+
+        if ( !r_itlb_cc_check_end )
+        {
+            r_inval_itlb_fsm = INVAL_ITLB_CHECK; 
+        }
+        else
+        {
+            r_inval_itlb_fsm = INVAL_ITLB_CLEAR;    
+        }
+        break;
+    }
+    ////////////////////
+    case INVAL_ITLB_CLEAR:
+    {
+        r_itlb_inval_req = false;
+        r_itlb_cc_check_end = false;
+        r_ccinval_itlb_way = 0; 
+        r_ccinval_itlb_set = 0; 
+        r_inval_itlb_fsm = INVAL_ITLB_IDLE;    
+        m_cost_ins_tlb_inval_frz++; 
+        break;
+    }
+    } // end switch r_inval_itlb_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //      DCACHE FSM 
+    //
+    // Both the Cacheability Table, and the MMU cached bit are used to define
+    // the cacheability.
+    // 
+    // There is 14 mutually exclusive conditions to exit the IDLE state.
+    // Seven configurations corresponding to an XTN request from processor:
+    // - Context switch => CTXT_SWITCH state
+    // - Flush dcache => DCACHE_FLUSH state 
+    // - Flush icache => ICACHE_FLUSH state 
+    // - Invalidate a dtlb entry => DTLB_INVAL state
+    // - Invalidate a itlb entry => ITLB_INVAL state
+    // - Invalidate a dcache line => DCACHE_INVAL state
+    // - Invalidate a icache line => ICACHE_INVAL state
+    // Seven configurations corresponding to various read miss or write requests: 
+    // - TLB miss(in case hit_p miss) => TLB1_READ state
+    // - TLB miss(in case hit_p hit) => TLB2_READ state
+    // - Hit in TLB but VPN changed => BIS state
+    // - Cached read miss => MISS_REQ state
+    // - Uncache read miss => UNC_REQ state
+    // - Write hit => WRITE_UPDT state
+    // - Write miss => WRITE_REQ
+    //
+    // The r_vci_rsp_data_error flip-flop is set by the VCI_RSP controller and reset 
+    // by DCACHE-FSM when its state is in DCACHE_ERROR. 
+    //--------------------------------------------------------------------- 
+    // Data TLB: 
+    //  
+    // - int        ET          (00: unmapped; 01: unused or PTD)
+    //                          (10: PTE new;  11: PTE old      )
+    // - bool       cachable    (cached bit)
+    // - bool       writable    (writable bit) 
+    // - bool       executable  (** not used alwayse false)
+    // - bool       user        (access in user mode allowed)
+    // - bool       global      (PTE not invalidated by a TLB flush)
+    // - bool       dirty       (page has been modified) 
+    // - uint32_t   vpn         (virtual page number)
+    // - uint32_t   ppn         (physical page number)
+    ////////////////////////////////////////////////////////////////////////////////////////
+
+    switch (r_dcache_fsm) {
+    //////////////////////
+    case DCACHE_WRITE_REQ:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++; 
+            break;
+        }
+
+        // try to post the write request in the write buffer
+        if ( !r_dcache_write_req )     // no previous write transaction     
+        {
+            if ( r_wbuf.wok(r_dcache_paddr_save) )   // write request in the same cache line 
+            {    
+                r_wbuf.write(r_dcache_paddr_save.read(), r_dcache_be_save.read(), r_dcache_wdata_save);
+                // closing the write packet if uncached
+                if ( !r_dcache_cached_save )
+                { 
+                    r_dcache_write_req = true;
+                }
+            } 
+            else 
+            {    // close the write packet if write request not in the same cache line
+                r_dcache_write_req = true;
+                m_cost_write_frz++;
+                break;  //  posting not possible : stay in DCACHE_WRITEREQ state
+            }
+        } 
+        else     //  previous write transaction not completed
+        {
+            m_cost_write_frz++;
+            break;  //  posting not possible : stay in DCACHE_WRITEREQ state
+        }
+
+        // close the write packet if the next processor request is not a write 
+        if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE)) 
+        {
+            r_dcache_write_req = true;
+        }
+        
+        // The next state and the processor request parameters are computed 
+        // as in the DCACHE_IDLE state (see below ...)
+    }
+    /////////////////
+    case DCACHE_IDLE:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = DCACHE_IDLE;
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // ins tlb cleanup
+        if ( r_dcache_itlb_cleanup_req )
+        {
+            r_dcache_fsm = DCACHE_ITLB_CLEANUP;
+            m_cpt_ins_tlb_cleanup++;
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+            break;
+        }    
+        // ins tlb miss
+    	if ( r_itlb_read_dcache_req )
+    	{
+            data_t rsp_itlb_miss;
+	    data_t rsp_itlb_ppn;
+
+    	    bool itlb_hit_dcache = r_dcache.read(r_icache_paddr_save, &rsp_itlb_miss);
+	    if ( (r_icache_fsm == ICACHE_TLB2_READ) && itlb_hit_dcache )
+	    {	
+	        bool itlb_hit_ppn = r_dcache.read(r_icache_paddr_save.read()+4, &rsp_itlb_ppn);
+		assert(itlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+	    }
+
+            m_cpt_dcache_data_read += m_dcache_ways;
+            m_cpt_dcache_dir_read += m_dcache_ways;
+
+    	    if ( itlb_hit_dcache )  // ins TLB request hits in data cache 
+    	    {
+                r_dcache_rsp_itlb_miss = rsp_itlb_miss; 
+                r_dcache_rsp_itlb_ppn = rsp_itlb_ppn; 
+    	    	r_itlb_read_dcache_req = false;
+                r_dcache_fsm = DCACHE_IDLE;
+                
+                // set TLB bit if it's a PTE
+                if ( !((rsp_itlb_miss & PTE_T_MASK ) >> PTE_T_SHIFT) )
+                {
+                    r_dcache.setinbit(r_icache_paddr_save, r_dcache_in_itlb, true);
+                }
+    	    }
+    	    else                    // ins TLB request miss in data cache
+    	    {
+                r_dcache_itlb_read_req = true;
+                r_dcache_fsm = DCACHE_ITLB_READ;
+            }
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++; 
+    	}
+    	else if ( r_itlb_acc_dcache_req ) // ins tlb write access bit
+    	{
+            bool write_hit = r_dcache.write(r_icache_paddr_save, r_icache_pte_update);
+            assert(write_hit && "Write on miss ignores data");
+            r_dcache_itlb_ll_acc_req = true;
+	    r_dcache_fsm = DCACHE_ITLB_LL_WAIT;	    		
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++; 
+    	}
+        else if (dreq.valid) 
+        {
+            pte_info_t  dcache_pte_info;
+            int         xtn_opcod        = (int)dreq.addr/4;
+            paddr_t     tlb_dpaddr       = 0;        // physical address obtained from TLB
+            paddr_t     spc_dpaddr       = 0;        // physical adress obtained from PPN_save (speculative)
+            bool        dcache_hit_t     = false;    // hit on 4Kilo TLB
+            bool        dcache_hit_x     = false;    // VPN unmodified (can use spc_dpaddr)
+            bool        dcache_hit_p     = false;    // PTP unmodified (can skip first level page table walk)
+            bool        dcache_hit_c     = false;    // Cache hit
+            bool        dcache_cached    = false;    // cacheable access (read or write)
+            size_t      dcache_tlb_way   = 0;        // selected way (in case of cache hit)
+            size_t      dcache_tlb_set   = 0;        // selected set (Y field in address)
+            data_t      dcache_rdata     = 0;        // read data
+            paddr_t     dcache_tlb_nline = 0;       // TLB NLINE 
+	    bool 	write_hit	 = false;
+
+            m_cpt_dcache_data_read += m_dcache_ways;
+            m_cpt_dcache_dir_read += m_dcache_ways;
+
+            // Decoding READ XTN requests from processor
+            // They are executed in this DCACHE_IDLE state
+
+            if (dreq.type == iss_t::XTN_READ) 
+            {
+                switch(xtn_opcod) {
+                case iss_t::XTN_INS_ERROR_TYPE:
+                    drsp.rdata = (uint32_t)r_icache_error_type;
+                    r_icache_error_type = MMU_NONE;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_DATA_ERROR_TYPE:
+                    drsp.rdata = (uint32_t)r_dcache_error_type;
+                    r_dcache_error_type = MMU_NONE;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_INS_BAD_VADDR:
+                    drsp.rdata = (uint32_t)r_icache_bad_vaddr;       
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_DATA_BAD_VADDR:
+                    drsp.rdata = (uint32_t)r_dcache_bad_vaddr;        
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_PTPR:
+                    drsp.rdata = (uint32_t)r_mmu_ptpr;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_TLB_MODE:
+                    drsp.rdata = (uint32_t)r_mmu_mode;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                default:
+                    r_dcache_error_type = MMU_READ_UNDEFINED_XTN; 
+                    r_dcache_bad_vaddr  = dreq.addr;
+                    drsp.valid = true;
+                    drsp.error = true;
+                    break;
+                }
+                r_dcache_fsm = DCACHE_IDLE;
+                break;
+            }
+
+            // Decoding WRITE XTN requests from processor
+            // If there is no privilege violation, they are not executed in this DCACHE_IDLE state,
+            // but in the next state, because they generally require access to the caches or the TLBs 
+
+            if (dreq.type == iss_t::XTN_WRITE) 
+            {
+                drsp.valid = false;
+                drsp.error = false;
+                drsp.rdata = 0;
+                r_dcache_wdata_save = dreq.wdata;   
+                switch(xtn_opcod) {     
+
+                case iss_t::XTN_PTPR:       // context switch : checking the kernel mode
+                                            // both instruction & data TLBs must be flushed
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_mmu_ptpr = dreq.wdata;
+                        r_icache_error_type = MMU_NONE;
+                        r_dcache_error_type = MMU_NONE;
+                        r_dcache_type_save = dreq.addr/4; 
+                        r_dcache_xtn_req = true;
+                        r_dcache_fsm = DCACHE_CTXT_SWITCH;
+                    } 
+                    else 
+                    { 
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                	r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+
+                case iss_t::XTN_TLB_MODE:     // modifying TLBs mode : checking the kernel mode
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_mmu_mode = (int)dreq.wdata;
+                        drsp.valid = true;
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                    }
+                    r_dcache_fsm = DCACHE_IDLE;
+                    break;
+
+                case iss_t::XTN_DTLB_INVAL:     //  checking the kernel mode
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_dcache_fsm = DCACHE_DTLB_INVAL;  
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                	r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+
+                case iss_t::XTN_ITLB_INVAL:     //  checking the kernel mode
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_dcache_xtn_req = true;
+                        r_dcache_type_save = dreq.addr/4;
+                        r_dcache_fsm = DCACHE_ITLB_INVAL;  
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                	r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+
+                case iss_t::XTN_DCACHE_INVAL:   // cache inval can be executed in user mode.
+                    r_dcache_fsm = DCACHE_DCACHE_INVAL;
+                    break;
+
+                case iss_t::XTN_DCACHE_FLUSH:   // cache flush can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true;
+                    r_dcache_way = 0;
+                    r_dcache_set = 0;
+                    r_dcache_fsm = DCACHE_DCACHE_FLUSH; 
+                    break;
+
+                case iss_t::XTN_ICACHE_INVAL:   // cache inval can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true;
+                    r_dcache_fsm = DCACHE_ICACHE_INVAL; 
+                    break;
+
+                case iss_t::XTN_ICACHE_FLUSH:   // cache flush can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true; 
+                    r_dcache_fsm = DCACHE_ICACHE_FLUSH;
+                    break;
+
+                case iss_t::XTN_SYNC:           // cache synchronization can be executed in user mode.
+                    if (r_wbuf.rok())
+                    {
+                        r_dcache_fsm = DCACHE_DCACHE_SYNC; 
+                    }
+                    else
+                    {
+                        drsp.valid = true;
+                        r_dcache_fsm = DCACHE_IDLE;
+                    }
+		    break;
+
+                default:
+                    r_dcache_error_type = MMU_WRITE_UNDEFINED_XTN; 
+                    r_dcache_bad_vaddr  = dreq.addr;
+                    drsp.valid = true;
+                    drsp.error = true;
+                    r_dcache_fsm = DCACHE_IDLE;
+                    break;
+                } // end switch xtn_opcod
+
+                break;
+            } // end if XTN_WRITE
+
+            // Evaluating dcache_hit_t, dcache_hit_x, dcache_hit_p, dcache_hit_c,
+            // dcache_pte_info, dcache_tlb_way, dcache_tlb_set & dpaddr & cacheability 
+            // - If MMU activated : cacheability is defined by the cachable bit in the TLB
+            // - If MMU not activated : cacheability is defined by the segment table.
+
+            if ( !(r_mmu_mode.read() & DATA_TLB_MASK) ) // MMU not activated
+            {
+                dcache_hit_t  = true;       
+                dcache_hit_x  = true;   
+                dcache_hit_p  = true;  
+                tlb_dpaddr    = dreq.addr; 
+                spc_dpaddr    = dreq.addr;    
+                dcache_cached = m_cacheability_table[dreq.addr] && 
+                                ((dreq.type != iss_t::DATA_LL)  && (dreq.type != iss_t::DATA_SC) &&
+                                 (dreq.type != iss_t::XTN_READ) && (dreq.type != iss_t::XTN_WRITE));     
+            } 
+            else                                                            // MMU activated
+            {
+                m_cpt_data_tlb_read++;
+                dcache_hit_t  = dcache_tlb.cctranslate(dreq.addr, &tlb_dpaddr, &dcache_pte_info, 
+                                                       &dcache_tlb_nline, &dcache_tlb_way, &dcache_tlb_set);                  
+                dcache_hit_x  = (((vaddr_t)r_dcache_vpn_save << PAGE_K_NBITS) == (dreq.addr & ~PAGE_K_MASK)) && r_dtlb_translation_valid; 
+                dcache_hit_p  = (((dreq.addr >> PAGE_M_NBITS) == r_dcache_id1_save) && r_dcache_ptba_ok );
+                spc_dpaddr    = ((paddr_t)r_dcache_ppn_save << PAGE_K_NBITS) | (paddr_t)((dreq.addr & PAGE_K_MASK));
+                dcache_cached = dcache_pte_info.c && 
+                                ((dreq.type != iss_t::DATA_LL)  && (dreq.type != iss_t::DATA_SC) &&
+                                 (dreq.type != iss_t::XTN_READ) && (dreq.type != iss_t::XTN_WRITE));    
+            }
+
+            if ( !(r_mmu_mode.read() & DATA_CACHE_MASK) )   // cache not actived
+            {
+                dcache_cached = false;
+            }
+
+            // dcache_hit_c & dcache_rdata
+            if ( dcache_cached )    // using speculative physical address for cached access
+            {
+                dcache_hit_c = r_dcache.read(spc_dpaddr, &dcache_rdata);
+            } 
+            else                    // using actual physical address for uncached access
+            {
+                dcache_hit_c = ((tlb_dpaddr == (paddr_t)r_dcache_paddr_save) && r_dcache_buf_unc_valid ); 
+                dcache_rdata = r_dcache_miss_buf[0];
+            }
+
+            if ( r_mmu_mode.read() & DATA_TLB_MASK ) 
+            {
+                // Checking access rights
+                if ( dcache_hit_t ) 
+                {
+                    if (!dcache_pte_info.u && (dreq.mode == iss_t::MODE_USER)) 
+                    {
+                        if ((dreq.type == iss_t::DATA_READ)||(dreq.type == iss_t::DATA_LL))
+                        {
+                            r_dcache_error_type = MMU_READ_PRIVILEGE_VIOLATION;
+                        }
+                        else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                        {
+                            r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION;
+                        }  
+                        r_dcache_bad_vaddr = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                        drsp.rdata = 0;
+                        r_dcache_fsm = DCACHE_IDLE;
+                        break;
+                    }
+                    if (!dcache_pte_info.w && ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))) 
+                    {
+                        r_dcache_error_type = MMU_WRITE_ACCES_VIOLATION;  
+                        r_dcache_bad_vaddr = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                        drsp.rdata = 0;
+                        r_dcache_fsm = DCACHE_IDLE;
+                        break;
+                    }
+                }
+
+                // update LRU, save ppn, vpn and page type
+                if ( dcache_hit_t ) {
+                    dcache_tlb.setlru(dcache_tlb_way,dcache_tlb_set); 
+                    r_dcache_ppn_save = tlb_dpaddr >> PAGE_K_NBITS;
+                    r_dcache_vpn_save = dreq.addr >> PAGE_K_NBITS;
+                    r_dcache_tlb_nline = dcache_tlb_nline;
+                    r_dtlb_translation_valid = true;
+                }
+                else
+                {
+                    r_dtlb_translation_valid = false;
+                }
+
+            } // end if MMU activated
+
+            // compute next state 
+            if ( !dcache_hit_p && !dcache_hit_t )  // TLB miss
+            {
+                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                m_cpt_data_tlb_miss++;
+                m_cost_data_tlb_miss_frz++;
+            }
+            else if ( dcache_hit_p && !dcache_hit_t )  // TLB Miss with possibility of bypass first level page
+            {
+                // walk page table level 2
+                r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save | 
+                                     (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3); 
+                r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
+                m_cpt_data_tlb_miss++;
+                m_cost_data_tlb_miss_frz++;
+            }
+            else if ( dcache_hit_t && !dcache_hit_x && dcache_cached )// cached access with an ucorrect speculative physical address
+            {
+                r_dcache_hit_p_save = dcache_hit_p;
+                r_dcache_fsm = DCACHE_BIS;
+                m_cost_data_miss_frz++;
+            }
+            else  // cached or uncached access with a correct speculative physical address
+            {
+                switch( dreq.type ) {
+                    case iss_t::DATA_READ:
+                    case iss_t::DATA_LL:
+                    case iss_t::DATA_SC:
+                        m_cpt_read++;
+                        if ( dcache_hit_c ) 
+                        {
+                            r_dcache_buf_unc_valid = false;
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+                        } 
+                        else 
+                        {
+                            if ( dcache_cached ) 
+                            {
+                                r_dcache_miss_req = true;
+                                r_dcache_fsm = DCACHE_MISS_WAIT;
+                                m_cpt_data_miss++;
+                                m_cost_data_miss_frz++;
+                            } 
+                            else 
+                            {
+                                r_dcache_unc_req = true;
+                                r_dcache_fsm = DCACHE_UNC_WAIT;
+                                m_cpt_unc_read++;
+                                m_cost_unc_read_frz++;
+                            }
+                        }
+                        break;
+/*
+                    case iss_t::DATA_READ:
+                        m_cpt_read++;
+                        if ( dcache_hit_c ) 
+                        {
+                            r_dcache_buf_unc_valid = false;
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+                        } 
+                        else 
+                        {
+                            if ( dcache_cached ) 
+                            {
+                                r_dcache_miss_req = true;
+                                r_dcache_fsm = DCACHE_MISS_WAIT;
+                                m_cpt_data_miss++;
+                                m_cost_data_miss_frz++;
+                            } 
+                            else 
+                            {
+                                r_dcache_unc_req = true;
+                                r_dcache_fsm = DCACHE_UNC_WAIT;
+                                m_cpt_unc_read++;
+                                m_cost_unc_read_frz++;
+                            }
+                        }
+                        break;
+                    case iss_t::DATA_LL:
+			if (r_dcache_llsc_reserved && (r_dcache_llsc_addr_save == tlb_dpaddr) && r_dcache_buf_unc_valid)
+			{
+                            r_dcache_buf_unc_valid = false;
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+			}
+			else
+			{
+			    r_dcache_llsc_reserved = true;
+			    r_dcache_llsc_addr_save = tlb_dpaddr;
+                            r_dcache_unc_req = true;
+                            r_dcache_fsm = DCACHE_UNC_WAIT;
+			}
+			break;
+                    case iss_t::DATA_SC:
+			if (r_dcache_llsc_reserved && (r_dcache_llsc_addr_save == tlb_dpaddr))
+			{
+			    r_dcache_llsc_reserved = false;
+                            r_dcache_unc_req = true;
+                            r_dcache_fsm = DCACHE_UNC_WAIT;
+			}
+			else
+			{   
+			    if ( r_dcache_buf_unc_valid )
+			    {                         
+			        r_dcache_llsc_reserved = false;
+			        r_dcache_buf_unc_valid = false;
+                                drsp.valid = true;
+                                drsp.rdata = dcache_rdata;
+			    }
+                            r_dcache_fsm = DCACHE_IDLE;
+			}			
+			break;
+*/
+                    case iss_t::DATA_WRITE:
+                        m_cpt_write++;
+                        if ( dcache_cached ) m_cpt_write_cached++;
+
+                        if ( dcache_hit_c && dcache_cached )    // cache update required
+                        {
+                            r_dcache_fsm = DCACHE_WRITE_UPDT;
+                        } 
+                        else if ( !dcache_pte_info.d && (r_mmu_mode.read() & DATA_TLB_MASK) )   // dirty bit update required
+                        {
+                            if ( dcache_tlb.getpagesize(dcache_tlb_way, dcache_tlb_set) )	// 2M page size, one level page table 
+                            {
+                                r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
+                                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                                write_hit = r_dcache.write((paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2), 
+                                                           (dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK));
+                                assert(write_hit && "Write on miss ignores data");
+                                r_dcache_tlb_ll_dirty_req = true;
+                                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                                m_cpt_data_tlb_write_dirty++;
+                            }
+                            else	// 4k page size, two levels page table 
+                            {   
+                                if (dcache_hit_p) 
+                                {
+                                    r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
+                                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save | (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                                    write_hit = r_dcache.write(((paddr_t)r_dcache_ptba_save | (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3)), 
+                                                       (dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK));
+                                    assert(write_hit && "Write on miss ignores data");
+                                    r_dcache_tlb_ll_dirty_req = true;
+                                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                                    m_cpt_data_tlb_write_dirty++;
+                                }
+                                else    // get PTBA to calculate the physical address of PTE
+                                {
+                                    r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
+                                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                                    r_dcache_tlb_ptba_read = true;
+                                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                                }
+                            }
+                            m_cost_data_tlb_miss_frz++;
+                        }
+                        else                                    // no cache update, not dirty bit update
+                        {
+                            r_dcache_fsm = DCACHE_WRITE_REQ;
+                            drsp.valid = true;
+                            drsp.rdata = 0;
+                        }
+                        break;
+                    default:
+                        break;
+                } // end switch dreq.type
+            } // end if next states
+
+            // save values for the next states
+            r_dcache_paddr_save   = tlb_dpaddr;
+            r_dcache_type_save    = dreq.type;
+            r_dcache_wdata_save   = dreq.wdata;
+            r_dcache_be_save      = dreq.be;
+            r_dcache_rdata_save   = dcache_rdata;
+            r_dcache_cached_save  = dcache_cached;
+            r_dcache_dirty_save   = dcache_pte_info.d;
+            r_dcache_tlb_set_save = dcache_tlb_set;
+            r_dcache_tlb_way_save = dcache_tlb_way;
+
+        } // end if dreq.valid
+        else 
+        {   
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+
+        // processor request are not accepted in the WRITE_REQ state 
+        // when the write buffer is not writeable
+
+        if ((r_dcache_fsm == DCACHE_WRITE_REQ) && 
+            (r_dcache_write_req || !r_wbuf.wok(r_dcache_paddr_save))) 
+        {
+            drsp.valid = false;
+        }
+        break;
+    }
+    /////////////////
+    case DCACHE_BIS:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        bool    dcache_hit   = false;
+        bool    write_hit    = false;
+        data_t  dcache_rdata = 0;
+
+        // acces always cached in this state
+        dcache_hit = r_dcache.read(r_dcache_paddr_save, &dcache_rdata);
+
+        if ( dreq.type == iss_t::DATA_READ )  // cached read
+        {
+            m_cpt_read++;
+            if ( !dcache_hit ) 
+            {
+                r_dcache_miss_req = true;
+                r_dcache_fsm = DCACHE_MISS_WAIT;
+                m_cpt_data_miss++;
+                m_cost_data_miss_frz++;
+            }
+            else
+            {
+                r_dcache_fsm = DCACHE_IDLE;
+            }
+            drsp.valid = dcache_hit;
+            drsp.error = false;
+            drsp.rdata = dcache_rdata;
+        }
+        else    // cached write
+        {
+            m_cpt_write++;
+            m_cpt_write_cached++;
+            if ( dcache_hit )    // cache update required
+            {
+            	r_dcache_rdata_save = dcache_rdata;
+                r_dcache_fsm = DCACHE_WRITE_UPDT;
+            } 
+            else if (!r_dcache_dirty_save && (r_mmu_mode.read() & DATA_TLB_MASK))   // dirty bit update required
+            {
+                if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save)) 
+                {
+                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                    write_hit = r_dcache.write((paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2), 
+                                               (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
+                    assert(write_hit && "Write on miss ignores data");
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {   
+                    if (r_dcache_hit_p_save) 
+                    {
+                        r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                        r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                        write_hit = r_dcache.write(((paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3)), 
+                                                    (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
+                        assert(write_hit && "Write on miss ignores data");
+                        r_dcache_tlb_ll_dirty_req = true;
+                        r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                        m_cpt_data_tlb_write_dirty++;
+                    }
+                    else
+                    {
+                        r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                        r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                        r_dcache_tlb_ptba_read = true;
+                        r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                    }
+                }
+                m_cost_data_tlb_miss_frz++;
+            }
+            else                                    // no cache update, not dirty bit update
+            {
+                r_dcache_fsm = DCACHE_WRITE_REQ;
+                drsp.valid = true;
+                drsp.rdata = 0;
+            }
+        }
+        break;
+    }
+    //////////////////////////
+    case DCACHE_LL_DIRTY_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_tlb_ll_dirty_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+		if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save)) 
+		{
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;     
+		}
+		else
+		{
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;     
+		}
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+            }
+	    else
+	    {
+		if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+		    if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
+		    { 
+			r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;       
+		    }
+		    else
+		    {
+			r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;       
+	  	    }
+                    r_dcache_bad_vaddr = dreq.addr;
+                    r_dcache_fsm = DCACHE_ERROR;
+
+		    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+	        }
+        	else if ( r_dcache_inval_tlb_rsp )
+        	{
+        	    r_dcache_inval_tlb_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	    m_cost_data_tlb_miss_frz++;
+        	}
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+		else
+		{
+		    r_dcache_tlb_sc_dirty_req = true;
+		    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
+                    r_dcache_fsm = DCACHE_SC_DIRTY_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    //////////////////////////
+    case DCACHE_SC_DIRTY_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_tlb_sc_dirty_req )
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+	        if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
+	        {
+	            r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;    
+	        }
+	        else
+	        {
+	            r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;    
+	        }
+	        r_dcache_bad_vaddr = dreq.addr;
+	        r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;		 		         }
+	    else 
+	    {
+                // Using tlb entry is invalidated 
+                if ( r_dcache_inval_tlb_rsp )
+                {
+                    r_dcache_inval_tlb_rsp = false;
+                    r_dcache_fsm = DCACHE_IDLE;
+                    m_cost_data_tlb_miss_frz++;
+                }
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+		else if ( r_dcache_tlb_ll_dirty_req )
+	        {
+	            r_dcache_fsm = DCACHE_LL_DIRTY_WAIT; 
+	        }
+		else
+		{
+	            r_dcache_fsm = DCACHE_WRITE_DIRTY; 
+		}
+	    }
+	}
+	break;
+    }
+    ////////////////////////////
+    case DCACHE_DTLB1_READ_CACHE:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        data_t tlb_data = 0;
+	bool write_hit = false;
+        bool tlb_hit_cache = r_dcache.read(r_dcache_tlb_paddr, &tlb_data);
+
+        // DTLB request hit in cache
+        if ( tlb_hit_cache )
+        {
+	    if ( !(tlb_data >> PTE_V_SHIFT) )	// unmapped
+	    {
+                r_dcache_ptba_ok    = false;
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
+                }  
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (tlb_data & PTE_T_MASK) >> PTE_T_SHIFT )	// PTD
+	    {
+                r_dcache_ptba_ok   = true;
+                r_dcache_ptba_save = (paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS;  
+                r_dcache_id1_save  = dreq.addr >> PAGE_M_NBITS;
+                r_dcache_tlb_paddr = (paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                     (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
+                if ( r_dcache_tlb_ptba_read )
+                {
+                    r_dcache_tlb_ptba_read = false;
+                    write_hit = r_dcache.write(((paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                                (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3)), r_dcache_pte_update);
+                    assert(write_hit && "Write on miss ignores data");
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {
+                    r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
+                }
+	    }
+	    else	// PTE
+	    {
+                r_dcache_ptba_ok = false;
+	        if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (tlb_data & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+                        r_dcache_fsm = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_L_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (tlb_data & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+                        r_dcache_fsm = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_R_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        else
+        {
+            // DTLB request miss in cache and walk page table level 1
+            r_dcache_tlb_read_req = true;
+            r_dcache_fsm = DCACHE_TLB1_READ;
+        }
+        break;
+    }
+    ///////////////////////
+    case DCACHE_TLB1_LL_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_tlb_ll_acc_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;		 
+            }
+	    else
+	    {
+		if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+               	    if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+               	    {
+               	        r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
+               	    }
+               	    else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+               	    {
+               	        r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
+               	    } 
+                    r_dcache_bad_vaddr  = dreq.addr;
+                    r_dcache_fsm        = DCACHE_ERROR;
+
+		    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	        }
+       		else if ( r_dcache_inval_tlb_rsp )
+       		{
+       		    r_dcache_inval_tlb_rsp = false;
+       		    r_dcache_fsm = DCACHE_IDLE;
+       		    m_cost_data_tlb_miss_frz++;
+       		}
+		else if ( r_dcache_inval_rsp )
+       		{
+       		    r_dcache_inval_rsp = false;
+       		    r_dcache_fsm = DCACHE_IDLE;
+       		}
+		else
+		{
+		    r_dcache_tlb_sc_acc_req = true;
+		    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
+                    r_dcache_fsm = DCACHE_TLB1_SC_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    ///////////////////////
+    case DCACHE_TLB1_SC_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_tlb_sc_acc_req )
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
+                } 
+	        r_dcache_bad_vaddr = dreq.addr;
+	        r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	    }
+	    else
+	    {
+        	// Using tlb entry is invalidated 
+        	if ( r_dcache_inval_tlb_rsp )
+        	{
+        	    r_dcache_inval_tlb_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	    m_cost_data_tlb_miss_frz++;
+        	}
+		else if ( r_dcache_inval_rsp )
+        	{
+        	    r_dcache_inval_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	}
+	    	else if ( r_dcache_tlb_ll_acc_req )
+	    	{
+	    	    r_dcache_fsm = DCACHE_TLB1_LL_WAIT; 
+	    	}
+	    	else 
+	    	{
+	    	    r_dcache_fsm = DCACHE_TLB1_UPDT; 
+	    	}
+	    }
+	}
+	break;
+    }
+    //////////////////////
+    case DCACHE_TLB1_READ:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+	if ( !r_dcache_tlb_read_req )
+	{	
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+		break;
+            }
+
+            if ( r_dcache_inval_tlb_rsp )  // TLB miss response and invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_tlb_rsp = false;
+		break;
+            }
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+		break;	    
+	    }
+	    // TLB miss response and no invalidation
+	    r_dcache_fsm = DCACHE_TLB1_READ_UPDT;
+	}
+        break;
+    }
+    //////////////////////////
+    case DCACHE_TLB1_READ_UPDT:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        // Using tlb entry is in the invalidated cache line  
+        if ( r_dcache_inval_rsp )
+        {
+            r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if ( !r_dcache_cleanup_req ) // Miss update and no invalidation
+        {
+            // update dcache
+            data_t   rsp_dtlb_miss = 0;
+            paddr_t  victim_index = 0;
+	    bool write_hit = false;
+            size_t way = 0;
+            size_t set = 0;
+
+            bool cleanup_req = r_dcache.find(r_dcache_tlb_paddr, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+            
+	    if ( cleanup_req )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+	    r_dcache.update(r_dcache_tlb_paddr, way, set, r_dcache_miss_buf);
+            r_dcache.read(r_dcache_tlb_paddr, &rsp_dtlb_miss);	
+
+	    if ( !(rsp_dtlb_miss >> PTE_V_SHIFT) )	// unmapped
+	    {
+                r_dcache_ptba_ok    = false;
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
+                } 
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (rsp_dtlb_miss & PTE_T_MASK) >> PTE_T_SHIFT ) // PTD
+	    {
+                r_dcache_ptba_ok   = true;
+                r_dcache_ptba_save = (paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS;  
+                r_dcache_id1_save  = dreq.addr >> PAGE_M_NBITS;
+                r_dcache_tlb_paddr = (paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                     (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
+                if ( r_dcache_tlb_ptba_read )
+                {
+                    r_dcache_tlb_ptba_read = false;
+                    write_hit = r_dcache.write(((paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                                (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3)),r_dcache_pte_update);
+                    assert(write_hit && "Write on miss ignores data");
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {
+                    r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
+                }
+	    }
+	    else	// PTE
+	    {
+                r_dcache_ptba_ok = false;
+	        if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (rsp_dtlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+                        r_dcache_fsm        = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_L_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm        = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (rsp_dtlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+                        r_dcache_fsm        = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_R_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm        = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        break;
+    }
+    //////////////////////
+    case DCACHE_TLB1_UPDT: 
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        if ( !r_dcache_inval_tlb_rsp && !r_dcache_inval_rsp )
+        {
+            paddr_t victim_index = 0;
+            if (dcache_tlb.update(r_dcache_pte_update,dreq.addr,(r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index))
+            {
+                r_dcache.setinbit((paddr_t)victim_index*m_dcache_words*2, r_dcache_in_dtlb, false);
+            }
+            r_dcache.setinbit(r_dcache_tlb_paddr, r_dcache_in_dtlb, true);
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        else  
+        {
+            if ( r_dcache_inval_tlb_rsp ) r_dcache_inval_tlb_rsp = false;
+            if ( r_dcache_inval_rsp ) r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        break;
+    }
+    /////////////////////////////
+    case DCACHE_DTLB2_READ_CACHE:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        data_t tlb_data = 0;
+        data_t tlb_data_ppn = 0;
+	bool write_hit = false;
+        bool tlb_hit_cache = r_dcache.read(r_dcache_tlb_paddr, &tlb_data);
+
+	if ( tlb_hit_cache )
+	{
+            bool tlb_hit_ppn = r_dcache.read(r_dcache_tlb_paddr.read()+4, &tlb_data_ppn);
+	    assert(tlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+	}
+
+        // DTLB request hit in cache
+        if ( tlb_hit_cache )
+        {
+	    if ( !(tlb_data >> PTE_V_SHIFT) )	// unmapped
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
+                } 
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (tlb_data & PTE_T_MASK) >> PTE_T_SHIFT ) //PTD
+	    {
+                r_dcache_pte_update = tlb_data;
+	        r_dcache_ppn_update = tlb_data_ppn;
+		r_dcache_fsm = DCACHE_TLB2_UPDT;
+	    }
+	    else 
+	    {
+	        if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (tlb_data & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_L_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (tlb_data & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_R_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        else
+        {
+            // DTLB request miss in cache and walk page table level 2
+            r_dcache_tlb_read_req = true;
+            r_dcache_fsm = DCACHE_TLB2_READ;
+        }
+        break;
+    }
+    ///////////////////////
+    case DCACHE_TLB2_LL_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_tlb_ll_acc_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+            }
+	    else
+	    {
+	        if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+               	    if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+               	    {
+               	        r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
+               	    }
+               	    else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+               	    {
+               	        r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
+               	    } 
+                    r_dcache_bad_vaddr = dreq.addr;
+                    r_dcache_fsm = DCACHE_ERROR;
+
+		    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+	        }
+        	else if ( r_dcache_inval_tlb_rsp )
+        	{
+        	    r_dcache_inval_tlb_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	    m_cost_data_tlb_miss_frz++;
+        	}
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+		else
+		{
+		    r_dcache_tlb_sc_acc_req = true;
+		    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
+                    r_dcache_fsm = DCACHE_TLB2_SC_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    ///////////////////////
+    case DCACHE_TLB2_SC_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_tlb_sc_acc_req )
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
+                } 
+	        r_dcache_bad_vaddr = dreq.addr;
+	        r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	    }
+	    else
+	    { 
+                // Using tlb entry is invalidated 
+                if ( r_dcache_inval_tlb_rsp )
+                {
+                    r_dcache_inval_tlb_rsp = false;
+                    r_dcache_fsm = DCACHE_IDLE;
+                    m_cost_data_tlb_miss_frz++;
+                }
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+	        else if ( r_dcache_tlb_ll_acc_req )
+	        {
+	            r_dcache_fsm = DCACHE_TLB2_LL_WAIT; 
+	        }
+	        else 
+	        {
+	            r_dcache_fsm = DCACHE_TLB2_UPDT; 
+	        }
+	    }
+	}
+	break;
+    }
+    /////////////////////
+    case DCACHE_TLB2_READ:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+	if ( !r_dcache_tlb_read_req )
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            }	
+
+            if ( r_dcache_inval_tlb_rsp )  // TLB miss response and invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE; 
+                r_dcache_inval_tlb_rsp = false;
+		break;
+            }   
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+		break;	    
+	    }
+	    // TLB miss response and no invalidation
+	    r_dcache_fsm = DCACHE_TLB2_READ_UPDT; 
+	}	
+        break;
+    }
+    //////////////////////////
+    case DCACHE_TLB2_READ_UPDT:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        // Using tlb entry is in the invalidated cache line  
+        if ( r_dcache_inval_rsp )
+        {
+            r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if ( !r_dcache_cleanup_req )
+        {
+            // update cache
+            data_t rsp_dtlb_miss;
+            data_t tlb_data_ppn;
+	    bool write_hit = false;
+            paddr_t  victim_index = 0;
+            size_t way = 0;
+            size_t set = 0;
+
+            bool cleanup_req = r_dcache.find(r_dcache_tlb_paddr, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+
+	    if ( cleanup_req )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+	    r_dcache.update(r_dcache_tlb_paddr, way, set, r_dcache_miss_buf);
+	    r_dcache.read(r_dcache_tlb_paddr, &rsp_dtlb_miss);
+
+	    bool tlb_hit_ppn = r_dcache.read(r_dcache_tlb_paddr.read()+4, &tlb_data_ppn);
+	    assert(tlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+
+	    if ( !(rsp_dtlb_miss >> PTE_V_SHIFT) )	// unmapped
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
+                }  
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (rsp_dtlb_miss & PTE_T_MASK) >> PTE_T_SHIFT ) // PTD
+	    {
+                r_dcache_pte_update = rsp_dtlb_miss;
+	        r_dcache_ppn_update = tlb_data_ppn;
+		r_dcache_fsm = DCACHE_TLB2_UPDT;
+	    }
+	    else
+	    {
+	        if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (rsp_dtlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_L_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (rsp_dtlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_R_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        break;
+    }
+    //////////////////////
+    case DCACHE_TLB2_UPDT:  
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        if ( !r_dcache_inval_tlb_rsp && !r_dcache_inval_rsp )
+        {
+            paddr_t victim_index = 0;
+            if (dcache_tlb.update(r_dcache_pte_update,r_dcache_ppn_update,dreq.addr,(r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index))
+            {
+                r_dcache.setinbit((paddr_t)victim_index*m_dcache_words*2, r_dcache_in_dtlb, false);
+            }
+            r_dcache.setinbit(r_dcache_tlb_paddr, r_dcache_in_dtlb, true);
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        else  
+        {
+            if ( r_dcache_inval_tlb_rsp ) r_dcache_inval_tlb_rsp = false;
+            if ( r_dcache_inval_rsp ) r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        break;
+    }
+    ///////////////////////
+    case DCACHE_CTXT_SWITCH:
+    {
+        // TLB flush leads to cleanup corresponding data cache line 
+        m_cost_data_tlb_sw_frz++;
+
+        paddr_t victim_index = 0;
+        size_t way = 0;
+        size_t set = 0;
+
+        if ( r_dcache_itlb_cleanup_req )
+        {    
+            r_dcache.setinbit(((paddr_t)r_dcache_itlb_cleanup_line.read()*m_dcache_words*2), r_dcache_in_itlb, false);
+            r_dcache_itlb_cleanup_req = false;
+	}
+
+        for ( way = 0; way < m_dtlb_ways; way++)
+        {
+            for ( set = 0; set < m_dtlb_sets; set++)
+            {
+                if(dcache_tlb.checkcleanup(way, set, &victim_index))
+                {
+                    r_dcache.setinbit((paddr_t)(victim_index << (m_dcache_words+2)), r_dcache_in_dtlb, false); 
+                }
+            }
+        }
+
+        if ((way == m_dtlb_ways) && (set == m_dtlb_sets) && (!r_dcache_xtn_req))
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            drsp.valid = true;
+        }
+        break;
+    }
+    ////////////////////////
+    case DCACHE_ICACHE_FLUSH:
+    case DCACHE_ICACHE_INVAL:
+    case DCACHE_ITLB_INVAL:
+    {
+        if ( !r_dcache_xtn_req ) 
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            drsp.valid = true;
+        }
+        break;
+    }
+    ////////////////////////
+    case DCACHE_DCACHE_FLUSH:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )
+        {
+            r_tgt_dcache_req = false;
+        }   
+
+        size_t way = r_dcache_way;
+        size_t set = r_dcache_set;
+        bool clean = false;
+        
+        m_cost_data_cache_flush_frz++;
+
+        // cache flush and send cleanup to external
+        if ( !r_dcache_cleanup_req )
+        {
+            paddr_t victim_index = 0;
+            for ( ; way < m_dcache_ways; way++ )
+            {    
+                for ( ; set < m_dcache_sets; set++ )
+                {  
+                    if ( r_dcache.flush(way, set, &victim_index) )
+                    {
+                        clean = true;
+                        r_dcache_cleanup_req = true;
+                        r_dcache_cleanup_line = victim_index;
+                        r_dcache_way = way + ((set+1)/m_dcache_sets);
+                        r_dcache_set = (set+1) % m_dcache_sets;
+                        break;
+                    }
+                }
+                if (clean) break;
+            }
+
+            if ((way == m_dcache_ways) && (set == m_dcache_sets) && !r_dcache_xtn_req ) 
+            {
+                // data TLB flush 
+                dcache_tlb.flush(true);      // global entries are not invalidated
+
+                for (size_t line = 0; line < m_dcache_ways*m_dcache_sets; line++)
+                {
+                    r_dcache_in_itlb[line] = false;
+                    r_dcache_in_dtlb[line] = false;
+                }
+
+                r_dcache_fsm = DCACHE_IDLE;
+                drsp.valid = true;
+                break;
+            }
+        }
+	break;
+    }
+    //////////////////////
+    case DCACHE_DTLB_INVAL: 
+    {
+        paddr_t victim_index = 0;
+        // clean indicate data tlb bit
+        if ( dcache_tlb.inval(r_dcache_wdata_save, &victim_index) )
+        {  
+            r_dcache.setinbit((paddr_t)(victim_index << (m_dcache_words+2)), r_dcache_in_dtlb, false); 
+        }
+        r_dcache_fsm = DCACHE_IDLE;
+        drsp.valid = true;
+        break;
+    }
+    ////////////////////////
+    case DCACHE_DCACHE_INVAL:
+    {
+        m_cpt_dcache_dir_read += m_dcache_ways;
+        vaddr_t invadr = dreq.wdata;
+        paddr_t dpaddr = 0;
+        bool dcache_hit_t = false; 
+        size_t way = 0;
+        size_t set = 0;
+
+	if ( !r_dcache_cleanup_req )
+	{
+            if ( r_mmu_mode.read() & DATA_TLB_MASK ) 
+            {
+                dcache_hit_t = dcache_tlb.translate(invadr, &dpaddr); 
+            } 
+            else 
+            {
+                dpaddr = invadr;  
+                dcache_hit_t = true;
+            }
+
+            if ( dcache_hit_t )
+            {
+		r_dcache_cleanup_req = r_dcache.inval(dpaddr, &way, &set);
+		r_dcache_cleanup_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+		
+		if ( r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[way*m_dcache_sets+set] ) 
+		{	
+		    // ins tlb invalidate verification
+		    r_dcache_itlb_inval_req = r_dcache_in_itlb[way*m_dcache_sets+set];
+		    r_dcache_itlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+		    r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+		
+		    // data tlb invalidate verification
+		    r_dcache_dtlb_inval_req = r_dcache_in_dtlb[way*m_dcache_sets+set];
+		    r_dcache_dtlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+		    r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+		    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+		    r_dcache_fsm_save = r_dcache_fsm;
+		    break;
+		}
+            }
+            r_dcache_fsm = DCACHE_IDLE;
+            drsp.valid = true;
+	}
+        break;
+    }
+    /////////////////////////
+    case DCACHE_DCACHE_SYNC:
+    {
+        if ( !r_dcache_write_req ) 
+        {
+            r_dcache_write_req = r_wbuf.rok();
+            drsp.valid = true;
+            r_dcache_fsm = DCACHE_IDLE;
+        }    
+        break;
+    }
+    /////////////////////
+    case DCACHE_MISS_WAIT:
+    {
+        m_cost_data_miss_frz++; 
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_miss_req )
+	{
+            if ( r_vci_rsp_data_error ) 
+            {
+                r_dcache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            } 
+
+            if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_tlb_rsp = false;
+		break;
+            }	
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+		break;	    
+	    }
+	    // Miss read response and no tlb invalidation
+	    r_dcache_fsm = DCACHE_MISS_UPDT;
+	}	
+        break;
+    }
+    /////////////////////
+    case DCACHE_MISS_UPDT:
+    {
+        m_cost_data_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        if ( r_dcache_inval_tlb_rsp ) // tlb invalidation
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        // Using tlb entry is in the invalidated cache line  
+        if ( r_dcache_inval_rsp )
+        {
+            r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if (!r_dcache_cleanup_req ) // Miss update and no invalidation
+        {
+            paddr_t  victim_index = 0;
+            size_t way = 0;
+            size_t set = 0;
+
+	    m_cpt_dcache_data_write++;
+            m_cpt_dcache_dir_write++;
+
+            bool cleanup_req = r_dcache.find(r_dcache_paddr_save.read(), r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+
+	    if ( cleanup_req )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+	    r_dcache.update(r_dcache_paddr_save.read(), way, set, r_dcache_miss_buf);
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+	break;
+    }
+    //////////////////////
+    case DCACHE_UNC_WAIT:
+    {
+        m_cost_unc_read_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_unc_req )
+	{
+            if ( r_vci_rsp_data_error ) 
+            {
+                r_dcache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		//if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            }
+
+            if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_tlb_rsp = false;
+		break;
+            }
+/*
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+
+		if ((dreq.type == iss_t::DATA_LL) || (dreq.type == iss_t::DATA_SC))
+		{
+        	    r_dcache_buf_unc_valid = false;
+		    r_dcache_llsc_reserved = false;
+		}
+		break;	    
+	    }
+*/  
+            if(dreq.type == iss_t::DATA_SC) 
+	    {
+                // Simulate an invalidate request
+                r_dcache.inval(r_dcache_paddr_save);
+            }		
+            r_dcache_buf_unc_valid = true;
+	    r_dcache_fsm = DCACHE_IDLE;
+	}	
+        break;
+    }
+    ///////////////////////
+    case DCACHE_WRITE_UPDT:
+    {
+        m_cost_write_frz++;
+        size_t way = 0;
+        size_t set = 0;
+	bool write_hit = false;
+        data_t mask = vci_param::be2mask(r_dcache_be_save.read());
+        data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
+        write_hit = r_dcache.write(r_dcache_paddr_save, wdata, &way, &set);
+        assert(write_hit && "Write on miss ignores data");
+        
+        if (r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[m_dcache_sets*way+set])
+        {
+	    // ins tlb invalidate verification    
+            r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+            r_dcache_itlb_inval_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
+            r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+            // data tlb invalidate verification
+            r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+            r_dcache_dtlb_inval_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
+            r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+            r_dcache_cleanup_req = true; 
+            r_dcache_cleanup_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
+	    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+            r_dcache_fsm_save = r_dcache_fsm;
+            break;
+	}
+
+        if ( !r_dcache_dirty_save && (r_mmu_mode.read() & DATA_TLB_MASK) )   
+        {
+            if ( dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save) )	// 2M page size, one level page table 
+            {
+                r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                write_hit = r_dcache.write((paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2), 
+                                     (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
+                assert(write_hit && "Write on miss ignores data");
+                r_dcache_tlb_ll_dirty_req = true;
+                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                m_cpt_data_tlb_write_dirty++;
+            }
+            else
+            {   
+                if (r_dcache_hit_p_save) 
+                {
+                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                    write_hit = r_dcache.write(((paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3)), 
+                                     (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
+                    assert(write_hit && "Write on miss ignores data");
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {
+                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                    r_dcache_tlb_ptba_read = true;
+                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                }
+            }
+        }
+        else
+        {
+            r_dcache_fsm = DCACHE_WRITE_REQ;
+            drsp.valid = true;
+            drsp.rdata = 0;
+        }
+        break;
+    }
+    ////////////////////////
+    case DCACHE_WRITE_DIRTY:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            r_dcache_inval_tlb_rsp = false;
+	    break;
+        }
+
+	if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	{
+            r_dcache_fsm = DCACHE_IDLE; 
+            r_dcache_inval_rsp = false;
+	    break;	    
+	}
+
+        dcache_tlb.setdirty(r_dcache_tlb_way_save, r_dcache_tlb_set_save);
+        r_dcache_fsm = DCACHE_WRITE_REQ;
+        drsp.valid = true;
+        drsp.rdata = 0;
+        break;
+    }
+    /////////////////
+    case DCACHE_ERROR:
+    {
+        r_vci_rsp_data_error = false;
+        drsp.valid = true;
+        drsp.error = true;
+        drsp.rdata = 0;
+        r_dcache_fsm = DCACHE_IDLE;
+        break;
+    }   
+    ////////////////////// 
+    case DCACHE_ITLB_READ:
+    {
+        m_cost_data_waste_wait_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+    	if ( !r_dcache_itlb_read_req ) // vci response ok
+        {  
+            if ( r_vci_rsp_data_error )
+            {
+                r_dcache_rsp_itlb_error = true;	
+                r_itlb_read_dcache_req = false;
+                r_vci_rsp_data_error = false;
+                r_dcache_fsm = DCACHE_IDLE;
+
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            }
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_rsp = false;
+		break;	    
+	    }
+            r_dcache_fsm = DCACHE_ITLB_UPDT;
+        }
+	break;    	
+    }
+    //////////////////////
+    case DCACHE_ITLB_UPDT:
+    {
+        m_cost_data_waste_wait_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        // Using tlb entry is in the invalidated cache line  
+        if ( r_dcache_inval_rsp )
+        {
+            r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if ( !r_dcache_cleanup_req )
+        {
+            data_t rsp_itlb_miss = 0;
+	    data_t rsp_itlb_ppn = 0;
+
+            paddr_t  victim_index = 0;
+            size_t way = 0;
+            size_t set = 0;
+            
+            bool cleanup = r_dcache.find(r_icache_paddr_save, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+
+	    if ( cleanup )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+            r_dcache.update(r_icache_paddr_save, way, set, r_dcache_miss_buf);
+
+            r_dcache.setinbit(r_icache_paddr_save, r_dcache_in_itlb, true);
+            bool itlb_hit_dcache = r_dcache.read(r_icache_paddr_save, &rsp_itlb_miss);	
+ 
+	    if ( (r_icache_fsm == ICACHE_TLB2_READ) && itlb_hit_dcache )
+	    {	
+            	bool itlb_hit_ppn = r_dcache.read(r_icache_paddr_save.read()+4, &rsp_itlb_ppn);
+		assert(itlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+	    }
+
+            r_dcache_rsp_itlb_miss = rsp_itlb_miss;
+            r_dcache_rsp_itlb_ppn = rsp_itlb_ppn;
+            r_dcache_rsp_itlb_error = false;	
+            r_itlb_read_dcache_req = false;
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        break;
+    }
+    //////////////////////////
+    case DCACHE_ITLB_LL_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_itlb_ll_acc_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                r_dcache_rsp_itlb_error = true;  
+                r_vci_rsp_data_error = false;
+                r_itlb_acc_dcache_req = false;
+		r_dcache_fsm = DCACHE_IDLE;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+            }
+	    else
+	    {
+	        if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+                    r_dcache_rsp_itlb_error = true;  
+                    r_itlb_acc_dcache_req = false;
+		    r_dcache_fsm = DCACHE_IDLE;	
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	        }
+       		else if ( r_dcache_inval_rsp )
+       		{
+       		    r_dcache_inval_rsp = false;
+       		    r_dcache_fsm = DCACHE_IDLE;
+       		    m_cost_data_tlb_miss_frz++;
+       		}
+		else
+		{
+		    r_dcache_itlb_sc_acc_req = true;
+		    r_icache_pte_update = r_dcache_miss_buf[0] | r_icache_pte_update.read();	
+                    r_dcache_fsm = DCACHE_ITLB_SC_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    //////////////////////////
+    case DCACHE_ITLB_SC_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+	
+        if ( !r_dcache_itlb_sc_acc_req ) 
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+	        r_dcache_rsp_itlb_error = true;  
+	        r_vci_rsp_data_error = false;
+	        r_itlb_acc_dcache_req = false;
+	        r_dcache_fsm = DCACHE_IDLE;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;		
+	    }
+	    else
+	    {
+	        if ( r_dcache_inval_rsp )
+	        {
+	            r_dcache_inval_rsp = false;
+	            r_dcache_fsm = DCACHE_IDLE;
+	            m_cost_data_tlb_miss_frz++;
+	        }
+	        else if ( r_dcache_itlb_ll_acc_req )
+	        {
+	            r_dcache_fsm = DCACHE_ITLB_LL_WAIT; 
+	        }
+	        else 
+	        {
+	            r_itlb_acc_dcache_req = false;
+	            r_dcache_fsm = DCACHE_IDLE; 
+	        }
+	    }
+	}
+	break;
+    }
+    /////////////////////
+    case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        m_cpt_dcache_dir_read += m_dcache_ways;
+        m_cpt_dcache_data_read += m_dcache_ways;
+
+        data_t dcache_rdata = 0;
+        size_t way = 0;
+        size_t set = 0;
+
+        bool dcache_hit = r_dcache.read(r_tgt_addr.read(), &dcache_rdata, &way, &set);
+
+        if ( dcache_hit )
+        {
+            if ( r_dcache_in_dtlb[m_dcache_sets*way+set] || r_dcache_in_itlb[m_dcache_sets*way+set] )
+	    {
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = r_tgt_addr.read() >> (uint32_log2(m_dcache_words)+2);
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = r_tgt_addr.read() >> (uint32_log2(m_dcache_words)+2);
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+		
+		r_dcache_cc_check = true;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+		break;
+	    }
+
+            if(( /*( r_dcache_fsm_save == DCACHE_UNC_WAIT ) ||*/
+	         ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) && 
+               ( (r_dcache_paddr_save.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1)))) 
+            {
+	        r_dcache_inval_rsp = true;
+            } 
+
+            if(( ( r_dcache_fsm_save == DCACHE_TLB1_READ )      || ( r_dcache_fsm_save == DCACHE_TLB2_READ )      ||
+		 ( r_dcache_fsm_save == DCACHE_TLB1_READ_UPDT ) || ( r_dcache_fsm_save == DCACHE_TLB2_READ_UPDT ) ||
+                 ( r_dcache_fsm_save == DCACHE_TLB1_UPDT )      || ( r_dcache_fsm_save == DCACHE_TLB2_UPDT )	  ||
+		 ( r_dcache_fsm_save == DCACHE_TLB1_LL_WAIT )   || ( r_dcache_fsm_save == DCACHE_TLB2_LL_WAIT )   ||
+		 ( r_dcache_fsm_save == DCACHE_TLB1_SC_WAIT )   || ( r_dcache_fsm_save == DCACHE_TLB2_SC_WAIT )   ||
+		 ( r_dcache_fsm_save == DCACHE_LL_DIRTY_WAIT )  || ( r_dcache_fsm_save == DCACHE_SC_DIRTY_WAIT )  ||
+		 ( r_dcache_fsm_save == DCACHE_WRITE_DIRTY ) ) && 
+               ( (r_dcache_tlb_paddr.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1))) ) 
+            {
+                r_dcache_inval_rsp = true;
+            }
+
+            if(( ( r_dcache_fsm_save == DCACHE_ITLB_READ ) || ( r_dcache_fsm_save == DCACHE_ITLB_UPDT ) ||
+                 ( r_dcache_fsm_save == DCACHE_ITLB_LL_WAIT ) || ( r_dcache_fsm_save == DCACHE_ITLB_SC_WAIT ) ) && 
+               ( (r_icache_paddr_save.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1))) ) 
+            {
+                r_dcache_inval_rsp = true;
+            }
+
+            if ( r_tgt_update ) // update 
+            {
+                r_dcache_fsm = DCACHE_CC_UPDT;
+            } 
+            else                // invalidate 
+            {
+                r_dcache_fsm = DCACHE_CC_INVAL;
+            }
+        }
+        else                    // nothing
+        {
+            r_dcache_fsm = DCACHE_CC_NOP;
+        }
+        break;
+    }
+    ///////////////////
+    case DCACHE_CC_UPDT:    // update directory and data cache        
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        m_cpt_dcache_dir_write++;
+        m_cpt_dcache_data_write++;
+        data_t* buf = r_tgt_buf;
+        for( size_t i = 0; i < m_dcache_words; i++ )
+        {
+            if( r_tgt_val[i] ) r_dcache.write( r_tgt_addr.read() + i*4, buf[i] );
+        }
+           
+        r_tgt_dcache_req = false;
+        r_dcache_fsm = r_dcache_fsm_save;
+        break;
+    }
+    /////////////////////
+    case DCACHE_CC_INVAL:   // invalidate a cache line
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        r_tgt_dcache_rsp = r_dcache.inval(r_tgt_addr.read());
+        r_tgt_dcache_req = false;
+        r_dcache_fsm = r_dcache_fsm_save;
+        break;
+    }
+    ///////////////////
+    case DCACHE_CC_NOP:     // no external hit
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        r_tgt_dcache_req = false;
+        r_dcache_fsm = r_dcache_fsm_save;
+        break;
+    }   
+    /////////////////////////
+    case DCACHE_TLB_CC_INVAL:
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+	if ( r_dcache_itlb_inval_req || r_dcache_dtlb_inval_req ) break;
+
+        if( (( r_dcache_fsm_save == DCACHE_TLB1_READ )        || ( r_dcache_fsm_save == DCACHE_TLB2_READ )        ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_READ_UPDT )   || ( r_dcache_fsm_save == DCACHE_TLB2_READ_UPDT )   ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_LL_WAIT )     || ( r_dcache_fsm_save == DCACHE_TLB2_LL_WAIT )     ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_SC_WAIT )     || ( r_dcache_fsm_save == DCACHE_TLB2_SC_WAIT )     ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_UPDT )        || ( r_dcache_fsm_save == DCACHE_TLB2_UPDT )        ||
+             ( r_dcache_fsm_save == DCACHE_DTLB1_READ_CACHE ) || ( r_dcache_fsm_save == DCACHE_DTLB2_READ_CACHE ) ||
+             ( r_dcache_fsm_save == DCACHE_LL_DIRTY_WAIT )    || ( r_dcache_fsm_save == DCACHE_SC_DIRTY_WAIT )    ||
+	     ( r_dcache_fsm_save == DCACHE_WRITE_DIRTY )) && 
+            (((r_dcache_tlb_paddr.read() & ~((m_dcache_words<<2)-1)) >> (uint32_log2(m_dcache_words) + 2)) == r_dcache_dtlb_inval_line.read()) ) 
+        {
+            r_dcache_inval_tlb_rsp = true;
+        } 
+
+        if (((r_dcache_fsm_save == DCACHE_BIS)||(r_dcache_fsm_save == DCACHE_MISS_WAIT) ||
+             (r_dcache_fsm_save == DCACHE_UNC_WAIT)||(r_dcache_fsm_save == DCACHE_MISS_UPDT)) && 
+             (r_dcache_tlb_nline == r_dcache_dtlb_inval_line))
+        {
+            r_dcache_inval_tlb_rsp = true;
+        }
+
+	if ( !r_dcache_cc_check )
+	{
+            r_dcache_fsm = r_dcache_fsm_save;
+	}
+	else
+	{
+            r_dcache_fsm = DCACHE_CC_CHECK;
+	    r_dcache_cc_check = false;
+	}
+        break;
+    }
+    /////////////////////////
+    case DCACHE_ITLB_CLEANUP:
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        r_dcache.setinbit(((paddr_t)r_dcache_itlb_cleanup_line.read()*m_dcache_words*2), r_dcache_in_itlb, false);
+        r_dcache_itlb_cleanup_req = false;
+        r_dcache_fsm = DCACHE_IDLE;
+        break;
+    }
+    } // end switch r_dcache_fsm
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout << name() << " Data Response: " << drsp << std::endl;
+#endif
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //      INVAL DTLB CHECK FSM 
+    ////////////////////////////////////////////////////////////////////////////////////////
+    switch(r_inval_dtlb_fsm) {
+    /////////////////////
+    case INVAL_DTLB_IDLE:
+    {
+        if ( r_dcache_dtlb_inval_req ) 
+        {
+            r_ccinval_dtlb_way = 0;
+            r_ccinval_dtlb_set = 0;
+            r_inval_dtlb_fsm = INVAL_DTLB_CHECK;    
+            m_cost_data_tlb_inval_frz++;
+        }   
+        break;
+    }
+    ////////////////////////////
+    case INVAL_DTLB_CHECK:
+    {
+        m_cost_data_tlb_inval_frz++;
+
+        size_t way = r_ccinval_dtlb_way; 
+        size_t set = r_ccinval_dtlb_set;
+        bool end = false;        
+        bool tlb_hit = dcache_tlb.cccheck(r_dcache_dtlb_inval_line.read(), way, set, &way, &set, &end); 
+    
+        if ( tlb_hit )
+        {
+            r_ccinval_dtlb_way = way; 
+            r_ccinval_dtlb_set = set;
+            r_dtlb_cc_check_end = end;
+            r_inval_dtlb_fsm = INVAL_DTLB_INVAL;
+            m_cpt_data_tlb_inval++;    
+        }        
+        else
+        {
+            r_inval_dtlb_fsm = INVAL_DTLB_CLEAR;    
+        }
+        break;
+    }
+    /////////////////////////
+    case INVAL_DTLB_INVAL:
+    {
+        m_cost_data_tlb_inval_frz++;
+
+        dcache_tlb.ccinval(r_ccinval_dtlb_way, r_ccinval_dtlb_set);
+
+        if ( !r_dtlb_cc_check_end )
+        {
+            r_inval_dtlb_fsm = INVAL_DTLB_CHECK; 
+        }
+        else
+        {
+            r_inval_dtlb_fsm = INVAL_DTLB_CLEAR;    
+        }
+        break;
+    }
+    ////////////////////
+    case INVAL_DTLB_CLEAR:
+    {
+        r_dcache_dtlb_inval_req = false;
+        r_dtlb_cc_check_end = false;
+        r_ccinval_dtlb_way = 0; 
+        r_ccinval_dtlb_set = 0; 
+        r_inval_dtlb_fsm = INVAL_DTLB_IDLE;   
+        m_cpt_data_tlb_inval++;    
+        break;
+    }
+    } // end switch r_inval_itlb_fsm
+
+    /////////// execute one iss cycle /////////////////////////////////
+    {
+    uint32_t it = 0;
+    for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if(p_irq[i].read()) it |= (1<<i);
+    m_iss.executeNCycles(1, irsp, drsp, it);
+    }
+
+    ////////////// number of frozen cycles //////////////////////////
+    if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) )
+    {
+        m_cpt_frz_cycles++;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    //     VCI_CMD FSM 
+    //
+    // This FSM handles requests from both the DCACHE controler
+    // (request registers) and the ICACHE controler (request registers).
+    // There is 10 VCI transaction types :
+    // - INS_TLB_READ
+    // - INS_TLB_WRITE
+    // - INS_MISS
+    // - INS_UNC_MISS
+    // - DATA_TLB_READ
+    // - DATA_TLB_WRITE
+    // - DATA_TLB_DIRTY
+    // - DATA_MISS
+    // - DATA_UNC 
+    // - DATA_WRITE
+    // The ICACHE requests have the highest priority.
+    // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM and RSP_FSM
+    // exit simultaneously the IDLE state.
+    //////////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_cmd_fsm) {
+    
+    case CMD_IDLE:
+        if (r_vci_rsp_fsm != RSP_IDLE)
+            break;
+
+        r_vci_cmd_cpt = 0;
+
+        if (r_dcache_itlb_read_req)           
+        {            
+            r_vci_cmd_fsm = CMD_ITLB_READ;
+            m_cpt_itlbmiss_transaction++; 
+        } 
+	else if (r_dcache_itlb_ll_acc_req)
+	{
+	    r_vci_cmd_fsm = CMD_ITLB_ACC_LL;
+            m_cpt_itlb_write_transaction++; 
+	}
+	else if (r_dcache_itlb_sc_acc_req)
+	{
+	    r_vci_cmd_fsm = CMD_ITLB_ACC_SC;
+            m_cpt_itlb_write_transaction++; 
+	}
+        else if (r_icache_miss_req) 
+        {    
+            r_vci_cmd_fsm = CMD_INS_MISS;
+            m_cpt_imiss_transaction++; 
+        }
+        else if (r_icache_unc_req) 
+        {    
+            r_vci_cmd_fsm = CMD_INS_UNC;
+            m_cpt_imiss_transaction++; 
+        }  
+        else if (r_dcache_tlb_read_req) 
+        {            
+            r_vci_cmd_fsm = CMD_DTLB_READ;
+            m_cpt_dtlbmiss_transaction++; 
+        } 
+        else if (r_dcache_tlb_ll_acc_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_ACC_LL;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_tlb_sc_acc_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_ACC_SC;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_tlb_ll_dirty_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_DIRTY_LL;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_tlb_sc_dirty_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_DIRTY_SC;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_write_req)
+        {
+            r_vci_cmd_fsm = CMD_DATA_WRITE;
+            r_vci_cmd_cpt = r_wbuf.getMin();
+            r_vci_cmd_min = r_wbuf.getMin();
+            r_vci_cmd_max = r_wbuf.getMax(); 
+            m_cpt_write_transaction++; 
+            m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1);
+        }
+        else if (r_dcache_miss_req)  
+        {
+            r_vci_cmd_fsm = CMD_DATA_MISS;
+            m_cpt_dmiss_transaction++; 
+        }
+        else if (r_dcache_unc_req)  
+        {
+            r_vci_cmd_fsm = CMD_DATA_UNC;
+            m_cpt_unc_transaction++; 
+        }
+        break;
+
+    case CMD_DATA_WRITE:
+        if ( p_vci_ini_rw.cmdack.read() ) 
+        {
+            r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
+            if (r_vci_cmd_cpt == r_vci_cmd_max) 
+            {
+                r_vci_cmd_fsm = CMD_IDLE;
+                r_wbuf.reset();
+            }
+        }
+        break;
+
+    default:
+        if ( p_vci_ini_rw.cmdack.read() )
+        {  
+            r_vci_cmd_fsm = CMD_IDLE;
+        }
+        break;
+
+    } // end  switch r_vci_cmd_fsm
+
+    //////////////////////////////////////////////////////////////////////////
+    //      VCI_RSP FSM 
+    //
+    // This FSM is synchronized with the VCI_CMD FSM, as both FSMs exit the
+    // IDLE state simultaneously.
+    //////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_rsp_fsm) {
+
+    case RSP_IDLE:
+        assert( ! p_vci_ini_rw.rspval.read() && "Unexpected response" );
+
+        if (r_vci_cmd_fsm != CMD_IDLE)
+            break;
+
+        r_vci_rsp_cpt = 0;
+        if (r_dcache_itlb_read_req)          // ITLB miss response
+        {            
+            r_vci_rsp_fsm = RSP_ITLB_READ;
+        } 
+        else if (r_dcache_itlb_ll_acc_req)   // ITLB linked load response
+        {   
+            r_vci_rsp_fsm = RSP_ITLB_ACC_LL;
+        } 
+        else if (r_dcache_itlb_sc_acc_req)   // ITLB store conditional response
+        {   
+            r_vci_rsp_fsm = RSP_ITLB_ACC_SC;
+        } 
+        else if (r_icache_miss_req)         // ICACHE cached miss response
+        {   
+            r_vci_rsp_fsm = RSP_INS_MISS;
+        }
+        else if (r_icache_unc_req)          // ICACHE uncached miss response
+        {   
+            r_vci_rsp_fsm = RSP_INS_UNC;
+        }  
+        else if (r_dcache_tlb_read_req)     // ITLB miss response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_READ; 
+        }
+        else if (r_dcache_tlb_ll_acc_req)    // DTLB access bits linked load response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_ACC_LL; 
+        }
+        else if (r_dcache_tlb_sc_acc_req)    // DTLB access bits store conditional response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_ACC_SC; 
+        }
+        else if (r_dcache_tlb_ll_dirty_req)  // DTLB dirty bit linked load response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_DIRTY_LL; 
+        }
+        else if (r_dcache_tlb_sc_dirty_req)  // DTLB dirty bit store conditional response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_DIRTY_SC; 
+        }
+        else if (r_dcache_write_req)        // DCACHE write request
+        {
+            r_vci_rsp_fsm = RSP_DATA_WRITE;
+        }
+        else if (r_dcache_miss_req)         // DCACHE read request
+        {
+            r_vci_rsp_fsm = RSP_DATA_MISS;
+        }
+        else if (r_dcache_unc_req)          // DCACHE uncached read request
+        {
+            r_vci_rsp_fsm = RSP_DATA_UNC;
+        }
+        break;
+
+    case RSP_ITLB_READ:
+        m_cost_itlbmiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                    "illegal VCI response packet for data read miss");
+            r_dcache_itlb_read_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        } 
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_data_error = true;
+        }
+        break;
+
+    case RSP_ITLB_ACC_LL:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for ll tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else
+	{
+	    r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+	}
+        r_dcache_itlb_ll_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_ITLB_ACC_SC:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for sc tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else if ( p_vci_ini_rw.rdata.read() == 1 ) // store conditional is not successful
+	{
+	    r_dcache_itlb_ll_acc_req = true;
+	}
+        r_dcache_itlb_sc_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_INS_MISS:
+        m_cost_imiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert( (r_vci_rsp_cpt < m_icache_words) && 
+               "The VCI response packet for instruction miss is too long");
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            assert( (r_vci_rsp_cpt == m_icache_words - 1) &&
+                       "The VCI response packet for instruction miss is too short");
+            r_icache_miss_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+                
+        } 
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_ins_error = true;
+        }
+        break;
+
+    case RSP_INS_UNC:
+        m_cost_imiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for uncached instruction");
+
+        r_icache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+        r_icache_buf_unc_valid = true;
+        r_icache_unc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_ins_error = true;
+        }
+        break;
+
+    case RSP_DTLB_READ:
+        m_cost_dtlbmiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                    "illegal VCI response packet for data read miss");
+            r_dcache_tlb_read_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        } 
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_data_error = true;
+        }
+        break;
+
+    case RSP_DTLB_ACC_LL:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for ll tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else
+	{
+	    r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+	}
+        r_dcache_tlb_ll_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DTLB_ACC_SC:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for sc tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else if ( p_vci_ini_rw.rdata.read() == 1 ) // store conditional is not successful
+	{
+	    r_dcache_tlb_ll_acc_req = true;
+	}
+        r_dcache_tlb_sc_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DTLB_DIRTY_LL:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for ll tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else
+	{
+	    r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+	}
+        r_dcache_tlb_ll_dirty_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DTLB_DIRTY_SC:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for sc tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else if ( p_vci_ini_rw.rdata.read() == 1 ) // store conditional is not successful
+	{
+	    r_dcache_tlb_ll_dirty_req = true;
+	}
+        r_dcache_tlb_sc_dirty_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DATA_UNC:
+        m_cost_unc_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() ) 
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for data read uncached");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+        else
+        {
+            r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+            r_dcache_buf_unc_valid = true;
+        }
+        r_dcache_unc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+        break;
+
+    case RSP_DATA_MISS:
+        m_cost_dmiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                    "illegal VCI response packet for data read miss");
+            r_dcache_miss_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        } 
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_data_error = true;
+        }
+        break;
+
+    case RSP_DATA_WRITE:
+        m_cost_write_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            r_vci_rsp_fsm = RSP_IDLE;
+            r_dcache_write_req = false;
+        }
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            m_iss.setWriteBerr();
+        }
+        break;
+    } // end switch r_vci_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////
+    //     VCI_CMD_CLEANUP FSM 
+    //
+    // This FSM handles requests from both the DCACHE controler
+    // (request registers) and the ICACHE controler (request registers).
+    // There is 10 VCI transaction types :
+    // - INS_TLB_READ
+    // - INS_TLB_WRITE
+    // - INS_MISS
+    // - INS_UNC_MISS
+    // - DATA_TLB_READ
+    // - DATA_TLB_WRITE
+    // - DATA_TLB_DIRTY
+    // - DATA_MISS
+    // - DATA_UNC 
+    // - DATA_WRITE
+    // The ICACHE requests have the highest priority.
+    // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM and RSP_FSM
+    // exit simultaneously the IDLE state.
+    //////////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_cmd_cleanup_fsm) {
+    
+    case CMD_CLEANUP_INS_IDLE:
+        if ((r_vci_rsp_cleanup_fsm != RSP_CLEANUP_INS_IDLE) && (r_vci_rsp_cleanup_fsm != RSP_CLEANUP_DATA_IDLE))
+            break;
+
+        if (r_icache_cleanup_req)           
+        {            
+            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_INS;
+            //m_cpt_ins_cleanup_transaction++; 
+        } 
+        else if (r_dcache_cleanup_req)      
+        {  
+            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_DATA;
+            //m_cpt_data_cleanup_transaction++; 
+        } 
+        break;
+
+    case CMD_CLEANUP_DATA_IDLE:
+        if ((r_vci_rsp_cleanup_fsm != RSP_CLEANUP_INS_IDLE) && (r_vci_rsp_cleanup_fsm != RSP_CLEANUP_DATA_IDLE))
+            break;
+
+        if (r_dcache_cleanup_req)           
+        {           
+            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_DATA;
+            //m_cpt_data_cleanup_transaction++; 
+        } 
+        else if (r_icache_cleanup_req)      
+        {  
+            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_INS;
+            //m_cpt_ins_cleanup_transaction++; 
+        } 
+        break;
+
+    case CMD_CLEANUP_INS:
+        if ( p_vci_ini_c.cmdack.read() )
+        {  
+            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_DATA_IDLE;
+        }
+	break;
+
+    case CMD_CLEANUP_DATA:
+        if ( p_vci_ini_c.cmdack.read() )
+        {  
+            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_INS_IDLE;
+        }
+	break;
+    } // end  switch r_vci_cmd_cleanup_fsm
+
+    //////////////////////////////////////////////////////////////////////////
+    //      VCI_RSP FSM 
+    //
+    // This FSM is synchronized with the VCI_CMD FSM, as both FSMs exit the
+    // IDLE state simultaneously.
+    //////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_rsp_cleanup_fsm) {
+
+    case RSP_CLEANUP_INS_IDLE:
+        assert( ! p_vci_ini_c.rspval.read() && "Unexpected response" );
+
+        if ((r_vci_cmd_cleanup_fsm != CMD_CLEANUP_INS_IDLE) && (r_vci_cmd_cleanup_fsm != CMD_CLEANUP_DATA_IDLE)) 
+            break;
+
+        if (r_icache_cleanup_req)
+        {
+            r_vci_rsp_cleanup_fsm = RSP_CLEANUP_INS;
+        }
+        else if (r_dcache_cleanup_req)
+        {
+            r_vci_rsp_cleanup_fsm = RSP_CLEANUP_DATA;
+        }
+        break;
+
+    case RSP_CLEANUP_DATA_IDLE:
+        assert( ! p_vci_ini_c.rspval.read() && "Unexpected response" );
+
+        if ((r_vci_cmd_cleanup_fsm != CMD_CLEANUP_INS_IDLE) && (r_vci_cmd_cleanup_fsm != CMD_CLEANUP_DATA_IDLE)) 
+            break;
+
+        if (r_dcache_cleanup_req)
+        {
+            r_vci_rsp_cleanup_fsm = RSP_CLEANUP_DATA;
+        }
+        else if (r_icache_cleanup_req)
+        {
+            r_vci_rsp_cleanup_fsm = RSP_CLEANUP_INS;
+        }
+        break;
+
+    case RSP_CLEANUP_INS:
+        if ( ! p_vci_ini_c.rspval.read() )
+            break;
+        assert( p_vci_ini_c.reop.read() &&
+                "illegal VCI CLEANUP response packet for icache cleanup");
+        assert( (p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL) &&
+                "error in response packet for icache cleanup");
+
+        r_icache_cleanup_req = false;
+        r_vci_rsp_cleanup_fsm = RSP_CLEANUP_DATA_IDLE;
+        break;
+
+    case RSP_CLEANUP_DATA:
+        if ( ! p_vci_ini_c.rspval.read() )
+            break;
+        assert( p_vci_ini_c.reop.read() &&
+                "illegal VCI CLEANUP response packet for icache cleanup");
+        assert( (p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL) &&
+                "error in response packet for icache cleanup");
+
+        r_dcache_cleanup_req = false;
+        r_vci_rsp_cleanup_fsm = RSP_CLEANUP_INS_IDLE;
+        break;
+
+    } // end switch r_vci_rsp_cleanup_fsm
+} // end transition()
+
+///////////////////////
+tmpl(void)::genMoore()
+///////////////////////
+{
+    // VCI initiator response
+
+    p_vci_ini_rw.rspack = true;
+
+    // VCI initiator command
+
+    p_vci_ini_rw.pktid  = 0;
+    p_vci_ini_rw.srcid  = m_srcid_rw;
+    p_vci_ini_rw.cons   = false;
+    p_vci_ini_rw.wrap   = false;
+    p_vci_ini_rw.contig = true;
+    p_vci_ini_rw.clen   = 0;
+    p_vci_ini_rw.cfixed = false;
+
+    switch (r_vci_cmd_fsm) {
+
+    case CMD_IDLE:
+        p_vci_ini_rw.cmdval  = false;
+        p_vci_ini_rw.address = 0;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0;
+        p_vci_ini_rw.trdid   = 0;
+        p_vci_ini_rw.plen    = 0;
+        p_vci_ini_rw.cmd     = vci_param::CMD_NOP;
+        p_vci_ini_rw.eop     = false;
+        break;
+
+    case CMD_ITLB_READ:     
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & m_dcache_yzmask;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 1; // via data cache cached read
+        p_vci_ini_rw.plen    = m_dcache_words << 2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+
+    case CMD_ITLB_ACC_LL:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & ~0x3;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini_rw.eop     = true;
+	break;
+
+    case CMD_ITLB_ACC_SC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & ~0x3;
+        p_vci_ini_rw.wdata   = r_icache_pte_update.read();
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_STORE_COND;
+        p_vci_ini_rw.eop     = true;
+	break;	
+
+    case CMD_INS_MISS:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & m_icache_yzmask;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 3; // ins cache cached read
+        p_vci_ini_rw.plen    = m_icache_words << 2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+
+    case CMD_INS_UNC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & ~0x3;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 2; // ins cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+
+    case CMD_DTLB_READ:     
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & m_dcache_yzmask;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 1; // via dcache cached read
+        p_vci_ini_rw.plen    = m_dcache_words << 2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+
+    case CMD_DTLB_ACC_LL:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini_rw.eop     = true;
+	break;
+
+    case CMD_DTLB_ACC_SC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini_rw.wdata   = r_dcache_pte_update.read();
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_STORE_COND;
+        p_vci_ini_rw.eop     = true;
+	break;	
+
+    case CMD_DTLB_DIRTY_LL:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini_rw.eop     = true;
+	break;
+
+    case CMD_DTLB_DIRTY_SC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini_rw.wdata   = r_dcache_pte_update.read();
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_STORE_COND;
+        p_vci_ini_rw.eop     = true;
+	break;	
+
+    case CMD_DATA_UNC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_paddr_save.read() & ~0x3;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.eop     = true;
+        switch(r_dcache_type_save) {
+        case iss_t::DATA_READ:
+            p_vci_ini_rw.wdata = 0;
+            p_vci_ini_rw.be    = r_dcache_be_save.read();
+            p_vci_ini_rw.cmd   = vci_param::CMD_READ;
+            break;
+        case iss_t::DATA_LL:
+            p_vci_ini_rw.wdata = 0;
+            p_vci_ini_rw.be    = 0xF;
+            p_vci_ini_rw.cmd   = vci_param::CMD_LOCKED_READ;
+            break;
+        case iss_t::DATA_SC:
+            p_vci_ini_rw.wdata = r_dcache_wdata_save.read();
+            p_vci_ini_rw.be    = 0xF;
+            p_vci_ini_rw.cmd   = vci_param::CMD_STORE_COND;
+            break;
+        default:
+            assert("this should not happen");
+        }
+        break;
+
+    case CMD_DATA_WRITE:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_wbuf.getAddress(r_vci_cmd_cpt);
+        p_vci_ini_rw.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
+        p_vci_ini_rw.be      = r_wbuf.getBe(r_vci_cmd_cpt);
+        p_vci_ini_rw.trdid   = 0; // data cache write
+        p_vci_ini_rw.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_WRITE;
+        p_vci_ini_rw.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
+        break;
+
+    case CMD_DATA_MISS:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_paddr_save.read() & m_dcache_yzmask;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 1; // data cache cached read
+        p_vci_ini_rw.plen    = m_dcache_words << 2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+    } // end switch r_vci_cmd_fsm
+
+    // VCI initiator response
+
+    p_vci_ini_c.rspack = true;
+
+    // VCI initiator command
+
+    p_vci_ini_c.pktid  = 0;
+    p_vci_ini_c.srcid  = m_srcid_c;
+    p_vci_ini_c.cons   = false;
+    p_vci_ini_c.wrap   = false;
+    p_vci_ini_c.contig = true;
+    p_vci_ini_c.clen   = 0;
+    p_vci_ini_c.cfixed = false;
+
+    switch (r_vci_cmd_cleanup_fsm) {
+
+    case CMD_CLEANUP_INS_IDLE:
+    case CMD_CLEANUP_DATA_IDLE:
+        p_vci_ini_c.cmdval  = false;
+        p_vci_ini_c.address = 0;
+        p_vci_ini_c.wdata   = 0;
+        p_vci_ini_c.be      = 0;
+        p_vci_ini_c.trdid   = 0;
+        p_vci_ini_c.plen    = 0;
+        p_vci_ini_c.cmd     = vci_param::CMD_NOP;
+        p_vci_ini_c.eop     = false;
+        break;
+
+    case CMD_CLEANUP_INS:
+    case CMD_CLEANUP_DATA:
+        p_vci_ini_c.cmdval = true;
+        if ( r_vci_cmd_cleanup_fsm == CMD_CLEANUP_INS ) p_vci_ini_c.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
+        else                                            p_vci_ini_c.address = r_dcache_cleanup_line.read() * (m_dcache_words<<2);
+        p_vci_ini_c.wdata  = 0;
+        p_vci_ini_c.be     = 0;
+        p_vci_ini_c.trdid  = 1; // cleanup for distinguish from a write
+        p_vci_ini_c.plen   = 4;
+        p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+        p_vci_ini_c.contig = false;
+        p_vci_ini_c.eop    = true;
+        break;
+
+    } // end switch r_vci_cmd_cleanup_fsm
+
+    // VCI_TGT
+    switch ( r_vci_tgt_fsm.read() ) {
+
+    case TGT_IDLE:
+    case TGT_UPDT_WORD:
+    case TGT_UPDT_DATA:
+        p_vci_tgt.cmdack  = true;
+        p_vci_tgt.rspval  = false;
+        break;
+
+    case TGT_RSP_BROADCAST:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
+        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+        p_vci_tgt.rpktid  = r_tgt_pktid.read();
+        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = true;
+        break;
+
+    case TGT_RSP_DCACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = !r_tgt_dcache_req.read();
+        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+        p_vci_tgt.rpktid  = r_tgt_pktid.read();
+        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = true;
+        break;
+
+    case TGT_REQ_BROADCAST:
+    case TGT_REQ_DCACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = false;
+        break;
+
+    } // end switch TGT_FSM
+
+#ifdef SOCLIB_MODULE_DEBUG 
+   std::cout << name() 
+      	     << "Moore:" << std::hex
+      	     << " p_vci_ini_rw.cmdval: " << p_vci_ini_rw.cmdval
+      	     << " p_vci_ini_rw.address: " << p_vci_ini_rw.address
+      	     << " p_vci_ini_rw.wdata: " << p_vci_ini_rw.wdata
+      	     << " p_vci_ini_rw.cmd: " << p_vci_ini_rw.cmd
+      	     << " p_vci_ini_rw.eop: " << p_vci_ini_rw.eop
+      	     << std::endl;
+
+   std::cout << name() 
+             << "Moore:" << std::hex
+             << " p_vci_ini_c.cmdval: " << p_vci_ini_c.cmdval
+             << " p_vci_ini_c.address: " << p_vci_ini_c.address
+             << " p_vci_ini_c.wdata: " << p_vci_ini_c.wdata
+             << " p_vci_ini_c.cmd: " << p_vci_ini_c.cmd
+             << " p_vci_ini_c.eop: " << p_vci_ini_c.eop
+             << std::endl;
+#endif
+
+}
+
+}}
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
+
+
+
+
+
+
+
Index: trunk/modules/vci_cc_vcache_wrapper2_v1/caba/metadata/vci_cc_vcache_wrapper2_v1.sd
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper2_v1/caba/metadata/vci_cc_vcache_wrapper2_v1.sd	(revision 2)
+++ trunk/modules/vci_cc_vcache_wrapper2_v1/caba/metadata/vci_cc_vcache_wrapper2_v1.sd	(revision 2)
@@ -0,0 +1,62 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_cc_vcache_wrapper2_v1',
+	classname = 'soclib::caba::VciCcVCacheWrapper2V1',
+	   tmpl_parameters = [
+	parameter.Module('vci_param', default = 'caba:vci_param'),
+	parameter.Module('iss_t'),
+	],
+	header_files = [
+	'../source/include/vci_cc_vcache_wrapper2_v1.h',
+	],
+	implementation_files = [
+	'../source/src/vci_cc_vcache_wrapper2_v1.cpp',
+	],
+	uses = [
+	Uses('caba:base_module'),
+	Uses('caba:write_buffer'),
+	Uses('caba:generic_tlb', addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', parameter.Reference('addr_size'))),
+	Uses('caba:generic_cache', addr_t = parameter.StringExt('sc_dt::sc_uint<%d> ', parameter.Reference('addr_size'))),
+	Uses('common:address_masking_table', data_t = parameter.StringExt('sc_dt::sc_uint<%d> ', parameter.Reference('addr_size'))),
+	Uses('common:iss2'),
+	Uses('common:mapping_table'),
+	],
+	ports = [
+	Port('caba:vci_initiator', 'p_vci_ini_rw'),
+	Port('caba:vci_initiator', 'p_vci_ini_c'),
+	Port('caba:vci_target', 'p_vci_tgt'),
+	Port('caba:bit_in','p_irq', parameter.Constant('n_irq')),
+	Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+	Port('caba:clock_in', 'p_clk', auto = 'clock'),
+	],
+	instance_parameters = [
+	parameter.Int('proc_id'),
+	parameter.Module('mt', 'common:mapping_table', auto='env:mapping_table'),
+	parameter.Module('mc', 'common:mapping_table', auto='env:mapping_table'),
+	parameter.IntTab('initiator_rw_index'),
+	parameter.IntTab('initiator_c_index'),
+	parameter.IntTab('target_index'),
+    	parameter.Int('itlb_ways'),
+    	parameter.Int('itlb_sets'),
+    	parameter.Int('dtlb_ways'),
+    	parameter.Int('dtlb_sets'),
+    	parameter.Int('icache_ways'),
+    	parameter.Int('icache_sets'),
+    	parameter.Int('icache_words'),
+    	parameter.Int('dcache_ways'),
+    	parameter.Int('dcache_sets'),
+    	parameter.Int('dcache_words'),
+    	parameter.Int('write_buf_size'),
+	],
+	   extensions = [
+	'dsx:get_ident=initiator_index:p_vci_ini_rw',
+	'dsx:cpu=wrapper:iss_t',
+	'dsx:mapping_type=processor:proc_id',
+   ],
+)
+
+
Index: trunk/modules/vci_cc_vcache_wrapper2_v1/caba/source/include/vci_cc_vcache_wrapper2_v1.h
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper2_v1/caba/source/include/vci_cc_vcache_wrapper2_v1.h	(revision 2)
+++ trunk/modules/vci_cc_vcache_wrapper2_v1/caba/source/include/vci_cc_vcache_wrapper2_v1.h	(revision 2)
@@ -0,0 +1,562 @@
+/* -*- c++ -*-
+ * File : vci_cc_vcache_wrapper2_v1.h
+ * Copyright (c) UPMC, Lip6, SoC
+ * Authors : Alain GREINER, Yang GAO
+ *
+ * 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
+ */
+ 
+#ifndef SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER2_V1_H
+#define SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER2_V1_H
+
+#include <inttypes.h>
+#include <systemc>
+#include "caba_base_module.h"
+#include "write_buffer.h"
+#include "generic_cache.h"
+#include "vci_initiator.h"
+#include "vci_target.h"
+#include "mapping_table.h"
+#include "generic_tlb.h"
+#include "static_assert.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+////////////////////////////////////////////
+template<typename vci_param, typename iss_t>
+class VciCcVCacheWrapper2V1
+////////////////////////////////////////////
+    : public soclib::caba::BaseModule
+{
+    typedef uint32_t vaddr_t;
+    typedef uint32_t data_t;
+    typedef uint32_t tag_t;
+    typedef uint32_t type_t;
+    typedef typename iss_t::DataOperationType data_op_t;
+
+    typedef typename vci_param::addr_t  paddr_t;
+    typedef typename vci_param::be_t    vci_be_t;
+	typedef typename vci_param::srcid_t vci_srcid_t;
+	typedef typename vci_param::trdid_t vci_trdid_t;
+	typedef typename vci_param::pktid_t vci_pktid_t;
+	typedef typename vci_param::plen_t  vci_plen_t;
+
+    enum icache_fsm_state_e {  
+        ICACHE_IDLE,                // 00
+        ICACHE_BIS,                 // 01
+        ICACHE_TLB1_READ,           // 02
+        ICACHE_TLB1_WRITE,          // 03
+        ICACHE_TLB1_UPDT,           // 04
+        ICACHE_TLB2_READ,           // 05
+        ICACHE_TLB2_WRITE,          // 06
+        ICACHE_TLB2_UPDT,           // 07
+        ICACHE_SW_FLUSH,            // 08
+        ICACHE_TLB_FLUSH,           // 09
+        ICACHE_CACHE_FLUSH,         // 0a
+        ICACHE_TLB_INVAL,           // 0b
+        ICACHE_CACHE_INVAL,         // 0c
+        ICACHE_CACHE_INVAL_PA,      // 0d
+        ICACHE_MISS_WAIT,           // 0e
+        ICACHE_UNC_WAIT,            // 0f
+        ICACHE_MISS_UPDT,           // 10
+        ICACHE_ERROR,               // 11
+        ICACHE_CC_INVAL,            // 12
+        ICACHE_TLB_CC_INVAL,        // 13
+    };
+
+    enum dcache_fsm_state_e {  
+        DCACHE_IDLE,                // 00
+        DCACHE_BIS,                 // 01
+        DCACHE_DTLB1_READ_CACHE,    // 02
+        DCACHE_TLB1_LL_WAIT,        // 03
+        DCACHE_TLB1_SC_WAIT,        // 04
+        DCACHE_TLB1_READ,           // 05
+        DCACHE_TLB1_READ_UPDT,      // 06
+        DCACHE_TLB1_UPDT,           // 07
+        DCACHE_DTLB2_READ_CACHE,    // 08
+        DCACHE_TLB2_LL_WAIT,        // 09
+        DCACHE_TLB2_SC_WAIT,        // 0a
+        DCACHE_TLB2_READ,           // 0b
+        DCACHE_TLB2_READ_UPDT,      // 0c
+        DCACHE_TLB2_UPDT,           // 0d
+        DCACHE_CTXT_SWITCH,         // 0e
+        DCACHE_ICACHE_FLUSH,        // 0f
+        DCACHE_DCACHE_FLUSH,        // 10
+        DCACHE_ITLB_INVAL,          // 11
+        DCACHE_DTLB_INVAL,          // 12
+        DCACHE_ICACHE_INVAL,        // 13
+        DCACHE_DCACHE_INVAL,        // 14
+	    DCACHE_ICACHE_INVAL_PA,     // 15
+	    DCACHE_DCACHE_INVAL_PA,     // 16
+        DCACHE_DCACHE_SYNC,         // 17
+        DCACHE_LL_DIRTY_WAIT,       // 18
+        DCACHE_SC_DIRTY_WAIT,       // 19
+        DCACHE_WRITE_UPDT,          // 1a
+        DCACHE_WRITE_DIRTY,         // 1b
+        DCACHE_WRITE_REQ,           // 1c
+        DCACHE_MISS_WAIT,           // 1d
+        DCACHE_MISS_UPDT,           // 1e
+        DCACHE_UNC_WAIT,            // 1f
+        DCACHE_ERROR,               // 20
+        DCACHE_ITLB_READ,           // 21
+        DCACHE_ITLB_UPDT,           // 22
+        DCACHE_ITLB_LL_WAIT,        // 23
+        DCACHE_ITLB_SC_WAIT,        // 24
+        DCACHE_CC_CHECK,            // 25
+        DCACHE_CC_INVAL,            // 26
+        DCACHE_CC_UPDT,             // 27
+        DCACHE_CC_NOP,              // 28
+        DCACHE_TLB_CC_INVAL,        // 29
+        DCACHE_ITLB_CLEANUP,        // 2a
+    };
+
+    enum cmd_fsm_state_e {      
+        CMD_IDLE,                   // 00
+        CMD_ITLB_READ,              // 01
+        CMD_ITLB_ACC_LL,            // 02
+        CMD_ITLB_ACC_SC,            // 03
+        CMD_INS_MISS,               // 04
+        CMD_INS_UNC,                // 05
+        CMD_DTLB_READ,              // 06
+        CMD_DTLB_ACC_LL,            // 07
+        CMD_DTLB_ACC_SC,            // 08
+        CMD_DTLB_DIRTY_LL,          // 09
+        CMD_DTLB_DIRTY_SC,          // 0a
+        CMD_DATA_UNC,               // 0b
+        CMD_DATA_MISS,              // 0c
+        CMD_DATA_WRITE,             // 0d
+        CMD_INS_CLEANUP,            // 0e
+        CMD_DATA_CLEANUP,           // 0f
+    };
+
+    enum rsp_fsm_state_e {       
+        RSP_IDLE,                   // 00
+        RSP_ITLB_READ,              // 01
+        RSP_ITLB_ACC_LL,            // 02
+        RSP_ITLB_ACC_SC,            // 03
+        RSP_INS_MISS,               // 04
+        RSP_INS_UNC,                // 05
+        RSP_DTLB_READ,              // 06
+        RSP_DTLB_ACC_LL,            // 07
+        RSP_DTLB_ACC_SC,            // 08
+        RSP_DTLB_DIRTY_LL,          // 09
+        RSP_DTLB_DIRTY_SC,          // 0a
+        RSP_DATA_MISS,              // 0b
+        RSP_DATA_UNC,               // 0c
+        RSP_DATA_WRITE,             // 0d
+        RSP_INS_CLEANUP,            // 0e
+        RSP_DATA_CLEANUP,           // 0f
+    };
+
+    enum tgt_fsm_state_e {  
+        TGT_IDLE,                   // 00
+        TGT_UPDT_WORD,              // 01
+        TGT_UPDT_DATA,              // 02
+        TGT_REQ_BROADCAST,          // 03
+        TGT_REQ_ICACHE,             // 04
+        TGT_REQ_DCACHE,             // 05
+        TGT_RSP_BROADCAST,          // 06
+        TGT_RSP_ICACHE,             // 07
+        TGT_RSP_DCACHE,             // 08
+    };
+
+    enum inval_itlb_fsm_state_e {
+        INVAL_ITLB_IDLE,            // 00
+        INVAL_ITLB_CHECK,           // 01
+        INVAL_ITLB_INVAL,           // 02
+        INVAL_ITLB_CLEAR,           // 03
+    };
+
+    enum inval_dtlb_fsm_state_e {
+        INVAL_DTLB_IDLE,            // 00
+        INVAL_DTLB_CHECK,           // 01
+        INVAL_DTLB_INVAL,           // 02
+        INVAL_DTLB_CLEAR,           // 03
+    };
+
+    // TLB Mode ITLB / DTLB / ICACHE / DCACHE
+    enum {          
+        ALL_DEACTIVE = 0x0000,   // TLBs disactive caches disactive
+        INS_TLB_MASK    = 0x8,
+        DATA_TLB_MASK   = 0x4,
+        INS_CACHE_MASK  = 0x2,
+        DATA_CACHE_MASK = 0x1,
+    };
+
+    // Error Type
+    enum mmu_error_type_e {
+        MMU_NONE                      = 0x0000, // None
+        MMU_WRITE_PT1_UNMAPPED 	      = 0x0001, // Write access of Page fault on Page Table 1          (non fatal error)
+        MMU_WRITE_PT2_UNMAPPED 	      = 0x0002, // Write access of Page fault on Page Table 2          (non fatal error)
+        MMU_WRITE_PRIVILEGE_VIOLATION = 0x0004, // Write access of Protected access in user mode       (user error)
+        MMU_WRITE_ACCES_VIOLATION 	  = 0x0008, // Write access of write access to a non writable page (user error)
+        MMU_WRITE_UNDEFINED_XTN 	  = 0x0020, // Write access of undefined external access address   (user error)
+        MMU_WRITE_PT1_ILLEGAL_ACCESS  = 0x0040, // Write access of Bus Error accessing Table 1         (kernel error)
+        MMU_WRITE_PT2_ILLEGAL_ACCESS  = 0x0080, // Write access of Bus Error accessing Table 2         (kernel error)
+        MMU_WRITE_DATA_ILLEGAL_ACCESS = 0x0100, // Write access of Bus Error in cache access           (kernel error)
+        MMU_READ_PT1_UNMAPPED 	      = 0x1001, // Read access of Page fault on Page Table 1  	       (non fatal error)
+        MMU_READ_PT2_UNMAPPED 	      = 0x1002, // Read access of Page fault on Page Table 2  	       (non fatal error)
+        MMU_READ_PRIVILEGE_VIOLATION  = 0x1004, // Read access of Protected access in user mode 	   (user error)
+        MMU_READ_EXEC_VIOLATION 	  = 0x1010, // Exec access to a non exec page                      (user error)
+        MMU_READ_UNDEFINED_XTN 	      = 0x1020, // Read access of Undefined external access address    (user error)
+        MMU_READ_PT1_ILLEGAL_ACCESS   = 0x1040, // Read access of Bus Error in Table1 access           (kernel error)
+        MMU_READ_PT2_ILLEGAL_ACCESS   = 0x1080, // Read access of Bus Error in Table2 access 	       (kernel error)
+        MMU_READ_DATA_ILLEGAL_ACCESS  = 0x1100, // Read access of Bus Error in cache access 	       (kernel error)
+    };
+
+public:
+    sc_in<bool>                             p_clk;
+    sc_in<bool>                             p_resetn;
+    sc_in<bool>                             p_irq[iss_t::n_irq];
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_rw;
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_c;
+    soclib::caba::VciTarget<vci_param>      p_vci_tgt;
+
+private:
+    // STRUCTURAL PARAMETERS
+    soclib::common::AddressDecodingTable<uint32_t, bool>    m_cacheability_table;
+    const soclib::common::Segment                           m_segment;
+    iss_t                                                   m_iss;   
+    const vci_srcid_t                                       m_srcid_rw;
+    const vci_srcid_t                                       m_srcid_c;
+
+    const size_t  m_itlb_ways;
+    const size_t  m_itlb_sets;
+
+    const size_t  m_dtlb_ways;
+    const size_t  m_dtlb_sets;
+
+    const size_t  m_icache_ways;
+    const size_t  m_icache_sets;
+    const size_t  m_icache_yzmask;
+    const size_t  m_icache_words;
+
+    const size_t  m_dcache_ways;
+    const size_t  m_dcache_sets;
+    const size_t  m_dcache_yzmask;
+    const size_t  m_dcache_words;
+
+    const size_t  m_write_buf_size;  
+    const size_t  m_paddr_nbits;  
+
+    // instruction and data vcache tlb instances 
+    soclib::caba::GenericCcTlb<paddr_t>    icache_tlb;
+    soclib::caba::GenericCcTlb<paddr_t>    dcache_tlb;
+
+    sc_signal<vaddr_t>      r_mmu_ptpr;             // page table pointer register
+    sc_signal<int>          r_mmu_mode;             // tlb mode register
+    sc_signal<int>          r_mmu_params;           // mmu parameters register
+    sc_signal<int>          r_mmu_release;          // mmu release register
+    sc_signal<int>          r_mmu_word_lo;          // mmu misc data low
+    sc_signal<int>          r_mmu_word_hi;          // mmu mmu misc data hight
+
+    // DCACHE FSM REGISTERS
+    sc_signal<int>          r_dcache_fsm;               // state register
+    sc_signal<paddr_t>      r_dcache_paddr_save;        // physical address
+    sc_signal<data_t>       r_dcache_wdata_save;        // write data
+    sc_signal<data_t>       r_dcache_rdata_save;        // read data
+    sc_signal<type_t>       r_dcache_type_save;         // access type
+    sc_signal<vci_be_t>     r_dcache_be_save;           // byte enable
+    sc_signal<bool>         r_dcache_cached_save;       // used by the write buffer
+    sc_signal<paddr_t>      r_dcache_tlb_paddr;         // physical address of tlb miss
+    sc_signal<bool>         r_dcache_dirty_save;        // used for TLB dirty bit update
+    sc_signal<size_t>       r_dcache_tlb_set_save;      // used for TLB dirty bit update
+    sc_signal<size_t>       r_dcache_tlb_way_save;      // used for TLB dirty bit update
+    sc_signal<vaddr_t>      r_dcache_id1_save;          // used by the PT1 bypass
+    sc_signal<paddr_t>      r_dcache_ptba_save;         // used by the PT1 bypass
+    sc_signal<bool>         r_dcache_ptba_ok;           // used by the PT1 bypass
+    sc_signal<data_t>       r_dcache_pte_update;        // used for page table update
+    sc_signal<data_t>       r_dcache_ppn_update;        // used for physical page number update 
+    sc_signal<tag_t>        r_dcache_ppn_save;          // used for speculative cache access
+    sc_signal<tag_t>        r_dcache_vpn_save;          // used for speculative cache access
+    sc_signal<bool>         r_dtlb_translation_valid;   // used for speculative address
+    sc_signal<bool>         r_dcache_buf_unc_valid;     // used for uncached read
+    sc_signal<bool>         r_dcache_hit_p_save;        // used to save hit_p in case BIS
+
+    sc_signal<data_t>       r_dcache_error_type;        // software visible register
+    sc_signal<vaddr_t>      r_dcache_bad_vaddr;         // software visible register 
+
+    sc_signal<bool>         r_dcache_miss_req;          // used for cached read miss
+    sc_signal<bool>         r_dcache_unc_req;           // used for uncached read miss
+    sc_signal<bool>         r_dcache_write_req;         // used for write 
+    sc_signal<bool>         r_dcache_tlb_read_req;      // used for tlb ptba or pte read
+
+    sc_signal<bool>         r_dcache_llsc_reserved;     // used for check address reserved
+    sc_signal<paddr_t>      r_dcache_llsc_addr_save;    // used for save llsc address
+ 
+    sc_signal<bool>         r_dcache_tlb_ll_acc_req;    // used for tlb access bit update
+    sc_signal<bool>         r_dcache_tlb_sc_acc_req;    // used for tlb access bit update
+    sc_signal<bool>         r_dcache_tlb_ll_dirty_req;  // used for tlb dirty bit update 
+    sc_signal<bool>         r_dcache_tlb_sc_dirty_req;  // used for tlb dirty bit update 
+    sc_signal<bool>         r_dcache_tlb_ptba_read;     // used for tlb ptba read when write dirty bit 
+    sc_signal<bool>         r_dcache_xtn_req;           // used for xtn write for ICACHE
+
+    bool                    *r_dcache_in_itlb;          // indicates some words of dcache line in ins TLB 
+    bool                    *r_dcache_in_dtlb;          // indicates some words of dcache line in data TLB 
+
+    // coherence registers
+    sc_signal<int>          r_dcache_fsm_save;          // state save register
+    sc_signal<size_t>       r_dcache_way;
+    sc_signal<size_t>       r_dcache_set;
+    sc_signal<bool>         r_dcache_cleanup_req;       // data cleanup request
+    sc_signal<paddr_t>      r_dcache_cleanup_line;      // data cleanup NLINE
+    sc_signal<bool>         r_dcache_inval_rsp;         // data cache invalidate
+
+    // ICACHE FSM REGISTERS
+    sc_signal<int>          r_icache_fsm;               // state register
+    sc_signal<paddr_t>      r_icache_paddr_save;        // physical address
+    sc_signal<vaddr_t>      r_icache_id1_save;          // used by the PT1 bypass
+    sc_signal<paddr_t>      r_icache_ptba_save;         // used by the PT1 bypass
+    sc_signal<bool>         r_icache_ptba_ok;           // used by the PT1 bypass
+    sc_signal<data_t>       r_icache_pte_update;        // used for page table update
+    sc_signal<tag_t>        r_icache_ppn_save;          // used for speculative cache access
+    sc_signal<tag_t>        r_icache_vpn_save;          // used for speculative cache access
+    sc_signal<bool>         r_itlb_translation_valid;   // used for speculative physical address
+    sc_signal<bool>         r_icache_buf_unc_valid;     // used for uncached read
+
+    sc_signal<data_t>       r_icache_error_type;        // software visible registers
+    sc_signal<vaddr_t>      r_icache_bad_vaddr;         // software visible registers
+
+    sc_signal<bool>         r_icache_miss_req;          // used for cached read miss
+    sc_signal<bool>         r_icache_unc_req;           // used for uncached read miss
+    sc_signal<bool>         r_dcache_itlb_read_req;     // used for tlb ptba or pte read 
+
+    sc_signal<bool>         r_dcache_itlb_ll_acc_req;   // used for tlb access bit update
+    sc_signal<bool>         r_dcache_itlb_sc_acc_req;   // used for tlb access bit update
+
+    sc_signal<bool>	        r_itlb_read_dcache_req;     // used for instruction tlb miss, request in data cache
+    sc_signal<bool>	        r_itlb_k_read_dcache;       // used for instruction tlb miss, request in data cache
+    sc_signal<bool>	        r_itlb_acc_dcache_req;      // used for itlb update access bit via dcache
+    sc_signal<bool>	        r_dcache_rsp_itlb_error;    // used for data cache rsp error when itlb miss
+    sc_signal<data_t>	    r_dcache_rsp_itlb_miss;	    // used for dcache rsp data when itlb miss
+    sc_signal<data_t>	    r_dcache_rsp_itlb_ppn;	    // used for dcache rsp ppn when itlb miss
+    sc_signal<vaddr_t>      r_icache_vaddr_req;			// virtual address requested by the CPU
+
+    // coherence registers
+    sc_signal<int>          r_icache_fsm_save;          // state save register
+    sc_signal<size_t>       r_icache_way;
+    sc_signal<size_t>       r_icache_set;
+    sc_signal<bool>         r_icache_cleanup_req;       // ins cleanup request
+    sc_signal<paddr_t>      r_icache_cleanup_line;      // ins cleanup NLINE
+    sc_signal<bool>         r_icache_inval_rsp;         // ins cache invalidate
+
+    // VCI_CMD FSM REGISTERS
+    sc_signal<int>          r_vci_cmd_fsm;
+    sc_signal<size_t>       r_vci_cmd_min;       
+    sc_signal<size_t>       r_vci_cmd_max;       
+    sc_signal<size_t>       r_vci_cmd_cpt;     
+
+    // VCI_RSP FSM REGISTERS
+    sc_signal<int>          r_vci_rsp_fsm;
+    sc_signal<size_t>       r_vci_rsp_cpt;
+    sc_signal<bool>         r_vci_rsp_ins_error;
+    sc_signal<bool>         r_vci_rsp_data_error;
+
+    data_t                  *r_icache_miss_buf;    
+    data_t                  *r_dcache_miss_buf;  
+
+    // VCI_TGT FSM REGISTERS
+    data_t                  *r_tgt_buf;
+    bool                    *r_tgt_val;
+
+    sc_signal<int>          r_vci_tgt_fsm;
+    sc_signal<paddr_t>      r_tgt_addr;
+    sc_signal<size_t>       r_tgt_word;
+    sc_signal<bool>         r_tgt_update;
+    sc_signal<vci_srcid_t>  r_tgt_srcid;
+    sc_signal<vci_pktid_t>  r_tgt_pktid;
+    sc_signal<vci_trdid_t>  r_tgt_trdid;
+    sc_signal<vci_plen_t>   r_tgt_plen;
+    sc_signal<bool>         r_tgt_req;
+    sc_signal<bool>         r_tgt_icache_req;
+    sc_signal<bool>         r_tgt_dcache_req;
+    sc_signal<bool>         r_tgt_icache_rsp;
+    sc_signal<bool>         r_tgt_dcache_rsp;
+
+    // INVAL CHECK FSM
+    sc_signal<int>          r_inval_itlb_fsm;          
+    sc_signal<bool>         r_dcache_itlb_inval_req;
+    sc_signal<paddr_t>      r_dcache_itlb_inval_line;
+    sc_signal<bool>         r_itlb_cc_check_end;
+    sc_signal<size_t>       r_ccinval_itlb_way; 
+    sc_signal<size_t>       r_ccinval_itlb_set; 
+    sc_signal<bool>         r_icache_inval_tlb_rsp;
+    sc_signal<paddr_t>      r_icache_tlb_nline;
+
+    sc_signal<int>          r_inval_dtlb_fsm;          
+    sc_signal<bool>         r_dcache_dtlb_inval_req;
+    sc_signal<paddr_t>      r_dcache_dtlb_inval_line;
+    sc_signal<bool>         r_dtlb_cc_check_end;
+    sc_signal<size_t>       r_ccinval_dtlb_way; 
+    sc_signal<size_t>       r_ccinval_dtlb_set; 
+    sc_signal<bool>         r_dcache_inval_tlb_rsp;
+    sc_signal<paddr_t>      r_dcache_tlb_nline;
+
+    sc_signal<bool>         r_dcache_itlb_cleanup_req;
+    sc_signal<paddr_t>      r_dcache_itlb_cleanup_line;
+
+    sc_signal<bool>         r_dcache_dtlb_cleanup_req;
+    sc_signal<paddr_t>      r_dcache_dtlb_cleanup_line;
+
+    sc_signal<bool>         r_itlb_inval_req;
+    sc_signal<bool>         r_dcache_cc_check;
+
+    WriteBuffer<paddr_t>     r_wbuf;
+    GenericCache<paddr_t>    r_icache;
+    GenericCache<paddr_t>    r_dcache;
+
+    // Activity counters
+    uint32_t m_cpt_dcache_data_read;        // DCACHE DATA READ
+    uint32_t m_cpt_dcache_data_write;       // DCACHE DATA WRITE
+    uint32_t m_cpt_dcache_dir_read;         // DCACHE DIR READ
+    uint32_t m_cpt_dcache_dir_write;        // DCACHE DIR WRITE
+
+    uint32_t m_cpt_icache_data_read;        // ICACHE DATA READ
+    uint32_t m_cpt_icache_data_write;       // ICACHE DATA WRITE
+    uint32_t m_cpt_icache_dir_read;         // ICACHE DIR READ
+    uint32_t m_cpt_icache_dir_write;        // ICACHE DIR WRITE
+
+    uint32_t m_cpt_frz_cycles;	            // number of cycles where the cpu is frozen
+    uint32_t m_cpt_total_cycles;	        // total number of cycles 
+
+    // Cache activity counters
+    uint32_t m_cpt_read;                    // total number of read data
+    uint32_t m_cpt_write;                   // total number of write data
+    uint32_t m_cpt_data_miss;               // number of read miss
+    uint32_t m_cpt_ins_miss;                // number of instruction miss
+    uint32_t m_cpt_unc_read;                // number of read uncached
+    uint32_t m_cpt_write_cached;            // number of cached write
+    uint32_t m_cpt_ins_read;                // number of instruction read
+
+    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
+    uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
+    uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
+    uint32_t m_cost_ins_miss_frz;           // number of frozen cycles related to ins miss
+
+    uint32_t m_cpt_imiss_transaction;       // number of VCI instruction miss transactions
+    uint32_t m_cpt_dmiss_transaction;       // number of VCI data miss transactions
+    uint32_t m_cpt_unc_transaction;         // number of VCI uncached read transactions
+    uint32_t m_cpt_write_transaction;       // number of VCI write transactions
+
+    uint32_t m_cost_imiss_transaction;      // cumulated duration for VCI IMISS transactions
+    uint32_t m_cost_dmiss_transaction;      // cumulated duration for VCI DMISS transactions
+    uint32_t m_cost_unc_transaction;        // cumulated duration for VCI UNC transactions
+    uint32_t m_cost_write_transaction;      // cumulated duration for VCI WRITE transactions
+    uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions
+
+    // TLB activity counters
+    uint32_t m_cpt_ins_tlb_read;            // number of instruction tlb read
+    uint32_t m_cpt_ins_tlb_miss;            // number of instruction tlb miss
+    uint32_t m_cpt_ins_tlb_write_et;        // number of instruction tlb write ET
+
+    uint32_t m_cpt_data_tlb_read;           // number of data tlb read
+    uint32_t m_cpt_data_tlb_miss;           // number of data tlb miss
+    uint32_t m_cpt_data_tlb_write_et;       // number of data tlb write ET
+    uint32_t m_cpt_data_tlb_write_dirty;    // number of data tlb write dirty
+    
+    uint32_t m_cost_ins_tlb_miss_frz;       // number of frozen cycles related to instruction tlb miss
+    uint32_t m_cost_data_tlb_miss_frz;      // number of frozen cycles related to data tlb miss
+
+    uint32_t m_cost_ins_waste_wait_frz;     // number of frozen cycles related to ins wait coherence operate 
+    uint32_t m_cost_ins_tlb_sw_frz;         // number of frozen cycles related to ins context switch
+    uint32_t m_cost_ins_cache_flush_frz;    // number of frozen cycles related to ins cache flush 
+
+    uint32_t m_cpt_ins_tlb_cleanup;         // number of ins tlb cleanup 
+    uint32_t m_cost_data_waste_wait_frz;    // number of frozen cycles related to data wait coherence operate
+    uint32_t m_cost_data_tlb_sw_frz;        // number of frozen cycles related to data context switch
+    uint32_t m_cost_data_cache_flush_frz;   // number of frozen cycles related to data cache flush
+
+    uint32_t m_cpt_itlbmiss_transaction;    // number of itlb miss transactions
+    uint32_t m_cpt_itlb_write_transaction;  // number of itlb write ET transactions
+    uint32_t m_cpt_dtlbmiss_transaction;    // number of dtlb miss transactions
+    uint32_t m_cpt_dtlb_write_transaction;  // number of dtlb write ET and dirty transactions
+
+    uint32_t m_cost_itlbmiss_transaction;   // cumulated duration for VCI instruction TLB miss transactions
+    uint32_t m_cost_itlb_write_transaction; // cumulated duration for VCI instruction TLB write ET transactions
+    uint32_t m_cost_dtlbmiss_transaction;   // cumulated duration for VCI data TLB miss transactions
+    uint32_t m_cost_dtlb_write_transaction; // cumulated duration for VCI data TLB write transactions
+
+    uint32_t m_cpt_cc_update;               // number of coherence update packets 
+    uint32_t m_cpt_cc_inval;                // number of coherence inval packets
+    uint32_t m_cpt_cc_broadcast;            // number of coherence broadcast packets
+
+    uint32_t m_cost_ins_tlb_inval_frz;      // number of frozen cycles related to checking ins tlb invalidate
+    uint32_t m_cpt_ins_tlb_inval;           // number of ins tlb invalidate
+
+    uint32_t m_cost_data_tlb_inval_frz;     // number of frozen cycles related to checking data tlb invalidate    
+    uint32_t m_cpt_data_tlb_inval;          // number of data tlb invalidate
+
+protected:
+    SC_HAS_PROCESS(VciCcVCacheWrapper2V1);
+
+public:
+    VciCcVCacheWrapper2V1(
+        sc_module_name insname,
+        int proc_id,
+        const soclib::common::MappingTable &mtp,
+        const soclib::common::MappingTable &mtc,
+        const soclib::common::IntTab &initiator_index_rw,
+        const soclib::common::IntTab &initiator_index_c,
+        const soclib::common::IntTab &target_index,
+        size_t itlb_ways,
+        size_t itlb_sets,
+        size_t dtlb_ways,
+        size_t dtlb_sets,
+        size_t icache_ways,
+        size_t icache_sets,
+        size_t icache_words,
+        size_t dcache_ways,
+        size_t dcache_sets,
+        size_t dcache_words,
+        size_t write_buf_size );
+
+    ~VciCcVCacheWrapper2V1();
+
+    void print_cpi();
+    void print_stats();
+
+private:
+    void transition();
+    void genMoore();
+
+    soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC);
+    soclib_static_assert((int)iss_t::SC_NOT_ATOMIC == (int)vci_param::STORE_COND_NOT_ATOMIC);
+};
+
+}}
+
+#endif /* SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER2_V1_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
+
Index: trunk/modules/vci_cc_vcache_wrapper2_v1/caba/source/src/vci_cc_vcache_wrapper2_v1.cpp
===================================================================
--- trunk/modules/vci_cc_vcache_wrapper2_v1/caba/source/src/vci_cc_vcache_wrapper2_v1.cpp	(revision 2)
+++ trunk/modules/vci_cc_vcache_wrapper2_v1/caba/source/src/vci_cc_vcache_wrapper2_v1.cpp	(revision 2)
@@ -0,0 +1,5763 @@
+/* -*- c++ -*-
+ * File : vci_cc_vcache_wrapper2_v1.cpp
+ * Copyright (c) UPMC, Lip6, SoC
+ * Authors : Alain GREINER, Yang GAO
+ *
+ * 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
+ */
+
+#include <cassert>
+#include "arithmetics.h"
+#include "../include/vci_cc_vcache_wrapper2_v1.h"
+
+namespace soclib { 
+namespace caba {
+
+//#define SOCLIB_MODULE_DEBUG
+#ifdef SOCLIB_MODULE_DEBUG
+namespace {
+const char *icache_fsm_state_str[] = {
+        "ICACHE_IDLE",
+        "ICACHE_BIS",       
+        "ICACHE_TLB1_READ",  
+        "ICACHE_TLB1_WRITE",  
+        "ICACHE_TLB1_UPDT",  
+        "ICACHE_TLB2_READ",  
+        "ICACHE_TLB2_WRITE",  
+        "ICACHE_TLB2_UPDT",  
+        "ICACHE_SW_FLUSH", 
+        "ICACHE_TLB_FLUSH", 
+        "ICACHE_CACHE_FLUSH", 
+        "ICACHE_TLB_INVAL",  
+        "ICACHE_CACHE_INVAL",
+	"ICACHE_CACHE_INVAL_PA",
+        "ICACHE_MISS_WAIT",
+        "ICACHE_UNC_WAIT",  
+        "ICACHE_MISS_UPDT",  
+        "ICACHE_ERROR", 
+        "ICACHE_CC_INVAL", 
+        "ICACHE_TLB_CC_INVAL",        
+    };
+const char *dcache_fsm_state_str[] = {
+        "DCACHE_IDLE",       
+        "DCACHE_BIS",   
+        "DCACHE_DTLB1_READ_CACHE",
+	"DCACHE_TLB1_LL_WAIT",
+	"DCACHE_TLB1_SC_WAIT",    
+        "DCACHE_TLB1_READ",
+        "DCACHE_TLB1_READ_UPDT",  
+        "DCACHE_TLB1_UPDT", 
+        "DCACHE_DTLB2_READ_CACHE", 
+	"DCACHE_TLB2_LL_WAIT",
+	"DCACHE_TLB2_SC_WAIT",   
+        "DCACHE_TLB2_READ",
+        "DCACHE_TLB2_READ_UPDT",  
+        "DCACHE_TLB2_UPDT",   
+        "DCACHE_CTXT_SWITCH",   
+        "DCACHE_ICACHE_FLUSH", 
+        "DCACHE_DCACHE_FLUSH", 
+        "DCACHE_ITLB_INVAL",
+        "DCACHE_DTLB_INVAL",
+        "DCACHE_ICACHE_INVAL",
+        "DCACHE_DCACHE_INVAL",
+	"DCACHE_ICACHE_INVAL_PA",
+	"DCACHE_DCACHE_INVAL_PA",
+	"DCACHE_DCACHE_SYNC",
+	"DCACHE_LL_DIRTY_WAIT",
+	"DCACHE_SC_DIRTY_WAIT",
+        "DCACHE_WRITE_UPDT", 
+        "DCACHE_WRITE_DIRTY",
+        "DCACHE_WRITE_REQ",  
+        "DCACHE_MISS_WAIT",  
+        "DCACHE_MISS_UPDT",  
+        "DCACHE_UNC_WAIT",   
+        "DCACHE_ERROR", 
+        "DCACHE_ITLB_READ",
+        "DCACHE_ITLB_UPDT",
+        "DCACHE_ITLB_LL_WAIT",        
+        "DCACHE_ITLB_SC_WAIT",        
+        "DCACHE_CC_CHECK",
+        "DCACHE_CC_INVAL",
+        "DCACHE_CC_UPDT",
+        "DCACHE_CC_NOP",
+        "DCACHE_TLB_CC_INVAL",
+        "DCACHE_ITLB_CLEANUP",
+    };
+const char *cmd_fsm_state_str[] = {
+        "CMD_IDLE",           
+        "CMD_ITLB_READ", 
+        "CMD_ITLB_ACC_LL",                
+        "CMD_ITLB_ACC_SC",                
+        "CMD_INS_MISS",     
+        "CMD_INS_UNC",     
+        "CMD_DTLB_READ",   
+        "CMD_DTLB_ACC_LL",            
+        "CMD_DTLB_ACC_SC",            
+        "CMD_DTLB_DIRTY_LL",          
+        "CMD_DTLB_DIRTY_SC",          
+        "CMD_DATA_UNC",     
+        "CMD_DATA_MISS",    
+        "CMD_DATA_WRITE", 
+        "CMD_INS_CLEANUP",    
+        "CMD_DATA_CLEANUP",      
+    };
+const char *rsp_fsm_state_str[] = {
+        "RSP_IDLE",                  
+        "RSP_ITLB_READ",             
+        "RSP_ITLB_ACC_LL",                
+        "RSP_ITLB_ACC_SC",                
+        "RSP_INS_MISS",   
+        "RSP_INS_UNC",           
+        "RSP_DTLB_READ",            
+        "RSP_DTLB_ACC_LL",            
+        "RSP_DTLB_ACC_SC",            
+        "RSP_DTLB_DIRTY_LL",          
+        "RSP_DTLB_DIRTY_SC",          
+        "RSP_DATA_MISS",             
+        "RSP_DATA_UNC",              
+        "RSP_DATA_WRITE",     
+        "RSP_INS_CLEANUP",    
+        "RSP_DATA_CLEANUP",        
+    };
+const char *tgt_fsm_state_str[] = {
+        "TGT_IDLE",
+        "TGT_UPDT_WORD",
+        "TGT_UPDT_DATA",
+        "TGT_REQ_BROADCAST",
+        "TGT_REQ_ICACHE",
+        "TGT_REQ_DCACHE",
+        "TGT_RSP_BROADCAST",
+        "TGT_RSP_ICACHE",
+        "TGT_RSP_DCACHE",
+    };	
+const char *inval_itlb_fsm_state_str[] = {
+        "INVAL_ITLB_IDLE",        
+        "INVAL_ITLB_CHECK"  , 
+        "INVAL_ITLB_INVAL",      
+        "INVAL_ITLB_CLEAR",           
+    };
+const char *inval_dtlb_fsm_state_str[] = {
+        "INVAL_DTLB_IDLE",        
+        "INVAL_DTLB_CHECK", 
+        "INVAL_DTLB_INVAL",    
+        "INVAL_DTLB_CLEAR",         
+    };
+}
+#endif
+
+#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcVCacheWrapper2V1<vci_param, iss_t>
+
+using soclib::common::uint32_log2;
+
+/***********************************************/
+tmpl(/**/)::VciCcVCacheWrapper2V1(
+    sc_module_name name,
+    int proc_id,
+    const soclib::common::MappingTable &mtp,
+    const soclib::common::MappingTable &mtc,
+    const soclib::common::IntTab &initiator_index_rw,
+    const soclib::common::IntTab &initiator_index_c,
+    const soclib::common::IntTab &target_index,
+    size_t itlb_ways,
+    size_t itlb_sets,
+    size_t dtlb_ways,
+    size_t dtlb_sets,
+    size_t icache_ways,
+    size_t icache_sets,
+    size_t icache_words,
+    size_t dcache_ways,
+    size_t dcache_sets,
+    size_t dcache_words,
+    size_t write_buf_size )
+/***********************************************/
+    : soclib::caba::BaseModule(name),
+
+      p_clk("clk"),
+      p_resetn("resetn"),
+      p_vci_ini_rw("vci_ini_rw"),
+      p_vci_ini_c("vci_ini_c"),
+      p_vci_tgt("vci_tgt"),
+
+      m_cacheability_table(mtp.getCacheabilityTable()),
+      m_segment(mtc.getSegment(target_index)),
+      m_iss(this->name(), proc_id),
+      m_srcid_rw(mtp.indexForId(initiator_index_rw)),
+      m_srcid_c(mtp.indexForId(initiator_index_c)),
+
+      m_itlb_ways(itlb_ways),
+      m_itlb_sets(itlb_sets),
+
+      m_dtlb_ways(dtlb_ways),
+      m_dtlb_sets(dtlb_sets),
+
+      m_icache_ways(icache_ways),
+      m_icache_sets(icache_sets),
+      m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
+      m_icache_words(icache_words),
+
+      m_dcache_ways(dcache_ways),
+      m_dcache_sets(dcache_sets),
+      m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
+      m_dcache_words(dcache_words),
+
+      m_write_buf_size(write_buf_size),	
+      m_paddr_nbits(vci_param::N),
+
+      icache_tlb(itlb_ways,itlb_sets,vci_param::N),
+      dcache_tlb(dtlb_ways,dtlb_sets,vci_param::N),
+
+      r_dcache_fsm("r_dcache_fsm"),
+      r_dcache_paddr_save("r_dcache_paddr_save"),
+      r_dcache_wdata_save("r_dcache_wdata_save"),
+      r_dcache_rdata_save("r_dcache_rdata_save"),
+      r_dcache_type_save("r_dcache_type_save"),
+      r_dcache_be_save("r_dcache_be_save"),
+      r_dcache_cached_save("r_dcache_cached_save"),
+      r_dcache_tlb_paddr("r_dcache_tlb_paddr"),
+      r_dcache_miss_req("r_dcache_miss_req"),
+      r_dcache_unc_req("r_dcache_unc_req"),
+      r_dcache_write_req("r_dcache_write_req"),
+      r_dcache_tlb_read_req("r_dcache_tlb_read_req"),
+
+      r_dcache_tlb_ll_acc_req("r_dcache_tlb_ll_acc_req"),       
+      r_dcache_tlb_sc_acc_req("r_dcache_tlb_sc_acc_req"),       
+      r_dcache_tlb_ll_dirty_req("r_dcache_tlb_ll_dirty_req"),    
+      r_dcache_tlb_sc_dirty_req("r_dcache_tlb_sc_dirty_req"), 
+      r_dcache_tlb_ptba_read("r_dcache_tlb_ptba_read"),
+      r_dcache_xtn_req("r_dcache_xtn_req"),
+
+      r_dcache_fsm_save("r_dcache_fsm_save"),
+      r_dcache_cleanup_req("r_dcache_cleanup_req"),
+      r_dcache_inval_rsp("r_dcache_inval_rsp"),
+
+      r_icache_fsm("r_icache_fsm"),
+      r_icache_paddr_save("r_icache_paddr_save"),
+      r_icache_miss_req("r_icache_miss_req"),
+      r_icache_unc_req("r_icache_unc_req"),
+      r_dcache_itlb_read_req("r_dcache_itlb_read_req"),
+      r_dcache_itlb_ll_acc_req("r_dcache_itlb_ll_acc_req"),     
+      r_dcache_itlb_sc_acc_req("r_dcache_itlb_sc_acc_req"),
+
+      r_itlb_read_dcache_req("r_itlb_read_dcache_req"),
+      r_itlb_k_read_dcache("r_itlb_k_read_dcache"),
+      r_itlb_acc_dcache_req("r_itlb_acc_dcache_req"),
+      r_dcache_rsp_itlb_error("r_dcache_rsp_itlb_error"),
+
+      r_icache_fsm_save("r_icache_fsm_save"),
+      r_icache_cleanup_req("r_icache_cleanup_req"),
+      r_icache_inval_rsp("r_icache_inval_rsp"),
+
+      r_vci_cmd_fsm("r_vci_cmd_fsm"),
+      r_vci_cmd_min("r_vci_cmd_min"),
+      r_vci_cmd_max("r_vci_cmd_max"),
+      r_vci_cmd_cpt("r_vci_cmd_cpt"),
+
+      r_vci_rsp_fsm("r_vci_rsp_fsm"),
+      r_vci_rsp_cpt("r_vci_rsp_cpt"),
+      r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
+      r_vci_rsp_data_error("r_vci_rsp_data_error"),
+
+      r_vci_tgt_fsm("r_vci_tgt_fsm"),
+      r_tgt_addr("r_tgt_addr"),
+      r_tgt_word("r_tgt_word"),
+      r_tgt_update("r_tgt_update"),
+      r_tgt_srcid("r_tgt_srcid"),
+      r_tgt_pktid("r_tgt_pktid"),
+      r_tgt_trdid("r_tgt_trdid"),
+      r_tgt_icache_req("r_tgt_icache_req"),
+      r_tgt_dcache_req("r_tgt_dcache_req"),
+
+      r_inval_itlb_fsm("r_inval_itlb_fsm"),          
+      r_dcache_itlb_inval_req("r_dcache_itlb_inval_req"),
+      r_dcache_itlb_inval_line("r_dcache_itlb_inval_line"),
+      r_itlb_cc_check_end("r_itlb_cc_check_end"),
+      r_ccinval_itlb_way("r_ccinval_itlb_way"), 
+      r_ccinval_itlb_set("r_ccinval_itlb_set"), 
+      r_icache_inval_tlb_rsp("r_icache_inval_tlb_rsp"),
+      r_icache_tlb_nline("r_icache_tlb_nline"),
+
+      r_inval_dtlb_fsm("r_inval_dtlb_fsm"),          
+      r_dcache_dtlb_inval_req("r_dcache_dtlb_inval_req"),
+      r_dcache_dtlb_inval_line("r_dcache_dtlb_inval_line"),
+      r_dtlb_cc_check_end("r_dtlb_cc_check_end"),
+      r_ccinval_dtlb_way("r_ccinval_dtlb_way"), 
+      r_ccinval_dtlb_set("r_ccinval_dtlb_set"), 
+      r_dcache_inval_tlb_rsp("r_dcache_inval_tlb_rsp"),
+      r_dcache_tlb_nline("r_dcache_tlb_nline"),
+
+      r_dcache_itlb_cleanup_req("r_dcache_itlb_cleanup_req"),
+      r_dcache_itlb_cleanup_line("r_dcache_itlb_cleanup_line"),
+
+      r_dcache_dtlb_cleanup_req("r_dcache_dtlb_cleanup_req"),
+      r_dcache_dtlb_cleanup_line("r_dcache_dtlb_cleanup_line"),
+
+      r_wbuf("wbuf", write_buf_size ),
+      r_icache("icache", icache_ways, icache_sets, icache_words),
+      r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
+{
+    r_icache_miss_buf = new data_t[icache_words];
+    r_dcache_miss_buf = new data_t[dcache_words];
+    r_tgt_buf         = new data_t[dcache_words];
+    r_tgt_val         = new bool[dcache_words];
+    r_dcache_in_itlb  = new bool[dcache_ways*dcache_sets];           
+    r_dcache_in_dtlb  = new bool[dcache_ways*dcache_sets];          
+
+    SC_METHOD(transition);
+    dont_initialize();
+    sensitive << p_clk.pos();
+  
+    SC_METHOD(genMoore);
+    dont_initialize();
+    sensitive << p_clk.neg();
+
+    typename iss_t::CacheInfo cache_info;
+    cache_info.has_mmu = true;
+    cache_info.icache_line_size = icache_words*sizeof(data_t);
+    cache_info.icache_assoc = icache_ways;
+    cache_info.icache_n_lines = icache_sets;
+    cache_info.dcache_line_size = dcache_words*sizeof(data_t);
+    cache_info.dcache_assoc = dcache_ways;
+    cache_info.dcache_n_lines = dcache_sets;
+    m_iss.setCacheInfo(cache_info);
+}
+
+/////////////////////////////////////
+tmpl(/**/)::~VciCcVCacheWrapper2V1()
+/////////////////////////////////////
+{
+    delete [] r_icache_miss_buf;
+    delete [] r_dcache_miss_buf;
+    delete [] r_tgt_val;
+    delete [] r_tgt_buf;
+    delete [] r_dcache_in_itlb;           
+    delete [] r_dcache_in_dtlb;          
+}
+
+////////////////////////
+tmpl(void)::print_cpi()
+////////////////////////
+{
+    std::cout << name() << " CPI = " 
+        << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
+}
+
+////////////////////////
+tmpl(void)::print_stats()
+////////////////////////
+{
+    float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
+    std::cout << name() << std::endl
+    	      << "- CPI                    = " << (float)m_cpt_total_cycles/run_cycles << std::endl 
+    	      << "- READ RATE              = " << (float)m_cpt_read/run_cycles << std::endl 
+    	      << "- WRITE RATE             = " << (float)m_cpt_write/run_cycles << std::endl
+    	      << "- UNCACHED READ RATE     = " << (float)m_cpt_unc_read/m_cpt_read << std::endl 
+    	      << "- CACHED WRITE RATE      = " << (float)m_cpt_write_cached/m_cpt_write << std::endl 
+    	      << "- IMISS_RATE             = " << (float)m_cpt_ins_miss/m_cpt_ins_read << std::endl    
+    	      << "- DMISS RATE             = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl 
+    	      << "- INS MISS COST          = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl
+    	      << "- IMISS TRANSACTION      = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl
+    	      << "- DMISS COST             = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl
+    	      << "- DMISS TRANSACTION      = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl
+    	      << "- UNC COST               = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl
+    	      << "- UNC TRANSACTION        = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl
+    	      << "- WRITE COST             = " << (float)m_cost_write_frz/m_cpt_write << std::endl
+    	      << "- WRITE TRANSACTION      = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl
+    	      << "- WRITE LENGTH           = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl
+    	      << "- INS TLB MISS RATE      = " << (float)m_cpt_ins_tlb_miss/m_cpt_ins_tlb_read << std::endl
+    	      << "- DATA TLB MISS RATE     = " << (float)m_cpt_data_tlb_miss/m_cpt_data_tlb_read << std::endl
+    	      << "- ITLB MISS TRANSACTION  = " << (float)m_cost_itlbmiss_transaction/m_cpt_itlbmiss_transaction << std::endl
+    	      << "- ITLB WRITE TRANSACTION = " << (float)m_cost_itlb_write_transaction/m_cpt_itlb_write_transaction << std::endl
+    	      << "- ITLB MISS COST         = " << (float)m_cost_ins_tlb_miss_frz/(m_cpt_ins_tlb_miss+m_cpt_ins_tlb_write_et) << std::endl
+    	      << "- DTLB MISS TRANSACTION  = " << (float)m_cost_dtlbmiss_transaction/m_cpt_dtlbmiss_transaction << std::endl
+    	      << "- DTLB WRITE TRANSACTION = " << (float)m_cost_dtlb_write_transaction/m_cpt_dtlb_write_transaction << std::endl
+    	      << "- DTLB MISS COST         = " << (float)m_cost_data_tlb_miss_frz/(m_cpt_data_tlb_miss+m_cpt_data_tlb_write_et+m_cpt_data_tlb_write_dirty) << std::endl;
+}
+
+/*************************************************/
+tmpl(void)::transition()
+/*************************************************/
+{
+    if ( ! p_resetn.read() ) 
+    {
+        m_iss.reset();
+
+        r_dcache_fsm = DCACHE_IDLE;
+        r_icache_fsm = ICACHE_IDLE;
+        r_vci_cmd_fsm = CMD_IDLE;
+        r_vci_rsp_fsm = RSP_IDLE;
+        r_vci_tgt_fsm = TGT_IDLE;
+        r_inval_itlb_fsm = INVAL_ITLB_IDLE;          
+        r_inval_dtlb_fsm = INVAL_DTLB_IDLE;          
+
+        // write buffer & caches
+        r_wbuf.reset();
+        r_icache.reset();
+        r_dcache.reset();
+
+        icache_tlb.reset();    
+        dcache_tlb.reset();    
+
+        std::memset(r_dcache_in_itlb, 0, sizeof(*r_dcache_in_itlb)*m_icache_ways*m_icache_sets);
+        std::memset(r_dcache_in_dtlb, 0, sizeof(*r_dcache_in_dtlb)*m_dcache_ways*m_dcache_sets);
+
+        //r_mmu_mode = ALL_DEACTIVE;
+        r_mmu_mode = 0x3;
+        r_mmu_params = (uint32_log2(m_dtlb_ways) << 29)   | (uint32_log2(m_dtlb_sets) << 25)   |
+                       (uint32_log2(m_dcache_ways) << 22) | (uint32_log2(m_dcache_sets) << 18) |
+                       (uint32_log2(m_itlb_ways) << 15)   | (uint32_log2(m_itlb_sets) << 11)   |
+                       (uint32_log2(m_icache_ways) << 8)  | (uint32_log2(m_icache_sets) << 4)  |
+                       (uint32_log2(m_icache_words * 4));
+        r_mmu_release = (uint32_t)(1 << 16) | 0x1;
+
+        r_icache_miss_req         = false;
+        r_icache_unc_req          = false;
+        r_dcache_itlb_read_req    = false;
+
+        r_itlb_read_dcache_req    = false;      
+        r_itlb_k_read_dcache      = false;      
+        r_itlb_acc_dcache_req     = false;   
+        r_dcache_rsp_itlb_error   = false;
+ 
+        r_dcache_miss_req         = false;
+        r_dcache_unc_req          = false;
+        r_dcache_write_req        = false;
+        r_dcache_tlb_read_req     = false;
+        r_dcache_tlb_ptba_read    = false;
+        r_dcache_xtn_req          = false;
+	r_dcache_llsc_reserved    = false;
+
+        r_dcache_tlb_ll_acc_req   = false;    
+        r_dcache_tlb_sc_acc_req   = false;    
+        r_dcache_tlb_ll_dirty_req = false;   
+        r_dcache_tlb_sc_dirty_req = false;   
+        r_dcache_itlb_ll_acc_req  = false;   
+        r_dcache_itlb_sc_acc_req  = false;   
+
+        r_icache_cleanup_req      = false;
+        r_dcache_cleanup_req      = false;
+
+        r_tgt_icache_req          = false;
+        r_tgt_dcache_req          = false;
+
+        r_icache_inval_rsp        = false;
+        r_dcache_inval_rsp        = false;
+
+        r_dcache_dirty_save       = false;
+        r_dcache_hit_p_save       = false;
+
+        r_icache_buf_unc_valid    = false;
+        r_dcache_buf_unc_valid    = false;
+
+        r_vci_rsp_ins_error       = false;
+        r_vci_rsp_data_error      = false;
+
+        r_icache_id1_save         = 0;
+        r_icache_ppn_save         = 0;
+        r_icache_vpn_save         = 0;
+        r_itlb_translation_valid  = false;
+
+        r_dcache_id1_save         = 0;
+        r_dcache_ppn_save         = 0;
+        r_dcache_vpn_save         = 0;
+        r_dtlb_translation_valid  = false;
+
+        r_icache_ptba_ok          = false;
+        r_dcache_ptba_ok          = false;
+
+        r_icache_error_type       = MMU_NONE;
+        r_dcache_error_type       = MMU_NONE;
+
+        // coherence registers
+        r_icache_way              = 0;
+        r_icache_set              = 0;
+        r_icache_cleanup_req      = false;
+        r_icache_inval_rsp        = false;
+
+        r_dcache_way              = 0;
+        r_dcache_set              = 0;
+        r_dcache_cleanup_req      = false;
+        r_dcache_inval_rsp        = false;
+
+	r_itlb_inval_req 	  = false;
+        r_dcache_itlb_inval_req   = false;
+        r_itlb_cc_check_end       = false;
+        r_ccinval_itlb_way        = 0; 
+        r_ccinval_itlb_set        = 0; 
+        r_icache_inval_tlb_rsp    = false;
+
+        r_dcache_dtlb_inval_req   = false;
+        r_dtlb_cc_check_end       = false;
+        r_ccinval_dtlb_way        = 0; 
+        r_ccinval_dtlb_set        = 0; 
+        r_dcache_inval_tlb_rsp    = false;
+
+        r_dcache_itlb_cleanup_req = false;
+        r_dcache_dtlb_cleanup_req = false;
+
+	r_dcache_cc_check         = false;
+
+        // activity counters
+        m_cpt_dcache_data_read  = 0;
+        m_cpt_dcache_data_write = 0;
+        m_cpt_dcache_dir_read   = 0;
+        m_cpt_dcache_dir_write  = 0;
+        m_cpt_icache_data_read  = 0;
+        m_cpt_icache_data_write = 0;
+        m_cpt_icache_dir_read   = 0;
+        m_cpt_icache_dir_write  = 0;
+
+	m_cpt_frz_cycles   = 0;
+        m_cpt_total_cycles = 0;
+
+        m_cpt_read         = 0;
+        m_cpt_write        = 0;
+        m_cpt_data_miss    = 0;
+        m_cpt_ins_miss     = 0;
+        m_cpt_unc_read     = 0;
+        m_cpt_write_cached = 0;
+        m_cpt_ins_read     = 0;
+
+        m_cost_write_frz     = 0;
+        m_cost_data_miss_frz = 0;
+        m_cost_unc_read_frz  = 0;
+        m_cost_ins_miss_frz  = 0;
+
+        m_cpt_imiss_transaction = 0;
+        m_cpt_dmiss_transaction = 0;
+        m_cpt_unc_transaction   = 0;
+        m_cpt_write_transaction = 0;
+
+        m_cost_imiss_transaction   = 0;
+        m_cost_dmiss_transaction   = 0;
+        m_cost_unc_transaction     = 0;
+        m_cost_write_transaction   = 0;
+        m_length_write_transaction = 0;
+
+        m_cpt_ins_tlb_read         = 0;             
+        m_cpt_ins_tlb_miss         = 0;             
+        m_cpt_ins_tlb_write_et     = 0;         
+
+        m_cpt_data_tlb_read        = 0;           
+        m_cpt_data_tlb_miss        = 0;           
+        m_cpt_data_tlb_write_et    = 0;       
+        m_cpt_data_tlb_write_dirty = 0;    
+
+        m_cost_ins_tlb_miss_frz    = 0;      
+        m_cost_data_tlb_miss_frz   = 0;      
+
+        m_cpt_itlbmiss_transaction   = 0;    
+        m_cpt_itlb_write_transaction = 0;  
+        m_cpt_dtlbmiss_transaction   = 0;  
+        m_cpt_dtlb_write_transaction = 0;  
+ 
+        m_cost_itlbmiss_transaction   = 0;   
+        m_cost_itlb_write_transaction = 0;  
+        m_cost_dtlbmiss_transaction   = 0;   
+        m_cost_dtlb_write_transaction = 0;   
+        return;
+    }
+
+#ifdef SOCLIB_MODULE_DEBUG
+std::cout << name() << "cycle = " << m_cpt_total_cycles  
+       	  << " tgt fsm: " << tgt_fsm_state_str[r_vci_tgt_fsm]
+       	  << " dcache fsm: " << dcache_fsm_state_str[r_dcache_fsm]
+       	  << " icache fsm: " << icache_fsm_state_str[r_icache_fsm]
+       	  << " cmd fsm: " << cmd_fsm_state_str[r_vci_cmd_fsm]
+       	  << " rsp fsm: " << rsp_fsm_state_str[r_vci_rsp_fsm] 
+       	  << " inval itlb fsm: " << inval_itlb_fsm_state_str[r_inval_itlb_fsm] 
+          << " inval dtlb fsm: " << inval_dtlb_fsm_state_str[r_inval_dtlb_fsm] << std::endl;
+#endif
+
+    m_cpt_total_cycles++;
+
+    typename iss_t::InstructionRequest ireq = ISS_IREQ_INITIALIZER;
+    typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
+
+    typename iss_t::DataRequest dreq = ISS_DREQ_INITIALIZER;
+    typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
+
+    m_iss.getRequests( ireq, dreq );
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout << name() << " Instruction Request: " << ireq << std::endl;
+    std::cout << name() << " Data Request: " << dreq << std::endl;
+#endif
+
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_FSM controls the following ressources:
+    // - r_vci_tgt_fsm
+    // - r_tgt_buf[nwords]
+    // - r_tgt_val[nwords]
+    // - r_tgt_update
+    // - r_tgt_word
+    // - r_tgt_addr
+    // - r_tgt_srcid
+    // - r_tgt_trdid
+    // - r_tgt_pktid
+    // All VCI commands must be CMD_WRITE.
+    // If the VCI address offset is null, the command is an invalidate 
+    // request. It is an update request otherwise.
+    // The VCI_TGT FSM stores the external request arguments in the
+    // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 
+    // & r_tgt_dcache_req flip-flops to signal the external request to 
+    // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
+    // of the update or invalidate request in the RSP state.
+    // -  for an invalidate request the VCI packet length is 1 word.
+    // The WDATA field contains the line index (i.e. the Z & Y fields).
+    // -  for an update request the VCI packet length is (n+2) words.
+    // The WDATA field of the first VCI word contains the line number.
+    // The WDATA field of the second VCI word contains the word index.
+    // The WDATA field of the n following words contains the values.
+    // -  for both invalidate & update requests, the VCI response
+    // is one single word.
+    // In case of errors in the VCI command packet, the simulation
+    // is stopped with an error message.
+    /////////////////////////////////////////////////////////////////////
+    
+    switch(r_vci_tgt_fsm) {
+    //////////////
+    case TGT_IDLE:
+    {
+        if ( p_vci_tgt.cmdval.read() ) 
+        {
+            paddr_t address = p_vci_tgt.address.read();
+
+            if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the received VCI command is not a write" << std::endl;
+                exit(0);
+            }
+
+            // multi-update or multi-invalidate for data type
+            if ( ( address != 0x3 ) && ( ! m_segment.contains(address)) ) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "out of segment VCI command received for a multi-updt or multi-inval request" << std::endl;
+                exit(0);
+            }
+
+            r_tgt_srcid = p_vci_tgt.srcid.read();
+            r_tgt_trdid = p_vci_tgt.trdid.read();
+            r_tgt_pktid = p_vci_tgt.pktid.read();
+            r_tgt_plen  = p_vci_tgt.plen.read(); // todo: wait L2 modification
+            r_tgt_addr  = (paddr_t)(p_vci_tgt.be.read() & 0x3) << 32 |
+			  (paddr_t)p_vci_tgt.wdata.read() * m_dcache_words * 4; 
+
+            if ( address == 0x3 ) // broadcast invalidate for data or instruction type
+            {
+                if ( ! p_vci_tgt.eop.read() ) 
+                {
+                    std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                    std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
+                    exit(0);
+                }
+                r_tgt_update = false; 
+                r_vci_tgt_fsm = TGT_REQ_BROADCAST;
+                m_cpt_cc_broadcast++;
+            }
+            else                // multi-update or multi-invalidate for data type
+            {
+                paddr_t cell = address - m_segment.baseAddress();   
+
+                if (cell == 0)                      // invalidate   
+                {                         
+                    if ( ! p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_update = false; 
+                    r_vci_tgt_fsm = TGT_REQ_DCACHE;
+                    m_cpt_cc_inval++ ;
+                }
+                else if (cell == 4)                // update 
+                {                                
+                    if ( p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_update = true; 
+                    r_vci_tgt_fsm = TGT_UPDT_WORD;
+                    m_cpt_cc_update++ ;
+                }     
+		else if (cell == 8)
+		{
+                    if ( ! p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_update = false; 
+                    r_vci_tgt_fsm = TGT_REQ_ICACHE;
+                    m_cpt_cc_inval++ ;
+
+		}
+            } // end if address    
+        } // end if cmdval
+        break;
+    }
+    ///////////////////
+    case TGT_UPDT_WORD:
+    {
+        if (p_vci_tgt.cmdval.read()) 
+        {
+            if ( p_vci_tgt.eop.read() ) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                exit(0);
+            }
+            for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_val[i] = false;
+            r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
+            r_vci_tgt_fsm = TGT_UPDT_DATA;
+        }
+        break;
+    }
+    ///////////////////
+    case TGT_UPDT_DATA:
+    {
+        if (p_vci_tgt.cmdval.read()) 
+        {
+            size_t word = r_tgt_word.read();
+            if (word >= m_dcache_words) 
+            {
+                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
+                exit(0);
+            }
+            r_tgt_buf[word] = p_vci_tgt.wdata.read();
+            if(p_vci_tgt.be.read())    r_tgt_val[word] = true;
+            r_tgt_word = word + 1;
+            if (p_vci_tgt.eop.read())  r_vci_tgt_fsm = TGT_REQ_DCACHE;
+        }
+        break;
+    }
+    ////////////////////////
+    case TGT_REQ_BROADCAST:
+    {
+        if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_RSP_BROADCAST; 
+            r_tgt_icache_req = true;
+            r_tgt_dcache_req = true;
+        }
+        break;
+    }
+    /////////////////////
+    case TGT_REQ_ICACHE:
+    {
+        if ( !r_tgt_icache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_RSP_ICACHE; 
+            r_tgt_icache_req = true;
+        }
+        break;
+    }
+    /////////////////////
+    case TGT_REQ_DCACHE:
+    {
+        if ( !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_RSP_DCACHE; 
+            r_tgt_dcache_req = true;
+        }
+        break;
+    }
+    ///////////////////////
+    case TGT_RSP_BROADCAST:
+    {
+        // no response
+        if ( !r_tgt_icache_rsp.read() && !r_tgt_dcache_rsp.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
+        {
+            r_vci_tgt_fsm = TGT_IDLE;
+            break;
+        }
+
+        if ( p_vci_tgt.rspack.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+        {
+            // one response
+            if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
+            {
+                r_vci_tgt_fsm = TGT_IDLE; 
+                r_tgt_icache_rsp = false;
+                r_tgt_dcache_rsp = false;
+            }
+
+            // if data and instruction have the inval line, need two responses  
+            if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
+            {
+                r_tgt_icache_rsp = false; // only reset one for respond the second time 
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case TGT_RSP_ICACHE:
+    {
+	if ( (p_vci_tgt.rspack.read() || !r_tgt_icache_rsp.read()) && !r_tgt_icache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_IDLE;
+            r_tgt_icache_rsp = false; 
+        }
+        break;
+    }
+    /////////////////////
+    case TGT_RSP_DCACHE:
+    {
+	if ( (p_vci_tgt.rspack.read() || !r_tgt_dcache_rsp.read()) && !r_tgt_dcache_req.read() )
+        {
+            r_vci_tgt_fsm = TGT_IDLE;
+            r_tgt_dcache_rsp = false; 
+        }
+        break;
+    }
+    } // end switch TGT_FSM
+
+    ////////////////////////////////////////////////////////////////////////////////////////
+    //      ICACHE_FSM
+    //
+    // There is 9 mutually exclusive conditions to exit the IDLE state.
+    // Four configurations corresponding to an XTN request from processor,
+    // - Flush TLB (in case of Context switch) => TLB_FLUSH state 
+    // - Flush cache => CACHE_FLUSH state 
+    // - Invalidate a TLB entry => TLB_INVAL state
+    // - Invalidate a cache line => CACHE_INVAL state
+    // Five configurations corresponding to various TLB or cache MISS :
+    // - TLB miss(in case hit_p miss) => TLB1_READ state
+    // - TLB miss(in case hit_p hit) => TLB2_READ state
+    // - Hit in TLB but VPN changed => BIS state
+    // - Cached read miss => MISS_REQ state
+    // - Uncache read miss => UNC_REQ state
+    // 
+    // In case of MISS, the controller writes a request in the r_icache_paddr_save register 
+    // and sets the corresponding request flip-flop : r_dcache_itlb_read_req, r_icache_miss_req 
+    // or r_icache_unc_req. These request flip-flops are reset by the VCI_RSP controller 
+    // when the response is ready in the ICACHE buffer.
+    //
+    // The DCACHE FSM signals XTN processor requests using the r_dcache_xtn_req flip-flop. 
+    // The request opcod and the address to be invalidated are transmitted
+    // in the r_dcache_paddr_save & r_dcache_wdata_save registers respectively.
+    // The request flip-flop is reset by the ICACHE_FSM when the operation is completed.
+    //
+    // The r_vci_rsp_ins_error flip-flop is set by the VCI_RSP FSM and reset
+    // by the ICACHE-FSM in the ICACHE_ERROR state.
+    //
+    //----------------------------------------------------------------------------------- 
+    // Instruction TLB: 
+    //  
+    // - int        ET          (00: unmapped; 01: unused or PTD)
+    //                          (10: PTE new;  11: PTE old      )
+    // - bool       cachable    (cached bit)
+    // - bool       writable    (** not used alwayse false) 
+    // - bool       executable  (executable bit)
+    // - bool       user        (access in user mode allowed)
+    // - bool       global      (PTE not invalidated by a TLB flush)
+    // - bool       dirty       (** not used alwayse false) 
+    // - uint32_t   vpn         (virtual page number)
+    // - uint32_t   ppn         (physical page number)
+    ////////////////////////////////////////////////////////////////////////////////////////
+
+    switch(r_icache_fsm) {
+
+    ////////////////
+    case ICACHE_IDLE:
+    {
+        pte_info_t  icache_pte_info;
+        paddr_t     tlb_ipaddr       = 0;    	// physical address obtained from TLB                         
+        paddr_t     spc_ipaddr       = 0;    	// physical adress obtained from PPN_save (speculative)       
+        data_t      icache_ins       = 0;    	// read instruction
+        bool        icache_hit_c     = false;	// Cache hit
+        bool        icache_cached    = false;	// cacheable access (read)
+        bool        icache_hit_t     = false;	// hit on TLB
+        bool        icache_hit_x     = false;	// VPN unmodified (can use spc_dpaddr)
+        bool        icache_hit_p     = false;	// PTP unmodified (can skip first level page table walk)
+        size_t      icache_tlb_way   = 0;    	// selected way (in case of cache hit)
+        size_t      icache_tlb_set   = 0;    	// selected set (Y field in address)
+        paddr_t     icache_tlb_nline = 0;  	// TLB NLINE 
+
+        // Decoding processor XTN requests
+        // They are sent by DCACHE FSM  
+
+        if (r_dcache_xtn_req)
+        {
+            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+            
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_PTPR )  
+            {
+                r_icache_way = 0;
+                r_icache_set = 0;
+                r_icache_fsm = ICACHE_SW_FLUSH;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_ICACHE_FLUSH)
+            {
+                r_icache_way = 0;
+                r_icache_set = 0;
+                r_icache_fsm = ICACHE_CACHE_FLUSH;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_ITLB_INVAL) 
+            {
+                r_icache_fsm = ICACHE_TLB_INVAL;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_ICACHE_INVAL) 
+            {
+                r_icache_fsm = ICACHE_CACHE_INVAL;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_MMU_ICACHE_PA_INV) 
+            {
+                r_icache_fsm = ICACHE_CACHE_INVAL_PA;   
+                break;
+            }
+            if ((int)r_dcache_type_save == (int)iss_t::XTN_DCACHE_FLUSH )  
+            {
+                // special for ins tlb miss via data cache
+                r_icache_fsm = ICACHE_TLB_FLUSH;   
+                break;
+            }
+        } // end if xtn_req
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            break;
+        }
+
+        // icache_hit_t_m, icache_hit_t_k, icache_hit_x, icache_hit_p 
+        // icache_pte_info, icache_tlb_way, icache_tlb_set & ipaddr & cacheability 
+        // - If MMU activated : cacheability is defined by the cachable bit in the TLB
+        // - If MMU not activated : cacheability is defined by the segment table.
+
+        if ( !(r_mmu_mode.read() & INS_TLB_MASK) )   // MMU not activated 
+        {
+            icache_hit_t  = true;         
+            icache_hit_x  = true;         
+            icache_hit_p  = true;         
+            tlb_ipaddr    = ireq.addr;
+            spc_ipaddr    = ireq.addr;
+            icache_cached = m_cacheability_table[ireq.addr];
+        } 
+        else                                                                // MMU activated
+        { 
+            m_cpt_ins_tlb_read++;
+            icache_hit_t  = icache_tlb.cctranslate(ireq.addr, &tlb_ipaddr, &icache_pte_info, 
+                                                   &icache_tlb_nline, &icache_tlb_way, &icache_tlb_set); 
+            icache_hit_x  = (((vaddr_t)r_icache_vpn_save << PAGE_K_NBITS) == (ireq.addr & ~PAGE_K_MASK)) && r_itlb_translation_valid;
+            icache_hit_p  = (((ireq.addr >> PAGE_M_NBITS) == r_icache_id1_save) && r_icache_ptba_ok); 
+            spc_ipaddr    = ((paddr_t)r_icache_ppn_save << PAGE_K_NBITS) | (paddr_t)(ireq.addr & PAGE_K_MASK);
+            icache_cached = icache_pte_info.c; 
+        }
+
+        if ( !(r_mmu_mode.read() & INS_CACHE_MASK) )   // cache not actived
+        {
+            icache_cached = false;
+        }
+
+        if ( ireq.valid ) 
+        {
+            m_cpt_icache_dir_read += m_icache_ways;
+            m_cpt_icache_data_read += m_icache_ways;
+
+            // icache_hit_c & icache_ins
+            if ( icache_cached )    // using speculative physical address for cached access
+            {
+                icache_hit_c = r_icache.read(spc_ipaddr, &icache_ins);
+            }
+            else                    // using actual physical address for uncached access
+            {
+                icache_hit_c = ( r_icache_buf_unc_valid && (tlb_ipaddr == (paddr_t)r_icache_paddr_save) );
+                icache_ins = r_icache_miss_buf[0];
+            }
+
+            if ( r_mmu_mode.read() & INS_TLB_MASK ) 
+            {
+                if ( icache_hit_t ) 
+                {
+                    // check access rights
+                    if ( !icache_pte_info.u && (ireq.mode == iss_t::MODE_USER)) 
+                    {
+                        r_icache_error_type = MMU_READ_PRIVILEGE_VIOLATION;  
+                        r_icache_bad_vaddr = ireq.addr;
+                        irsp.valid = true;
+                        irsp.error = true;
+                        irsp.instruction = 0;
+                        break;
+                    }
+                    if ( !icache_pte_info.x ) 
+                    {
+                        r_icache_error_type = MMU_READ_EXEC_VIOLATION;  
+                        r_icache_bad_vaddr = ireq.addr;
+                        irsp.valid = true;
+                        irsp.error = true;
+                        irsp.instruction = 0;
+                        break;
+                    }
+                }
+
+                // update LRU, save ppn, vpn and page type
+                if ( icache_hit_t )
+                {  
+                    icache_tlb.setlru(icache_tlb_way,icache_tlb_set);     
+                    r_icache_ppn_save = tlb_ipaddr >> PAGE_K_NBITS;
+                    r_icache_vpn_save = ireq.addr >> PAGE_K_NBITS;
+                    r_icache_tlb_nline = icache_tlb_nline;
+                    r_itlb_translation_valid = true;
+                }
+                else
+                {
+                    r_itlb_translation_valid = false;
+                }
+
+            } // end if MMU activated
+
+            // compute next state 
+            if ( !icache_hit_t && !icache_hit_p )      // TLB miss
+            {
+                // walk page table  level 1
+                r_icache_paddr_save = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((ireq.addr>>PAGE_M_NBITS)<<2);
+                r_itlb_read_dcache_req = true;
+		r_icache_vaddr_req = ireq.addr;
+                r_icache_fsm = ICACHE_TLB1_READ;
+                m_cpt_ins_tlb_miss++;
+                m_cost_ins_tlb_miss_frz++;
+            }
+            else if ( !icache_hit_t && icache_hit_p )  // TLB Miss with possibility of bypass first level page
+            {
+                // walk page table level 2
+                r_icache_paddr_save = (paddr_t)r_icache_ptba_save | 
+                                      (paddr_t)(((ireq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                r_itlb_read_dcache_req = true;
+		r_icache_vaddr_req = ireq.addr;
+                r_icache_fsm = ICACHE_TLB2_READ;
+                m_cpt_ins_tlb_miss++;
+                m_cost_ins_tlb_miss_frz++;
+            }
+            else if ( icache_hit_t && !icache_hit_x && icache_cached ) // cached access with an ucorrect speculative physical address
+            {
+                r_icache_paddr_save = tlb_ipaddr;   // save actual physical address for BIS
+		r_icache_vaddr_req = ireq.addr;
+                r_icache_fsm = ICACHE_BIS;
+                m_cost_ins_miss_frz++;
+            }
+            else    // cached or uncached access with a correct speculative physical address 
+            {        
+                m_cpt_ins_read++; 
+                if ( !icache_hit_c ) 
+                {
+                    m_cpt_ins_miss++;
+                    m_cost_ins_miss_frz++;
+                    if ( icache_cached ) 
+                    {
+                        r_icache_miss_req = true;
+                    	r_icache_paddr_save = spc_ipaddr; 
+			r_icache_vaddr_req = ireq.addr;
+                        r_icache_fsm = ICACHE_MISS_WAIT;
+                    } 
+                    else 
+                    {
+                        r_icache_unc_req = true;
+                        r_icache_buf_unc_valid = false;
+                    	r_icache_paddr_save = tlb_ipaddr; 
+			r_icache_vaddr_req = ireq.addr;
+                        r_icache_fsm = ICACHE_UNC_WAIT;
+                    } 
+                } 
+                else 
+                {
+                    r_icache_buf_unc_valid = false;
+                    r_icache_fsm = ICACHE_IDLE;
+                }
+                irsp.valid = icache_hit_c;
+                irsp.instruction = icache_ins;
+            } // end if next states
+            
+        } // end if ireq.valid
+        break;
+    }
+    ////////////////
+    case ICACHE_BIS: 
+    {
+        m_cost_ins_miss_frz++;
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+      
+        // using page is invalidated 
+        if ( r_icache_inval_tlb_rsp )
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+            m_cost_ins_tlb_miss_frz++;
+            break;
+        }
+ 
+        data_t	icache_ins = 0;
+        bool	icache_hit_c = false;
+        bool    icache_hit_t = false;
+        paddr_t	tlb_ipaddr = 0;
+
+	icache_hit_t = icache_tlb.translate(ireq.addr, &tlb_ipaddr);
+
+	if ( (tlb_ipaddr == r_icache_paddr_save.read()) && ireq.valid && icache_hit_t )		// unmodified & valid
+	{
+            m_cpt_ins_read++;
+
+            // acces is always cached in this state
+            icache_hit_c = r_icache.read(r_icache_paddr_save, &icache_ins);
+
+            if ( !icache_hit_c )
+            {
+                r_icache_miss_req = true;
+                r_icache_fsm = ICACHE_MISS_WAIT;
+                m_cpt_ins_miss++;
+            } 
+            else
+            {
+                r_icache_fsm = ICACHE_IDLE; 
+            }
+            irsp.valid = icache_hit_c;
+	    if (irsp.valid)
+	      assert((r_icache_vaddr_req.read() == ireq.addr) &&
+	          "vaddress should not be modified while ICACHE_BIS");
+            irsp.error = false;
+            irsp.instruction = icache_ins;
+	}
+	else	// modified or invalid
+	{
+            irsp.valid = false;
+            irsp.error = false;
+            irsp.instruction = 0;
+            r_icache_fsm = ICACHE_IDLE;
+	}
+        break;
+    }
+    //////////////////////
+    case ICACHE_TLB1_READ:
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_itlb_read_dcache_req )
+	{
+	    if (r_icache_vaddr_req.read() != ireq.addr || !ireq.valid) 
+	    {
+		/* request modified, drop response and restart */
+		r_icache_ptba_ok = false;
+            	if ( r_icache_inval_tlb_rsp )	r_icache_inval_tlb_rsp = false;
+                if ( r_dcache_rsp_itlb_error )	r_dcache_rsp_itlb_error = false;
+		r_icache_fsm = ICACHE_IDLE;
+		break;
+	    }
+
+            if ( !r_icache_inval_tlb_rsp ) // TLB miss read response and no invalidation
+            {
+                if ( !r_dcache_rsp_itlb_error ) // vci response ok
+                {  
+            	    if ( !(r_dcache_rsp_itlb_miss >> PTE_V_SHIFT) ) // unmapped
+            	    {
+                	r_icache_ptba_ok    = false;	
+                        r_icache_error_type = MMU_READ_PT1_UNMAPPED;  
+                        r_icache_bad_vaddr  = r_icache_vaddr_req.read();
+                        r_icache_fsm        = ICACHE_ERROR;
+            	    }
+            	    else if ( (r_dcache_rsp_itlb_miss & PTE_T_MASK ) >> PTE_T_SHIFT ) // PTD
+            	    {
+                	r_icache_ptba_ok       = true;	
+                        r_icache_ptba_save     = (paddr_t)(r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS; 
+                        r_icache_id1_save      = r_icache_vaddr_req.read() >> PAGE_M_NBITS;
+                        r_icache_paddr_save    = (paddr_t)(r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
+                                                 (paddr_t)(((r_icache_vaddr_req.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3); 
+                        r_itlb_read_dcache_req = true;
+			r_itlb_k_read_dcache   = true;
+                        r_icache_fsm           = ICACHE_TLB2_READ;
+             	    }	
+            	    else
+            	    {
+                	r_icache_ptba_ok = false;
+            
+            	        if ( (m_srcid_rw >> 4) == ((r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+            	        {
+            		    if ( (r_dcache_rsp_itlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+            		    {
+                                r_icache_pte_update = r_dcache_rsp_itlb_miss;
+                                r_icache_fsm        = ICACHE_TLB1_UPDT;
+            		    }
+            		    else
+            		    {
+                                r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_L_MASK;
+                                r_itlb_acc_dcache_req = true;
+                                r_icache_fsm          = ICACHE_TLB1_WRITE;
+                                m_cpt_ins_tlb_write_et++;
+            		    }
+                        }
+            	        else // remotely
+            	        {
+            		    if ( (r_dcache_rsp_itlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+            		    {
+                                r_icache_pte_update = r_dcache_rsp_itlb_miss;
+                                r_icache_fsm        = ICACHE_TLB1_UPDT;
+            		    }
+            		    else
+            		    {
+                                r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_R_MASK;
+                                r_itlb_acc_dcache_req = true;
+                                r_icache_fsm          = ICACHE_TLB1_WRITE;
+                                m_cpt_ins_tlb_write_et++;
+            		    }
+            	        }
+            	    }
+                }
+                else                        // vci response error
+                {  
+                    r_icache_fsm = ICACHE_ERROR;
+                    r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;    
+                    r_icache_bad_vaddr = r_icache_vaddr_req.read();
+                }
+            }
+
+            if ( r_icache_inval_tlb_rsp ) // TLB miss read response and invalidation
+            {
+                if ( r_dcache_rsp_itlb_error ) 
+                {
+                    r_icache_inval_tlb_rsp = false;
+                    r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;    
+                    r_icache_bad_vaddr = r_icache_vaddr_req.read();
+                    r_icache_fsm = ICACHE_ERROR;
+                } 
+                else 
+                {
+                    r_icache_inval_tlb_rsp = false;
+                    r_icache_fsm = ICACHE_IDLE;  
+                } 
+            }
+	}
+        break;
+    }
+    ///////////////////////
+    case ICACHE_TLB1_WRITE:  
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( !r_itlb_acc_dcache_req ) // TLB access bits write response 
+	{        
+            if ( !r_icache_inval_tlb_rsp ) // TLB access bits write response and no invalidation        
+            { 
+                if ( r_dcache_rsp_itlb_error ) 
+                {
+                    r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;  
+                    r_icache_bad_vaddr = r_icache_vaddr_req.read();
+                    r_icache_fsm = ICACHE_ERROR;
+                } 
+                else  
+                {
+                    r_icache_fsm = ICACHE_TLB1_UPDT;  
+                }
+            } 
+
+            if ( r_icache_inval_tlb_rsp) // TLB ET write response and invalidation     
+            {   
+                if ( r_dcache_rsp_itlb_error ) 
+                {
+                    r_icache_inval_tlb_rsp = false;
+                    r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;  
+                    r_icache_bad_vaddr = r_icache_vaddr_req.read();
+                    r_icache_fsm = ICACHE_ERROR;
+                } 
+                else  
+                {
+                    r_icache_inval_tlb_rsp = false;
+                    r_icache_fsm = ICACHE_IDLE;    
+                }
+            }
+	}
+        break;
+    }
+    //////////////////////
+    case ICACHE_TLB1_UPDT:
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req ) 
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // TLB update and invalidate different PTE
+        if ( !r_dcache_itlb_cleanup_req && !r_icache_inval_tlb_rsp )  
+        {
+            paddr_t victim_index = 0;
+            r_dcache_itlb_cleanup_req = icache_tlb.update(r_icache_pte_update,r_icache_vaddr_req.read(),(r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index);
+            r_dcache_itlb_cleanup_line = victim_index;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+
+        // TLB update and invalidate same PTE
+        if ( r_icache_inval_tlb_rsp )                                 
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB2_READ:
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( !r_itlb_read_dcache_req  ) // TLB miss read response
+	{ 
+	    if (r_icache_vaddr_req.read() != ireq.addr || !ireq.valid) 
+	    {
+		/* request modified, drop response and restart */
+		r_icache_ptba_ok = false;
+            	if ( r_icache_inval_tlb_rsp )	r_icache_inval_tlb_rsp = false;
+                if ( r_dcache_rsp_itlb_error )	r_dcache_rsp_itlb_error = false;
+		r_icache_fsm = ICACHE_IDLE;
+		break;
+	    }
+
+            if ( !r_icache_inval_tlb_rsp ) // TLB miss read response 
+            {
+                if ( !r_dcache_rsp_itlb_error ) // VCI response ok        
+                {
+            	    if ( !(r_dcache_rsp_itlb_miss >> PTE_V_SHIFT) ) // unmapped
+            	    {
+                        r_icache_error_type = MMU_READ_PT2_UNMAPPED;  
+                        r_icache_bad_vaddr  = r_icache_vaddr_req.read();
+                        r_icache_fsm = ICACHE_ERROR;
+            	    }
+            	    else
+            	    {
+            	        if ( (m_srcid_rw >> 4) == ((r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+            	        {
+            		    if ( (r_dcache_rsp_itlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+            		    {
+                        	r_icache_fsm        = ICACHE_TLB2_UPDT;
+                        	r_icache_pte_update = r_dcache_rsp_itlb_miss;
+            		    }
+            		    else
+            		    {
+                        	r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_L_MASK;
+                        	r_itlb_acc_dcache_req = true;
+                        	r_icache_fsm          = ICACHE_TLB2_WRITE;
+                         	m_cpt_ins_tlb_write_et++;
+            		    }
+                        }
+            	    	else // remotely
+            	    	{
+            		    if ( (r_dcache_rsp_itlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+            		    {
+                        	r_icache_fsm        = ICACHE_TLB2_UPDT;
+                        	r_icache_pte_update = r_dcache_rsp_itlb_miss;
+            		    }
+            		    else
+            		    {
+                        	r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_R_MASK;
+                        	r_itlb_acc_dcache_req = true;
+                        	r_icache_fsm          = ICACHE_TLB2_WRITE;
+                        	m_cpt_ins_tlb_write_et++;
+            		    }
+            	        }
+            	    }
+                }
+                else                            // VCI response error        
+                {
+                    r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                    r_icache_bad_vaddr = r_icache_vaddr_req.read();
+                    r_icache_fsm = ICACHE_ERROR;
+                }
+            }
+            
+            if ( r_icache_inval_tlb_rsp ) // TLB miss read response and invalidation
+            {
+                if ( r_dcache_rsp_itlb_error ) 
+                {
+                    r_icache_inval_tlb_rsp = false;
+                    r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;    
+                    r_icache_bad_vaddr = r_icache_vaddr_req.read();
+                    r_icache_fsm = ICACHE_ERROR;
+                } 
+                else 
+                {
+                    r_icache_inval_tlb_rsp = false;
+                    r_icache_fsm = ICACHE_IDLE;  
+                } 
+            }
+	}
+        break;
+    }
+    /////////////////////////
+    case ICACHE_TLB2_WRITE:
+    {  
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( !r_itlb_acc_dcache_req ) // TLB access bits write response          
+	{
+            if ( !r_icache_inval_tlb_rsp ) // TLB access bits write response          
+            {
+                if ( r_dcache_rsp_itlb_error )             
+                {
+                    r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;  
+                    r_icache_bad_vaddr = r_icache_vaddr_req.read();
+                    r_icache_fsm = ICACHE_ERROR;
+                } 
+                else  
+                {
+                    r_icache_fsm = ICACHE_TLB2_UPDT;  
+                }
+            }
+ 
+            if ( r_icache_inval_tlb_rsp ) // TLB ET write response and invalidation     
+            {   
+                if ( r_dcache_rsp_itlb_error ) 
+                {
+                    r_icache_inval_tlb_rsp = false;
+                    r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;  
+                    r_icache_bad_vaddr = r_icache_vaddr_req.read();
+                    r_icache_fsm = ICACHE_ERROR;
+                } 
+                else  
+                {
+                    r_icache_inval_tlb_rsp = false;
+                    r_icache_fsm = ICACHE_IDLE;    
+                }
+            }
+	}
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB2_UPDT: 
+    {
+        m_cost_ins_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req ) 
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // TLB update and invalidate different PTE
+        if ( !r_dcache_itlb_cleanup_req && !r_icache_inval_tlb_rsp ) 
+        {
+            paddr_t victim_index = 0;
+            r_dcache_itlb_cleanup_req = icache_tlb.update(r_icache_pte_update,r_dcache_rsp_itlb_ppn,r_icache_vaddr_req.read(),(r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index);
+            r_dcache_itlb_cleanup_line = victim_index;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        // TLB update and invalidate same PTE
+        if ( r_icache_inval_tlb_rsp )                            
+        {
+            r_icache_inval_tlb_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    /////////////////////////////
+    case ICACHE_SW_FLUSH:
+    {
+        size_t way = r_icache_way;
+        size_t set = r_icache_set;
+        bool clean = false;
+
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+        m_cost_ins_tlb_sw_frz++;
+
+        // 4K page size TLB flush leads to cleanup req to data cache 
+        if ( !r_dcache_itlb_cleanup_req )    // last cleanup finish
+        {
+            paddr_t victim_index = 0;
+            for ( ; way < m_itlb_ways; way++)
+            {
+                for ( ; set < m_itlb_sets; set++)
+                {
+                    if(icache_tlb.checkcleanup(way, set, &victim_index))
+                    {
+                        clean = true;
+                        r_dcache_itlb_cleanup_req = true;
+                        r_dcache_itlb_cleanup_line = victim_index;
+                        r_icache_way = way + ((set+1)/m_itlb_sets);
+                        r_icache_set = (set+1) % m_itlb_sets;
+                        break;
+                    }
+                }
+                if (clean) break;
+            }
+
+            if (way == m_itlb_ways)
+            {
+                r_dcache_xtn_req = false;
+        	r_itlb_translation_valid = false;
+        	r_icache_ptba_ok = false;
+                r_icache_fsm = ICACHE_IDLE;
+                break;
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB_FLUSH:
+    {   
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+
+        // data cache flush leads to ins tlb flush, flush all tlb entry 
+        icache_tlb.flush(true);    // global entries are invalidated
+        r_dcache_xtn_req = false;
+	r_itlb_translation_valid = false;
+        r_icache_ptba_ok = false;
+        r_icache_fsm = ICACHE_IDLE;
+        break;
+    }
+    ////////////////////////
+    case ICACHE_CACHE_FLUSH:
+    {
+        // external cache invalidate request
+        if ( r_tgt_icache_req )
+        {
+            r_tgt_icache_req = false;
+        }
+
+        size_t way = r_icache_way;
+        size_t set = r_icache_set;
+        bool clean = false;
+
+        m_cost_ins_cache_flush_frz++;
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+
+        // cache flush and send cleanup to external
+        if ( !r_icache_cleanup_req )
+        {
+            paddr_t victim_index = 0;
+            for ( ; way < m_icache_ways; way++ )
+            {    
+                for ( ; set < m_icache_sets; set++ )
+                {    
+                    if ( r_icache.flush(way, set, &victim_index) )
+                    {
+                        clean = true;
+                        r_icache_cleanup_req = true;
+                        r_icache_cleanup_line = victim_index;
+                        r_icache_way = way + ((set+1)/m_icache_sets);
+                        r_icache_set = (set+1) % m_icache_sets;
+                        break;
+                    }
+                }
+                if (clean) break;
+            }
+            if (way == m_icache_ways)
+            {
+                r_dcache_xtn_req = false;
+                r_icache_fsm = ICACHE_IDLE;
+                break;
+            }
+        }
+        break;
+    }
+    /////////////////////
+    case ICACHE_TLB_INVAL:  
+    {
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+        paddr_t victim_index = 0;
+
+        if ( !r_dcache_itlb_cleanup_req )
+        {
+            r_dcache_itlb_cleanup_req = icache_tlb.inval(r_dcache_wdata_save, &victim_index);
+            r_dcache_itlb_cleanup_line = victim_index;
+            r_dcache_xtn_req = false;
+            r_itlb_translation_valid = false;
+            r_icache_ptba_ok = false;
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    ////////////////////////
+    case ICACHE_CACHE_INVAL:
+    {	
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+
+        paddr_t ipaddr = 0;                     
+        bool    icache_hit_t = false;
+
+        if ( !r_icache_cleanup_req )
+        {    
+            if ( r_mmu_mode.read() & INS_TLB_MASK ) 
+            {
+                icache_hit_t = icache_tlb.translate(r_dcache_wdata_save, &ipaddr); 
+            } 
+            else 
+            {
+                ipaddr = (paddr_t)r_dcache_wdata_save;
+                icache_hit_t = true;
+            }
+            if ( icache_hit_t )
+            {
+                // invalidate and cleanup if necessary
+                r_icache_cleanup_req = r_icache.inval(ipaddr);
+                r_icache_cleanup_line = ipaddr >> (uint32_log2(m_icache_words) + 2);   
+            }
+            r_dcache_xtn_req = false; 
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    ////////////////////////
+    case ICACHE_CACHE_INVAL_PA:
+    {	
+        paddr_t ipaddr = (paddr_t)r_mmu_word_hi.read() << 32 | r_mmu_word_lo.read();
+
+        if ( !r_icache_cleanup_req )
+        {    
+            // invalidate and cleanup if necessary
+            r_icache_cleanup_req = r_icache.inval(ipaddr);
+            r_icache_cleanup_line = ipaddr >> (uint32_log2(m_icache_words) + 2);   
+            r_dcache_xtn_req = false; 
+            r_icache_fsm = ICACHE_IDLE;
+        }
+        break;
+    }
+    ///////////////////////
+    case ICACHE_MISS_WAIT:
+    {
+        m_cost_ins_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )     
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+       
+	if ( !r_icache_miss_req )
+	{
+	    if ( r_vci_rsp_ins_error ) 
+            {
+                r_icache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+
+            	if ( r_icache_inval_tlb_rsp ) r_icache_inval_tlb_rsp = false;
+            	if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
+		break;
+            }
+
+            if ( r_icache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+		if ( r_icache_cleanup_req ) break;
+                r_icache_cleanup_req = true;
+                r_icache_cleanup_line = r_icache_paddr_save.read() >> (uint32_log2(m_icache_words) + 2);  
+                r_icache_fsm = ICACHE_IDLE;
+                r_icache_inval_tlb_rsp = false;
+                if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
+                m_cost_ins_tlb_miss_frz++;
+                break;
+            }
+	
+            if ( r_icache_inval_rsp ) // Miss read response and tlb invalidation
+            {
+		if ( r_icache_cleanup_req ) break;
+                r_icache_cleanup_req = true;
+                r_icache_cleanup_line = r_icache_paddr_save.read() >> (uint32_log2(m_icache_words) + 2);  
+                r_icache_fsm = ICACHE_IDLE;
+                r_icache_inval_rsp = false;
+                break;
+            }
+            r_icache_fsm = ICACHE_MISS_UPDT;  
+	}	
+        break;
+    }
+    ////////////////////
+    case ICACHE_UNC_WAIT:
+    {
+        m_cost_ins_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req ) 
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_icache_unc_req )
+	{
+	    if ( r_vci_rsp_ins_error ) 
+            {
+                r_icache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS;    
+                r_icache_bad_vaddr = ireq.addr;
+                r_icache_fsm = ICACHE_ERROR;
+
+            	if ( r_icache_inval_tlb_rsp ) r_icache_inval_tlb_rsp = false;
+            	//if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
+		break;
+            }
+
+	    if ( r_icache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_icache_inval_tlb_rsp = false;
+                r_icache_fsm = ICACHE_IDLE;
+		break;
+            }
+
+	    // Miss read response and no invalidation
+            r_icache_buf_unc_valid = true;
+            r_icache_fsm = ICACHE_IDLE;
+	}	
+        break;
+    }
+    //////////////////////
+    case ICACHE_MISS_UPDT:
+    {
+        m_cost_ins_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_icache_req )   
+        {
+            r_icache_fsm = ICACHE_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        // external tlb invalidate request
+        if ( r_dcache_itlb_inval_req )
+        {
+	    r_itlb_inval_req = true;
+            r_icache_fsm = ICACHE_TLB_CC_INVAL;
+            r_icache_fsm_save = r_icache_fsm;
+            m_cost_ins_waste_wait_frz++;
+            break;
+        }
+
+        if ( r_icache_inval_tlb_rsp ) // tlb invalidation
+        {
+            if ( r_icache_cleanup_req ) break;
+            r_icache_cleanup_req = true;
+            r_icache_cleanup_line = r_icache_paddr_save.read() >> (uint32_log2(m_icache_words) + 2);  
+            r_icache_inval_tlb_rsp = false;
+            if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
+            r_icache_fsm = ICACHE_IDLE;
+            m_cost_ins_tlb_miss_frz++;
+            break;
+        }
+
+        if ( !r_icache_cleanup_req ) // Miss update and no invalidation
+        {
+            if ( r_icache_inval_rsp ) // invalidation
+            {
+                r_icache_cleanup_req = true;
+                r_icache_cleanup_line = r_icache_paddr_save.read() >> (uint32_log2(m_icache_words) + 2);  
+                r_icache_fsm = ICACHE_IDLE;
+                r_icache_inval_rsp = false;
+            } 
+	    else
+	    {
+                data_t* buf = r_icache_miss_buf;
+                paddr_t  victim_index = 0;
+                m_cpt_icache_dir_write++;
+                m_cpt_icache_data_write++;
+
+                r_icache_cleanup_req = r_icache.update(r_icache_paddr_save.read(), buf, &victim_index);
+                r_icache_cleanup_line = victim_index;            
+
+                r_icache_fsm = ICACHE_IDLE;
+	    }
+        }
+        break;
+    }
+    ///////////////////
+    case ICACHE_ERROR:
+    {
+        r_vci_rsp_ins_error = false;
+        r_dcache_rsp_itlb_error = false;
+        irsp.valid = true;
+        irsp.error = true;
+        irsp.instruction = 0; 
+        r_icache_fsm = ICACHE_IDLE;
+        break;
+    }
+    /////////////////////
+    case ICACHE_CC_INVAL:  
+    {                       
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
+        m_cpt_icache_dir_read += m_icache_ways;
+
+        // invalidate cache
+        if( (( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT ) /*|| 
+             ( r_icache_fsm_save == ICACHE_UNC_WAIT )*/ ) && 
+            ((r_icache_paddr_save.read() & ~((m_icache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_icache_words<<2)-1))) ) 
+        {
+            r_icache_inval_rsp = true;
+	    r_tgt_icache_rsp = false;
+        } 
+        else 
+        {
+            r_tgt_icache_rsp = r_icache.inval(r_tgt_addr.read());
+        }
+        r_tgt_icache_req = false;
+        r_icache_fsm = r_icache_fsm_save;
+        break;
+    }
+    /////////////////////////
+    case ICACHE_TLB_CC_INVAL:
+    {
+        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;        
+
+	if ( r_itlb_inval_req ) break;
+        // invalidate cache
+        if( (( r_icache_fsm_save == ICACHE_TLB1_READ ) || ( r_icache_fsm_save == ICACHE_TLB2_READ )  ||
+          /* ( r_icache_fsm_save == ICACHE_TLB1_WRITE )|| ( r_icache_fsm_save == ICACHE_TLB2_WRITE ) ||*/
+             ( r_icache_fsm_save == ICACHE_TLB1_UPDT ) || ( r_icache_fsm_save == ICACHE_TLB2_UPDT )) && 
+            (((r_icache_paddr_save.read() & ~((m_icache_words<<2)-1)) >> (uint32_log2(m_icache_words) + 2) ) == r_dcache_itlb_inval_line.read()) ) 
+        {
+            r_icache_inval_tlb_rsp = true;
+        } 
+        else if (((r_icache_fsm_save == ICACHE_BIS)||(r_icache_fsm_save == ICACHE_MISS_WAIT) ||
+               /* (r_icache_fsm_save == ICACHE_UNC_WAIT)||*/(r_icache_fsm_save == ICACHE_MISS_UPDT)) && 
+                (r_icache_tlb_nline.read() == r_dcache_itlb_inval_line.read()))
+        {
+            r_icache_inval_tlb_rsp = true;
+        }
+	r_dcache_itlb_inval_req = false;
+	r_itlb_translation_valid = false;
+        r_icache_ptba_ok = false;
+        r_icache_fsm = r_icache_fsm_save;
+        break;
+    }
+    } // end switch r_icache_fsm
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout << name() << " Instruction Response: " << irsp << std::endl;
+#endif
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //      INVAL ITLB CHECK FSM 
+    ////////////////////////////////////////////////////////////////////////////////////////
+    switch(r_inval_itlb_fsm) {
+    /////////////////////
+    case INVAL_ITLB_IDLE:
+    {
+        if ( r_itlb_inval_req )
+        {
+            r_ccinval_itlb_way = 0; 
+            r_ccinval_itlb_set = 0;
+            r_inval_itlb_fsm = INVAL_ITLB_CHECK;   
+            m_cost_ins_tlb_inval_frz++; 
+        }   
+        break;
+    }
+    ////////////////////////////
+    case INVAL_ITLB_CHECK:
+    {
+        m_cost_ins_tlb_inval_frz++; 
+
+        size_t way = r_ccinval_itlb_way; 
+        size_t set = r_ccinval_itlb_set;
+        bool end = false;        
+        bool tlb_hit = icache_tlb.cccheck(r_dcache_itlb_inval_line.read(), way, set, &way, &set, &end); 
+    
+        if ( tlb_hit )
+        {
+            r_ccinval_itlb_way = way; 
+            r_ccinval_itlb_set = set;
+            r_itlb_cc_check_end = end;
+            r_inval_itlb_fsm = INVAL_ITLB_INVAL; 
+            m_cpt_ins_tlb_inval++;   
+        }        
+        else
+        {
+            r_inval_itlb_fsm = INVAL_ITLB_CLEAR;    
+        }
+        break;
+    }
+    /////////////////////////
+    case INVAL_ITLB_INVAL:
+    {
+        m_cost_ins_tlb_inval_frz++;
+ 
+        icache_tlb.ccinval(r_ccinval_itlb_way, r_ccinval_itlb_set);
+
+        if ( !r_itlb_cc_check_end )
+        {
+            r_inval_itlb_fsm = INVAL_ITLB_CHECK; 
+        }
+        else
+        {
+            r_inval_itlb_fsm = INVAL_ITLB_CLEAR;    
+        }
+        break;
+    }
+    ////////////////////
+    case INVAL_ITLB_CLEAR:
+    {
+        r_itlb_inval_req = false;
+        r_itlb_cc_check_end = false;
+        r_ccinval_itlb_way = 0; 
+        r_ccinval_itlb_set = 0; 
+        r_inval_itlb_fsm = INVAL_ITLB_IDLE;    
+        m_cost_ins_tlb_inval_frz++; 
+        break;
+    }
+    } // end switch r_inval_itlb_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //      DCACHE FSM 
+    //
+    // Both the Cacheability Table, and the MMU cached bit are used to define
+    // the cacheability.
+    // 
+    // There is 14 mutually exclusive conditions to exit the IDLE state.
+    // Seven configurations corresponding to an XTN request from processor:
+    // - Context switch => CTXT_SWITCH state
+    // - Flush dcache => DCACHE_FLUSH state 
+    // - Flush icache => ICACHE_FLUSH state 
+    // - Invalidate a dtlb entry => DTLB_INVAL state
+    // - Invalidate a itlb entry => ITLB_INVAL state
+    // - Invalidate a dcache line => DCACHE_INVAL state
+    // - Invalidate a icache line => ICACHE_INVAL state
+    // Seven configurations corresponding to various read miss or write requests: 
+    // - TLB miss(in case hit_p miss) => TLB1_READ state
+    // - TLB miss(in case hit_p hit) => TLB2_READ state
+    // - Hit in TLB but VPN changed => BIS state
+    // - Cached read miss => MISS_REQ state
+    // - Uncache read miss => UNC_REQ state
+    // - Write hit => WRITE_UPDT state
+    // - Write miss => WRITE_REQ
+    //
+    // The r_vci_rsp_data_error flip-flop is set by the VCI_RSP controller and reset 
+    // by DCACHE-FSM when its state is in DCACHE_ERROR. 
+    //--------------------------------------------------------------------- 
+    // Data TLB: 
+    //  
+    // - int        ET          (00: unmapped; 01: unused or PTD)
+    //                          (10: PTE new;  11: PTE old      )
+    // - bool       cachable    (cached bit)
+    // - bool       writable    (writable bit) 
+    // - bool       executable  (** not used alwayse false)
+    // - bool       user        (access in user mode allowed)
+    // - bool       global      (PTE not invalidated by a TLB flush)
+    // - bool       dirty       (page has been modified) 
+    // - uint32_t   vpn         (virtual page number)
+    // - uint32_t   ppn         (physical page number)
+    ////////////////////////////////////////////////////////////////////////////////////////
+
+    switch (r_dcache_fsm) {
+    //////////////////////
+    case DCACHE_WRITE_REQ:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++; 
+            break;
+        }
+
+        // try to post the write request in the write buffer
+        if ( !r_dcache_write_req )     // no previous write transaction     
+        {
+            if ( r_wbuf.wok(r_dcache_paddr_save) )   // write request in the same cache line 
+            {    
+                r_wbuf.write(r_dcache_paddr_save.read(), r_dcache_be_save.read(), r_dcache_wdata_save);
+                // closing the write packet if uncached
+                if ( !r_dcache_cached_save )
+                { 
+                    r_dcache_write_req = true;
+                }
+            } 
+            else 
+            {    // close the write packet if write request not in the same cache line
+                r_dcache_write_req = true;
+                m_cost_write_frz++;
+                break;  //  posting not possible : stay in DCACHE_WRITEREQ state
+            }
+        } 
+        else     //  previous write transaction not completed
+        {
+            m_cost_write_frz++;
+            break;  //  posting not possible : stay in DCACHE_WRITEREQ state
+        }
+
+        // close the write packet if the next processor request is not a write 
+        if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE)) 
+        {
+            r_dcache_write_req = true;
+        }
+        
+        // The next state and the processor request parameters are computed 
+        // as in the DCACHE_IDLE state (see below ...)
+    }
+    /////////////////
+    case DCACHE_IDLE:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = DCACHE_IDLE;
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // ins tlb cleanup
+        if ( r_dcache_itlb_cleanup_req )
+        {
+            r_dcache_fsm = DCACHE_ITLB_CLEANUP;
+            m_cpt_ins_tlb_cleanup++;
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+            break;
+        }    
+        // ins tlb miss
+    	if ( r_itlb_read_dcache_req )
+    	{
+            data_t rsp_itlb_miss;
+	    data_t rsp_itlb_ppn;
+
+    	    bool itlb_hit_dcache = r_dcache.read(r_icache_paddr_save, &rsp_itlb_miss);
+	    if ( (r_icache_fsm == ICACHE_TLB2_READ) && itlb_hit_dcache )
+	    {	
+	        bool itlb_hit_ppn = r_dcache.read(r_icache_paddr_save.read()+4, &rsp_itlb_ppn);
+		assert(itlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+	    }
+
+            m_cpt_dcache_data_read += m_dcache_ways;
+            m_cpt_dcache_dir_read += m_dcache_ways;
+
+    	    if ( itlb_hit_dcache )  // ins TLB request hits in data cache 
+    	    {
+                r_dcache_rsp_itlb_miss = rsp_itlb_miss; 
+                r_dcache_rsp_itlb_ppn = rsp_itlb_ppn; 
+    	    	r_itlb_read_dcache_req = false;
+                r_dcache_fsm = DCACHE_IDLE;
+                
+                // set TLB bit if it's a PTE
+                if ( !((rsp_itlb_miss & PTE_T_MASK ) >> PTE_T_SHIFT) )
+                {
+                    r_dcache.setinbit(r_icache_paddr_save, r_dcache_in_itlb, true);
+                }
+    	    }
+    	    else                    // ins TLB request miss in data cache
+    	    {
+                r_dcache_itlb_read_req = true;
+                r_dcache_fsm = DCACHE_ITLB_READ;
+            }
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++; 
+    	}
+    	else if ( r_itlb_acc_dcache_req ) // ins tlb write access bit
+    	{
+            bool write_hit = r_dcache.write(r_icache_paddr_save, r_icache_pte_update);
+            assert(write_hit && "Write on miss ignores data");
+            r_dcache_itlb_ll_acc_req = true;
+	    r_dcache_fsm = DCACHE_ITLB_LL_WAIT;	    		
+            if ( dreq.valid ) m_cost_data_waste_wait_frz++; 
+    	}
+        else if (dreq.valid) 
+        {
+            pte_info_t  dcache_pte_info;
+            int         xtn_opcod        = (int)dreq.addr/4;
+            paddr_t     tlb_dpaddr       = 0;        // physical address obtained from TLB
+            paddr_t     spc_dpaddr       = 0;        // physical adress obtained from PPN_save (speculative)
+            bool        dcache_hit_t     = false;    // hit on 4Kilo TLB
+            bool        dcache_hit_x     = false;    // VPN unmodified (can use spc_dpaddr)
+            bool        dcache_hit_p     = false;    // PTP unmodified (can skip first level page table walk)
+            bool        dcache_hit_c     = false;    // Cache hit
+            bool        dcache_cached    = false;    // cacheable access (read or write)
+            size_t      dcache_tlb_way   = 0;        // selected way (in case of cache hit)
+            size_t      dcache_tlb_set   = 0;        // selected set (Y field in address)
+            data_t      dcache_rdata     = 0;        // read data
+            paddr_t     dcache_tlb_nline = 0;       // TLB NLINE 
+
+            m_cpt_dcache_data_read += m_dcache_ways;
+            m_cpt_dcache_dir_read += m_dcache_ways;
+
+            // Decoding READ XTN requests from processor
+            // They are executed in this DCACHE_IDLE state
+
+            if (dreq.type == iss_t::XTN_READ) 
+            {
+                switch(xtn_opcod) {
+                case iss_t::XTN_INS_ERROR_TYPE:
+                    drsp.rdata = (uint32_t)r_icache_error_type;
+                    r_icache_error_type = MMU_NONE;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_DATA_ERROR_TYPE:
+                    drsp.rdata = (uint32_t)r_dcache_error_type;
+                    r_dcache_error_type = MMU_NONE;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_INS_BAD_VADDR:
+                    drsp.rdata = (uint32_t)r_icache_bad_vaddr;       
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_DATA_BAD_VADDR:
+                    drsp.rdata = (uint32_t)r_dcache_bad_vaddr;        
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_PTPR:
+                    drsp.rdata = (uint32_t)r_mmu_ptpr;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_TLB_MODE:
+                    drsp.rdata = (uint32_t)r_mmu_mode;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_MMU_PARAMS:
+                    drsp.rdata = (uint32_t)r_mmu_params;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_MMU_RELEASE:
+                    drsp.rdata = (uint32_t)r_mmu_release;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_MMU_WORD_LO:
+                    drsp.rdata = (uint32_t)r_mmu_word_lo;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                case iss_t::XTN_MMU_WORD_HI:
+                    drsp.rdata = (uint32_t)r_mmu_word_hi;
+                    drsp.valid = true;
+                    drsp.error = false;
+                    break;
+                default:
+                    r_dcache_error_type = MMU_READ_UNDEFINED_XTN; 
+                    r_dcache_bad_vaddr  = dreq.addr;
+                    drsp.valid = true;
+                    drsp.error = true;
+                    break;
+                }
+                r_dcache_fsm = DCACHE_IDLE;
+                break;
+            }
+
+            // Decoding WRITE XTN requests from processor
+            // If there is no privilege violation, they are not executed in this DCACHE_IDLE state,
+            // but in the next state, because they generally require access to the caches or the TLBs 
+
+            if (dreq.type == iss_t::XTN_WRITE) 
+            {
+                drsp.valid = false;
+                drsp.error = false;
+                drsp.rdata = 0;
+                r_dcache_wdata_save = dreq.wdata;   
+                switch(xtn_opcod) {     
+
+                case iss_t::XTN_PTPR:       // context switch : checking the kernel mode
+                                            // both instruction & data TLBs must be flushed
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_mmu_ptpr = dreq.wdata;
+                        r_icache_error_type = MMU_NONE;
+                        r_dcache_error_type = MMU_NONE;
+                        r_dcache_type_save = dreq.addr/4; 
+                        r_dcache_xtn_req = true;
+                        r_dcache_fsm = DCACHE_CTXT_SWITCH;
+                    } 
+                    else 
+                    { 
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                	r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+
+                case iss_t::XTN_TLB_MODE:     // modifying TLBs mode : checking the kernel mode
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_mmu_mode = (int)dreq.wdata;
+                        drsp.valid = true;
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                    }
+                    r_dcache_fsm = DCACHE_IDLE;
+                    break;
+
+                case iss_t::XTN_DTLB_INVAL:     //  checking the kernel mode
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_dcache_fsm = DCACHE_DTLB_INVAL;  
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                	r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+
+                case iss_t::XTN_ITLB_INVAL:     //  checking the kernel mode
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_dcache_xtn_req = true;
+                        r_dcache_type_save = dreq.addr/4;
+                        r_dcache_fsm = DCACHE_ITLB_INVAL;  
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                	r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+
+                case iss_t::XTN_DCACHE_INVAL:   // cache inval can be executed in user mode.
+                    r_dcache_fsm = DCACHE_DCACHE_INVAL;
+                    break;
+
+                case iss_t::XTN_MMU_DCACHE_PA_INV:   // cache inval can be executed in user mode.
+                    r_dcache_fsm = DCACHE_DCACHE_INVAL_PA;
+                    break;
+
+                case iss_t::XTN_DCACHE_FLUSH:   // cache flush can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true;
+                    r_dcache_way = 0;
+                    r_dcache_set = 0;
+                    r_dcache_fsm = DCACHE_DCACHE_FLUSH; 
+                    break;
+
+                case iss_t::XTN_ICACHE_INVAL:   // cache inval can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true;
+                    r_dcache_fsm = DCACHE_ICACHE_INVAL; 
+                    break;
+
+                case iss_t::XTN_MMU_ICACHE_PA_INV:   // cache inval can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true;
+                    r_dcache_fsm = DCACHE_ICACHE_INVAL_PA; 
+                    break;
+
+                case iss_t::XTN_ICACHE_FLUSH:   // cache flush can be executed in user mode.
+                    r_dcache_type_save = dreq.addr/4; 
+                    r_dcache_xtn_req = true; 
+                    r_dcache_fsm = DCACHE_ICACHE_FLUSH;
+                    break;
+
+                case iss_t::XTN_SYNC:           // cache synchronization can be executed in user mode.
+                    if (r_wbuf.rok())
+                    {
+                        r_dcache_fsm = DCACHE_DCACHE_SYNC; 
+                    }
+                    else
+                    {
+                        drsp.valid = true;
+                        r_dcache_fsm = DCACHE_IDLE;
+                    }
+		    break;
+
+                case iss_t::XTN_MMU_WORD_LO: // modifying MMU misc registers
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_mmu_word_lo = (int)dreq.wdata;
+                        drsp.valid = true;
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                    }
+                    r_dcache_fsm = DCACHE_IDLE;
+                    break;
+
+                case iss_t::XTN_MMU_WORD_HI: // modifying MMU misc registers
+                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL)) 
+                    {
+                        r_mmu_word_hi = (int)dreq.wdata;
+                        drsp.valid = true;
+                    } 
+                    else 
+                    {
+                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION; 
+                        r_dcache_bad_vaddr  = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                    }
+                    r_dcache_fsm = DCACHE_IDLE;
+                    break;
+
+		  case iss_t::XTN_ICACHE_PREFETCH:
+		  case iss_t::XTN_DCACHE_PREFETCH:
+		    drsp.valid = true;
+                    drsp.error = false;
+		    break;
+	
+                default:
+                    r_dcache_error_type = MMU_WRITE_UNDEFINED_XTN; 
+                    r_dcache_bad_vaddr  = dreq.addr;
+                    drsp.valid = true;
+                    drsp.error = true;
+                    r_dcache_fsm = DCACHE_IDLE;
+                    break;
+                } // end switch xtn_opcod
+
+                break;
+            } // end if XTN_WRITE
+
+            // Evaluating dcache_hit_t, dcache_hit_x, dcache_hit_p, dcache_hit_c,
+            // dcache_pte_info, dcache_tlb_way, dcache_tlb_set & dpaddr & cacheability 
+            // - If MMU activated : cacheability is defined by the cachable bit in the TLB
+            // - If MMU not activated : cacheability is defined by the segment table.
+
+            if ( !(r_mmu_mode.read() & DATA_TLB_MASK) ) // MMU not activated
+            {
+                dcache_hit_t  = true;       
+                dcache_hit_x  = true;   
+                dcache_hit_p  = true;  
+                tlb_dpaddr    = dreq.addr; 
+                spc_dpaddr    = dreq.addr;    
+                dcache_cached = m_cacheability_table[dreq.addr] && 
+                                ((dreq.type != iss_t::DATA_LL)  && (dreq.type != iss_t::DATA_SC) &&
+                                 (dreq.type != iss_t::XTN_READ) && (dreq.type != iss_t::XTN_WRITE));     
+            } 
+            else                                                            // MMU activated
+            {
+                m_cpt_data_tlb_read++;
+                dcache_hit_t  = dcache_tlb.cctranslate(dreq.addr, &tlb_dpaddr, &dcache_pte_info, 
+                                                       &dcache_tlb_nline, &dcache_tlb_way, &dcache_tlb_set);                  
+                dcache_hit_x  = (((vaddr_t)r_dcache_vpn_save << PAGE_K_NBITS) == (dreq.addr & ~PAGE_K_MASK)) && r_dtlb_translation_valid; 
+                dcache_hit_p  = (((dreq.addr >> PAGE_M_NBITS) == r_dcache_id1_save) && r_dcache_ptba_ok );
+                spc_dpaddr    = ((paddr_t)r_dcache_ppn_save << PAGE_K_NBITS) | (paddr_t)((dreq.addr & PAGE_K_MASK));
+                dcache_cached = dcache_pte_info.c && 
+                                ((dreq.type != iss_t::DATA_LL)  && (dreq.type != iss_t::DATA_SC) &&
+                                 (dreq.type != iss_t::XTN_READ) && (dreq.type != iss_t::XTN_WRITE));    
+            }
+
+            if ( !(r_mmu_mode.read() & DATA_CACHE_MASK) )   // cache not actived
+            {
+                dcache_cached = false;
+            }
+
+            // dcache_hit_c & dcache_rdata
+            if ( dcache_cached )    // using speculative physical address for cached access
+            {
+                dcache_hit_c = r_dcache.read(spc_dpaddr, &dcache_rdata);
+            } 
+            else                    // using actual physical address for uncached access
+            {
+                dcache_hit_c = ((tlb_dpaddr == (paddr_t)r_dcache_paddr_save) && r_dcache_buf_unc_valid ); 
+                dcache_rdata = r_dcache_miss_buf[0];
+            }
+
+            if ( r_mmu_mode.read() & DATA_TLB_MASK ) 
+            {
+                // Checking access rights
+                if ( dcache_hit_t ) 
+                {
+                    if (!dcache_pte_info.u && (dreq.mode == iss_t::MODE_USER)) 
+                    {
+                        if ((dreq.type == iss_t::DATA_READ)||(dreq.type == iss_t::DATA_LL))
+                        {
+                            r_dcache_error_type = MMU_READ_PRIVILEGE_VIOLATION;
+                        }
+                        else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                        {
+                            r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION;
+                        }  
+                        r_dcache_bad_vaddr = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                        drsp.rdata = 0;
+                        r_dcache_fsm = DCACHE_IDLE;
+                        break;
+                    }
+                    if (!dcache_pte_info.w && ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))) 
+                    {
+                        r_dcache_error_type = MMU_WRITE_ACCES_VIOLATION;  
+                        r_dcache_bad_vaddr = dreq.addr;
+                        drsp.valid = true;
+                        drsp.error = true;
+                        drsp.rdata = 0;
+                        r_dcache_fsm = DCACHE_IDLE;
+                        break;
+                    }
+                }
+
+                // update LRU, save ppn, vpn and page type
+                if ( dcache_hit_t ) {
+                    dcache_tlb.setlru(dcache_tlb_way,dcache_tlb_set); 
+                    r_dcache_ppn_save = tlb_dpaddr >> PAGE_K_NBITS;
+                    r_dcache_vpn_save = dreq.addr >> PAGE_K_NBITS;
+                    r_dcache_tlb_nline = dcache_tlb_nline;
+                    r_dtlb_translation_valid = true;
+                }
+                else
+                {
+                    r_dtlb_translation_valid = false;
+                }
+
+            } // end if MMU activated
+
+            // compute next state 
+            if ( !dcache_hit_p && !dcache_hit_t )  // TLB miss
+            {
+                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                m_cpt_data_tlb_miss++;
+                m_cost_data_tlb_miss_frz++;
+            }
+            else if ( dcache_hit_p && !dcache_hit_t )  // TLB Miss with possibility of bypass first level page
+            {
+                // walk page table level 2
+                r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save | 
+                                     (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3); 
+                r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
+                m_cpt_data_tlb_miss++;
+                m_cost_data_tlb_miss_frz++;
+            }
+            else if ( dcache_hit_t && !dcache_hit_x && dcache_cached )// cached access with an ucorrect speculative physical address
+            {
+                r_dcache_hit_p_save = dcache_hit_p;
+                r_dcache_fsm = DCACHE_BIS;
+                m_cost_data_miss_frz++;
+            }
+            else  // cached or uncached access with a correct speculative physical address
+            {
+                switch( dreq.type ) {
+                    case iss_t::DATA_READ:
+                    case iss_t::DATA_LL:
+                    case iss_t::DATA_SC:
+                        m_cpt_read++;
+                        if ( dcache_hit_c ) 
+                        {
+                            r_dcache_buf_unc_valid = false;
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+                        } 
+                        else 
+                        {
+                            if ( dcache_cached ) 
+                            {
+                                r_dcache_miss_req = true;
+                                r_dcache_fsm = DCACHE_MISS_WAIT;
+                                m_cpt_data_miss++;
+                                m_cost_data_miss_frz++;
+                            } 
+                            else 
+                            {
+                                r_dcache_unc_req = true;
+                                r_dcache_fsm = DCACHE_UNC_WAIT;
+                                m_cpt_unc_read++;
+                                m_cost_unc_read_frz++;
+                            }
+                        }
+                        break;
+/*
+                    case iss_t::DATA_READ:
+                        m_cpt_read++;
+                        if ( dcache_hit_c ) 
+                        {
+                            r_dcache_buf_unc_valid = false;
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+                        } 
+                        else 
+                        {
+                            if ( dcache_cached ) 
+                            {
+                                r_dcache_miss_req = true;
+                                r_dcache_fsm = DCACHE_MISS_WAIT;
+                                m_cpt_data_miss++;
+                                m_cost_data_miss_frz++;
+                            } 
+                            else 
+                            {
+                                r_dcache_unc_req = true;
+                                r_dcache_fsm = DCACHE_UNC_WAIT;
+                                m_cpt_unc_read++;
+                                m_cost_unc_read_frz++;
+                            }
+                        }
+                        break;
+                    case iss_t::DATA_LL:
+			if (r_dcache_llsc_reserved && (r_dcache_llsc_addr_save == tlb_dpaddr) && r_dcache_buf_unc_valid)
+			{
+                            r_dcache_buf_unc_valid = false;
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+			}
+			else
+			{
+			    r_dcache_llsc_reserved = true;
+			    r_dcache_llsc_addr_save = tlb_dpaddr;
+                            r_dcache_unc_req = true;
+                            r_dcache_fsm = DCACHE_UNC_WAIT;
+			}
+			break;
+                    case iss_t::DATA_SC:
+			if (r_dcache_llsc_reserved && (r_dcache_llsc_addr_save == tlb_dpaddr))
+			{
+			    r_dcache_llsc_reserved = false;
+                            r_dcache_unc_req = true;
+                            r_dcache_fsm = DCACHE_UNC_WAIT;
+			}
+			else
+			{   
+			    if ( r_dcache_buf_unc_valid )
+			    {                         
+			        r_dcache_llsc_reserved = false;
+			        r_dcache_buf_unc_valid = false;
+                                drsp.valid = true;
+                                drsp.rdata = dcache_rdata;
+			    }
+                            r_dcache_fsm = DCACHE_IDLE;
+			}			
+			break;
+*/
+                    case iss_t::DATA_WRITE:
+                        m_cpt_write++;
+                        if ( dcache_cached ) m_cpt_write_cached++;
+
+                        if ( dcache_hit_c && dcache_cached )    // cache update required
+                        {
+                            r_dcache_fsm = DCACHE_WRITE_UPDT;
+                        } 
+                        else if ( !dcache_pte_info.d && (r_mmu_mode.read() & DATA_TLB_MASK) )   // dirty bit update required
+                        {
+                            if ( dcache_tlb.getpagesize(dcache_tlb_way, dcache_tlb_set) )	// 2M page size, one level page table 
+                            {
+                                r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
+                                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                                r_dcache_tlb_ll_dirty_req = true;
+                                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                                m_cpt_data_tlb_write_dirty++;
+                            }
+                            else	// 4k page size, two levels page table 
+                            {   
+                                if (dcache_hit_p) 
+                                {
+                                    r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
+                                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save | (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                                    r_dcache_tlb_ll_dirty_req = true;
+                                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                                    m_cpt_data_tlb_write_dirty++;
+                                }
+                                else    // get PTBA to calculate the physical address of PTE
+                                {
+                                    r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
+                                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                                    r_dcache_tlb_ptba_read = true;
+                                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                                }
+                            }
+                            m_cost_data_tlb_miss_frz++;
+                        }
+                        else                                    // no cache update, not dirty bit update
+                        {
+                            r_dcache_fsm = DCACHE_WRITE_REQ;
+                            drsp.valid = true;
+                            drsp.rdata = 0;
+                        }
+                        break;
+                    default:
+                        break;
+                } // end switch dreq.type
+            } // end if next states
+
+            // save values for the next states
+            r_dcache_paddr_save   = tlb_dpaddr;
+            r_dcache_type_save    = dreq.type;
+            r_dcache_wdata_save   = dreq.wdata;
+            r_dcache_be_save      = dreq.be;
+            r_dcache_rdata_save   = dcache_rdata;
+            r_dcache_cached_save  = dcache_cached;
+            r_dcache_dirty_save   = dcache_pte_info.d;
+            r_dcache_tlb_set_save = dcache_tlb_set;
+            r_dcache_tlb_way_save = dcache_tlb_way;
+
+        } // end if dreq.valid
+        else 
+        {   
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+
+        // processor request are not accepted in the WRITE_REQ state 
+        // when the write buffer is not writeable
+
+        if ((r_dcache_fsm == DCACHE_WRITE_REQ) && 
+            (r_dcache_write_req || !r_wbuf.wok(r_dcache_paddr_save))) 
+        {
+            drsp.valid = false;
+        }
+        break;
+    }
+    /////////////////
+    case DCACHE_BIS:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        data_t  dcache_rdata = 0;
+        bool    dcache_hit_c = false;
+        bool    dcache_hit_t = false;
+        paddr_t tlb_dpaddr   = 0;
+
+	dcache_hit_t = dcache_tlb.translate(dreq.addr, &tlb_dpaddr);
+
+	if ( (tlb_dpaddr == r_dcache_paddr_save.read()) && dreq.valid && dcache_hit_t ) 
+	{
+	    // acces always cached in this state
+	    dcache_hit_c = r_dcache.read(r_dcache_paddr_save, &dcache_rdata);
+	    
+	    if ( dreq.type == iss_t::DATA_READ )  // cached read
+	    {
+	        m_cpt_read++;
+	        if ( !dcache_hit_c ) 
+	        {
+	            r_dcache_miss_req = true;
+	            r_dcache_fsm = DCACHE_MISS_WAIT;
+	            m_cpt_data_miss++;
+	            m_cost_data_miss_frz++;
+	        }
+	        else
+	        {
+	            r_dcache_fsm = DCACHE_IDLE;
+	        }
+	        drsp.valid = dcache_hit_c;
+	        drsp.error = false;
+	        drsp.rdata = dcache_rdata;
+	    }
+	    else    // cached write
+	    {
+	        m_cpt_write++;
+	        m_cpt_write_cached++;
+	        if ( dcache_hit_c )    // cache update required
+	        {
+	            r_dcache_rdata_save = dcache_rdata;
+	            r_dcache_fsm = DCACHE_WRITE_UPDT;
+	        } 
+	        else if (!r_dcache_dirty_save && (r_mmu_mode.read() & DATA_TLB_MASK))   // dirty bit update required
+	        {
+	            if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save)) 
+	            {
+	                r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+	                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+	                r_dcache_tlb_ll_dirty_req = true;
+	                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+	                m_cpt_data_tlb_write_dirty++;
+	            }
+	            else
+	            {   
+	                if (r_dcache_hit_p_save) 
+	                {
+	                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+	                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+	                    r_dcache_tlb_ll_dirty_req = true;
+	                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+	                    m_cpt_data_tlb_write_dirty++;
+	                }
+	                else
+	                {
+	                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+	                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+	                    r_dcache_tlb_ptba_read = true;
+	                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+	                }
+	            }
+	            m_cost_data_tlb_miss_frz++;
+	        }
+	        else                                    // no cache update, not dirty bit update
+	        {
+	            r_dcache_fsm = DCACHE_WRITE_REQ;
+	            drsp.valid = true;
+	            drsp.rdata = 0;
+	        }
+	    }
+	}
+	else
+	{
+            drsp.valid = false;
+            drsp.error = false;
+            drsp.rdata = 0;
+            r_dcache_fsm = DCACHE_IDLE;
+	}
+        break;
+    }
+    //////////////////////////
+    case DCACHE_LL_DIRTY_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_tlb_ll_dirty_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+		if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save)) 
+		{
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;     
+		}
+		else
+		{
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;     
+		}
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+            }
+	    else
+	    {
+		if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+		    if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
+		    { 
+			r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;       
+		    }
+		    else
+		    {
+			r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;       
+	  	    }
+                    r_dcache_bad_vaddr = dreq.addr;
+                    r_dcache_fsm = DCACHE_ERROR;
+
+		    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+	        }
+        	else if ( r_dcache_inval_tlb_rsp )
+        	{
+        	    r_dcache_inval_tlb_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	    m_cost_data_tlb_miss_frz++;
+        	}
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+		else
+		{
+		    r_dcache_tlb_sc_dirty_req = true;
+		    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
+                    r_dcache_fsm = DCACHE_SC_DIRTY_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    //////////////////////////
+    case DCACHE_SC_DIRTY_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_tlb_sc_dirty_req )
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+	        if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
+	        {
+	            r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;    
+	        }
+	        else
+	        {
+	            r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;    
+	        }
+	        r_dcache_bad_vaddr = dreq.addr;
+	        r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;		 	    }
+	    else 
+	    {
+                // Using tlb entry is invalidated 
+                if ( r_dcache_inval_tlb_rsp )
+                {
+                    r_dcache_inval_tlb_rsp = false;
+                    r_dcache_fsm = DCACHE_IDLE;
+                    m_cost_data_tlb_miss_frz++;
+                }
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+		else if ( r_dcache_tlb_ll_dirty_req )
+	        {
+	            r_dcache_fsm = DCACHE_LL_DIRTY_WAIT; 
+	        }
+		else
+		{
+	            r_dcache_fsm = DCACHE_WRITE_DIRTY; 
+		}
+	    }
+	}
+	break;
+    }
+    ////////////////////////////
+    case DCACHE_DTLB1_READ_CACHE:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        data_t tlb_data = 0;
+	bool write_hit = false;
+        bool tlb_hit_cache = r_dcache.read(r_dcache_tlb_paddr, &tlb_data);
+
+        // DTLB request hit in cache
+        if ( tlb_hit_cache )
+        {
+	    if ( !(tlb_data >> PTE_V_SHIFT) )	// unmapped
+	    {
+                r_dcache_ptba_ok    = false;
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
+                }  
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (tlb_data & PTE_T_MASK) >> PTE_T_SHIFT )	// PTD
+	    {
+                r_dcache_ptba_ok   = true;
+                r_dcache_ptba_save = (paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS;  
+                r_dcache_id1_save  = dreq.addr >> PAGE_M_NBITS;
+                r_dcache_tlb_paddr = (paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                     (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
+                if ( r_dcache_tlb_ptba_read )
+                {
+                    r_dcache_tlb_ptba_read = false;
+                    write_hit = r_dcache.write(((paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                                (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3)), r_dcache_pte_update);
+                    //assert(write_hit && "Write on miss ignores data");
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {
+                    r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
+                }
+	    }
+	    else	// PTE
+	    {
+                r_dcache_ptba_ok = false;
+	        if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (tlb_data & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+                        r_dcache_fsm = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_L_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (tlb_data & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+                        r_dcache_fsm = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_R_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        else
+        {
+            // DTLB request miss in cache and walk page table level 1
+            r_dcache_tlb_read_req = true;
+            r_dcache_fsm = DCACHE_TLB1_READ;
+        }
+        break;
+    }
+    ///////////////////////
+    case DCACHE_TLB1_LL_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_tlb_ll_acc_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;		 
+            }
+	    else
+	    {
+		if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+               	    if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+               	    {
+               	        r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
+               	    }
+               	    else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+               	    {
+               	        r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
+               	    }  
+                    r_dcache_bad_vaddr  = dreq.addr;
+                    r_dcache_fsm        = DCACHE_ERROR;
+
+		    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	        }
+       		else if ( r_dcache_inval_tlb_rsp )
+       		{
+       		    r_dcache_inval_tlb_rsp = false;
+       		    r_dcache_fsm = DCACHE_IDLE;
+       		    m_cost_data_tlb_miss_frz++;
+       		}
+		else if ( r_dcache_inval_rsp )
+       		{
+       		    r_dcache_inval_rsp = false;
+       		    r_dcache_fsm = DCACHE_IDLE;
+       		}
+		else
+		{
+		    r_dcache_tlb_sc_acc_req = true;
+		    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
+                    r_dcache_fsm = DCACHE_TLB1_SC_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    ///////////////////////
+    case DCACHE_TLB1_SC_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_tlb_sc_acc_req )
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
+                } 
+	        r_dcache_bad_vaddr = dreq.addr;
+	        r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	    }
+	    else
+	    {
+        	// Using tlb entry is invalidated 
+        	if ( r_dcache_inval_tlb_rsp )
+        	{
+        	    r_dcache_inval_tlb_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	    m_cost_data_tlb_miss_frz++;
+        	}
+		else if ( r_dcache_inval_rsp )
+        	{
+        	    r_dcache_inval_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	}
+	    	else if ( r_dcache_tlb_ll_acc_req )
+	    	{
+	    	    r_dcache_fsm = DCACHE_TLB1_LL_WAIT; 
+	    	}
+	    	else 
+	    	{
+	    	    r_dcache_fsm = DCACHE_TLB1_UPDT; 
+	    	}
+	    }
+	}
+	break;
+    }
+    //////////////////////
+    case DCACHE_TLB1_READ:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+	if ( !r_dcache_tlb_read_req )
+	{	
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+		break;
+            }
+
+            if ( r_dcache_inval_tlb_rsp )  // TLB miss response and invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE; 
+            	r_dcache_inval_tlb_rsp = false;
+		break;
+            }
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+	        if ( r_dcache_cleanup_req ) break;
+                r_dcache_cleanup_req = true;
+                r_dcache_cleanup_line = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words) + 2);  
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_rsp = false;
+                break;
+	    }
+
+	    // TLB miss response and no invalidation
+	    r_dcache_fsm = DCACHE_TLB1_READ_UPDT;
+	}
+        break;
+    }
+    //////////////////////////
+    case DCACHE_TLB1_READ_UPDT:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if ( !r_dcache_cleanup_req ) // Miss update and no invalidation
+        {
+            // update dcache
+            data_t   rsp_dtlb_miss = 0;
+            paddr_t  victim_index = 0;
+	    bool write_hit = false;
+            size_t way = 0;
+            size_t set = 0;
+
+            // Using tlb entry is in the invalidated cache line  
+            if ( r_dcache_inval_rsp )
+            {
+                r_dcache_cleanup_req = true;
+                r_dcache_cleanup_line = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words) + 2);  
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_rsp = false;
+                break;
+            }
+
+            bool cleanup_req = r_dcache.find(r_dcache_tlb_paddr, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+            
+	    if ( cleanup_req )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+	    r_dcache.update(r_dcache_tlb_paddr, way, set, r_dcache_miss_buf);
+            r_dcache.read(r_dcache_tlb_paddr, &rsp_dtlb_miss);	
+
+	    if ( !(rsp_dtlb_miss >> PTE_V_SHIFT) )	// unmapped
+	    {
+                r_dcache_ptba_ok    = false;
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
+                } 
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (rsp_dtlb_miss & PTE_T_MASK) >> PTE_T_SHIFT ) // PTD
+	    {
+                r_dcache_ptba_ok   = true;
+                r_dcache_ptba_save = (paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS;  
+                r_dcache_id1_save  = dreq.addr >> PAGE_M_NBITS;
+                r_dcache_tlb_paddr = (paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                     (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
+                if ( r_dcache_tlb_ptba_read )
+                {
+                    r_dcache_tlb_ptba_read = false;
+                    write_hit = r_dcache.write(((paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS | 
+                                                (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3)),r_dcache_pte_update);
+                    //assert(write_hit && "Write on miss ignores data");
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {
+                    r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
+                }
+	    }
+	    else	// PTE
+	    {
+                r_dcache_ptba_ok = false;
+	        if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (rsp_dtlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+                        r_dcache_fsm        = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_L_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm        = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (rsp_dtlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+                        r_dcache_fsm        = DCACHE_TLB1_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_R_MASK;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm        = DCACHE_TLB1_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        break;
+    }
+    //////////////////////
+    case DCACHE_TLB1_UPDT: 
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        if ( !r_dcache_inval_tlb_rsp && !r_dcache_inval_rsp )
+        {
+            paddr_t victim_index = 0;
+            if (dcache_tlb.update(r_dcache_pte_update,dreq.addr,(r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index))
+            {
+                r_dcache.setinbit((paddr_t)victim_index*m_dcache_words*2, r_dcache_in_dtlb, false);
+            }
+            r_dcache.setinbit(r_dcache_tlb_paddr, r_dcache_in_dtlb, true);
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        else  
+        {
+            if ( r_dcache_inval_tlb_rsp ) r_dcache_inval_tlb_rsp = false;
+            if ( r_dcache_inval_rsp ) r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        break;
+    }
+    /////////////////////////////
+    case DCACHE_DTLB2_READ_CACHE:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        data_t tlb_data = 0;
+        data_t tlb_data_ppn = 0;
+	bool write_hit = false;
+        bool tlb_hit_cache = r_dcache.read(r_dcache_tlb_paddr, &tlb_data);
+
+	if ( tlb_hit_cache )
+	{
+            bool tlb_hit_ppn = r_dcache.read(r_dcache_tlb_paddr.read()+4, &tlb_data_ppn);
+	    assert(tlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+	}
+
+        // DTLB request hit in cache
+        if ( tlb_hit_cache )
+        {
+	    if ( !(tlb_data >> PTE_V_SHIFT) )	// unmapped
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
+                } 
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (tlb_data & PTE_T_MASK) >> PTE_T_SHIFT ) //PTD
+	    {
+                r_dcache_pte_update = tlb_data;
+	        r_dcache_ppn_update = tlb_data_ppn;
+		r_dcache_fsm = DCACHE_TLB2_UPDT;
+	    }
+	    else 
+	    {
+	        if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (tlb_data & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_L_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (tlb_data & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = tlb_data;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = tlb_data | PTE_R_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        else
+        {
+            // DTLB request miss in cache and walk page table level 2
+            r_dcache_tlb_read_req = true;
+            r_dcache_fsm = DCACHE_TLB2_READ;
+        }
+        break;
+    }
+    ///////////////////////
+    case DCACHE_TLB2_LL_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_tlb_ll_acc_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+            }
+	    else
+	    {
+	        if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+               	    if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+               	    {
+               	        r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
+               	    }
+               	    else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+               	    {
+               	        r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
+               	    } 
+                    r_dcache_bad_vaddr = dreq.addr;
+                    r_dcache_fsm = DCACHE_ERROR;
+
+		    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+	        }
+        	else if ( r_dcache_inval_tlb_rsp )
+        	{
+        	    r_dcache_inval_tlb_rsp = false;
+        	    r_dcache_fsm = DCACHE_IDLE;
+        	    m_cost_data_tlb_miss_frz++;
+        	}
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+		else
+		{
+		    r_dcache_tlb_sc_acc_req = true;
+		    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
+                    r_dcache_fsm = DCACHE_TLB2_SC_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    ///////////////////////
+    case DCACHE_TLB2_SC_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_tlb_sc_acc_req )
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
+                } 
+	        r_dcache_bad_vaddr = dreq.addr;
+	        r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	    }
+	    else
+	    { 
+                // Using tlb entry is invalidated 
+                if ( r_dcache_inval_tlb_rsp )
+                {
+                    r_dcache_inval_tlb_rsp = false;
+                    r_dcache_fsm = DCACHE_IDLE;
+                    m_cost_data_tlb_miss_frz++;
+                }
+		else if ( r_dcache_inval_rsp )
+		{
+        	    r_dcache_inval_rsp = false;
+		    r_dcache_fsm = DCACHE_IDLE;
+		}
+	        else if ( r_dcache_tlb_ll_acc_req )
+	        {
+	            r_dcache_fsm = DCACHE_TLB2_LL_WAIT; 
+	        }
+	        else 
+	        {
+	            r_dcache_fsm = DCACHE_TLB2_UPDT; 
+	        }
+	    }
+	}
+	break;
+    }
+    /////////////////////
+    case DCACHE_TLB2_READ:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+	if ( !r_dcache_tlb_read_req )
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
+                } 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR; 
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            }	
+
+            if ( r_dcache_inval_tlb_rsp )  // TLB miss response and invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE; 
+                r_dcache_inval_tlb_rsp = false;
+		break;
+            }  
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+	        if ( r_dcache_cleanup_req ) break;
+                r_dcache_cleanup_req = true;
+                r_dcache_cleanup_line = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words) + 2);  
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_rsp = false;
+                break;
+	    } 
+
+	    // TLB miss response and no invalidation
+	    r_dcache_fsm = DCACHE_TLB2_READ_UPDT;
+	}	
+        break;
+    }
+    //////////////////////////
+    case DCACHE_TLB2_READ_UPDT:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        // Using tlb entry is invalidated 
+        if ( r_dcache_inval_tlb_rsp )
+        {
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if ( !r_dcache_cleanup_req )
+        {
+            // update cache
+            data_t rsp_dtlb_miss;
+            data_t tlb_data_ppn;
+	    bool write_hit = false;
+            paddr_t  victim_index = 0;
+            size_t way = 0;
+            size_t set = 0;
+
+            // Using tlb entry is in the invalidated cache line  
+            if ( r_dcache_inval_rsp )
+            {
+                r_dcache_cleanup_req = true;
+                r_dcache_cleanup_line = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words) + 2);  
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_rsp = false;
+                break;
+            }
+
+            bool cleanup_req = r_dcache.find(r_dcache_tlb_paddr, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+
+	    if ( cleanup_req )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                r_dcache_fsm_save = r_dcache_fsm;
+		break;
+	    }
+
+	    r_dcache.update(r_dcache_tlb_paddr, way, set, r_dcache_miss_buf);
+	    r_dcache.read(r_dcache_tlb_paddr, &rsp_dtlb_miss);
+
+	    bool tlb_hit_ppn = r_dcache.read(r_dcache_tlb_paddr.read()+4, &tlb_data_ppn);
+	    assert(tlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+
+	    if ( !(rsp_dtlb_miss >> PTE_V_SHIFT) )	// unmapped
+	    {
+                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
+                {
+                    r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
+                }
+                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
+                {
+                    r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
+                }  
+                r_dcache_bad_vaddr  = dreq.addr;
+                r_dcache_fsm        = DCACHE_ERROR;
+	    }
+	    else if ( (rsp_dtlb_miss & PTE_T_MASK) >> PTE_T_SHIFT ) // PTD
+	    {
+                r_dcache_pte_update = rsp_dtlb_miss;
+	        r_dcache_ppn_update = tlb_data_ppn;
+		r_dcache_fsm = DCACHE_TLB2_UPDT;
+	    }
+	    else
+	    {
+	        if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
+		{
+		    if ( (rsp_dtlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_L_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_L_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+    	        }
+		else // remotely
+		{
+		    if ( (rsp_dtlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss;
+			r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
+		    }
+		    else
+		    {
+                        r_dcache_pte_update = rsp_dtlb_miss | PTE_R_MASK;
+	        	r_dcache_ppn_update = tlb_data_ppn;
+                        r_dcache_tlb_ll_acc_req = true;
+                	write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_R_MASK));  
+                	assert(write_hit && "Write on miss ignores data");  
+                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
+                        m_cpt_ins_tlb_write_et++;
+		    }
+		}
+	    }
+        }
+        break;
+    }
+    //////////////////////
+    case DCACHE_TLB2_UPDT:  
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }        
+
+        if ( !r_dcache_inval_tlb_rsp && !r_dcache_inval_rsp )
+        {
+            paddr_t victim_index = 0;
+            if (dcache_tlb.update(r_dcache_pte_update,r_dcache_ppn_update,dreq.addr,(r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index))
+            {
+                r_dcache.setinbit((paddr_t)victim_index*m_dcache_words*2, r_dcache_in_dtlb, false);
+            }
+            r_dcache.setinbit(r_dcache_tlb_paddr, r_dcache_in_dtlb, true);
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        else  
+        {
+            if ( r_dcache_inval_tlb_rsp ) r_dcache_inval_tlb_rsp = false;
+            if ( r_dcache_inval_rsp ) r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        break;
+    }
+    ///////////////////////
+    case DCACHE_CTXT_SWITCH:
+    {
+        // TLB flush leads to cleanup corresponding data cache line 
+        m_cost_data_tlb_sw_frz++;
+
+        paddr_t victim_index = 0;
+        size_t way = 0;
+        size_t set = 0;
+
+        if ( r_dcache_itlb_cleanup_req )
+        {    
+            r_dcache.setinbit(((paddr_t)r_dcache_itlb_cleanup_line.read()*m_dcache_words*2), r_dcache_in_itlb, false);
+            r_dcache_itlb_cleanup_req = false;
+	}
+
+        for ( way = 0; way < m_dtlb_ways; way++)
+        {
+            for ( set = 0; set < m_dtlb_sets; set++)
+            {
+                if(dcache_tlb.checkcleanup(way, set, &victim_index))
+                {
+                    r_dcache.setinbit((paddr_t)(victim_index << (m_dcache_words+2)), r_dcache_in_dtlb, false); 
+                }
+            }
+        }
+
+        if ( !r_dcache_xtn_req )
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            r_dtlb_translation_valid = false;
+            r_dcache_ptba_ok = false;
+            drsp.valid = true;
+        }
+        break;
+    }
+    ////////////////////////
+    case DCACHE_ICACHE_FLUSH:
+    case DCACHE_ICACHE_INVAL:
+    case DCACHE_ICACHE_INVAL_PA:
+    case DCACHE_ITLB_INVAL:
+    {
+        if ( !r_dcache_xtn_req ) 
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            drsp.valid = true;
+        }
+        break;
+    }
+    ////////////////////////
+    case DCACHE_DCACHE_FLUSH:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )
+        {
+            r_tgt_dcache_req = false;
+        }   
+
+        size_t way = r_dcache_way;
+        size_t set = r_dcache_set;
+        bool clean = false;
+        
+        m_cost_data_cache_flush_frz++;
+
+        // cache flush and send cleanup to external
+        if ( !r_dcache_cleanup_req )
+        {
+            paddr_t victim_index = 0;
+            for ( ; way < m_dcache_ways; way++ )
+            {    
+                for ( ; set < m_dcache_sets; set++ )
+                {  
+                    if ( r_dcache.flush(way, set, &victim_index) )
+                    {
+                        clean = true;
+                        r_dcache_cleanup_req = true;
+                        r_dcache_cleanup_line = victim_index;
+                        r_dcache_way = way + ((set+1)/m_dcache_sets);
+                        r_dcache_set = (set+1) % m_dcache_sets;
+                        break;
+                    }
+                }
+                if (clean) break;
+            }
+
+            if ((way == m_dcache_ways) && !r_dcache_xtn_req ) 
+            {
+                // data TLB flush 
+                dcache_tlb.flush(true);      // global entries are not invalidated
+            	r_dtlb_translation_valid = false;
+            	r_dcache_ptba_ok = false;
+
+                for (size_t line = 0; line < m_dcache_ways*m_dcache_sets; line++)
+                {
+                    r_dcache_in_itlb[line] = false;
+                    r_dcache_in_dtlb[line] = false;
+                }
+
+                r_dcache_fsm = DCACHE_IDLE;
+                drsp.valid = true;
+                break;
+            }
+        }
+	break;
+    }
+    //////////////////////
+    case DCACHE_DTLB_INVAL: 
+    {
+        paddr_t victim_index = 0;
+        // clean indicate data tlb bit
+        if ( dcache_tlb.inval(r_dcache_wdata_save, &victim_index) )
+        {  
+            r_dcache.setinbit((paddr_t)(victim_index << (m_dcache_words+2)), r_dcache_in_dtlb, false); 
+        }
+        r_dtlb_translation_valid = false;
+        r_dcache_ptba_ok = false;
+        r_dcache_fsm = DCACHE_IDLE;
+        drsp.valid = true;
+        break;
+    }
+    ////////////////////////
+    case DCACHE_DCACHE_INVAL:
+    {
+        m_cpt_dcache_dir_read += m_dcache_ways;
+        vaddr_t invadr = dreq.wdata;
+        paddr_t dpaddr = 0;
+        bool dcache_hit_t = false; 
+        size_t way = 0;
+        size_t set = 0;
+
+	if ( !r_dcache_cleanup_req )
+	{
+            if ( r_mmu_mode.read() & DATA_TLB_MASK ) 
+            {
+                dcache_hit_t = dcache_tlb.translate(invadr, &dpaddr); 
+            } 
+            else 
+            {
+                dpaddr = invadr;  
+                dcache_hit_t = true;
+            }
+
+            if ( dcache_hit_t )
+            {
+		r_dcache_cleanup_req = r_dcache.inval(dpaddr, &way, &set);
+		r_dcache_cleanup_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+		
+		if ( r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[way*m_dcache_sets+set] ) 
+		{	
+		    // ins tlb invalidate verification
+		    r_dcache_itlb_inval_req = r_dcache_in_itlb[way*m_dcache_sets+set];
+		    r_dcache_itlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+		    r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+		
+		    // data tlb invalidate verification
+		    r_dcache_dtlb_inval_req = r_dcache_in_dtlb[way*m_dcache_sets+set];
+		    r_dcache_dtlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+		    r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+		    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+		    r_dcache_fsm_save = r_dcache_fsm;
+		    break;
+		}
+            }
+            r_dcache_fsm = DCACHE_IDLE;
+            drsp.valid = true;
+	}
+        break;
+    }
+    ////////////////////////
+    case DCACHE_DCACHE_INVAL_PA:
+    {
+        m_cpt_dcache_dir_read += m_dcache_ways;
+        paddr_t dpaddr = (paddr_t)r_mmu_word_hi.read() << 32 | r_mmu_word_lo.read();
+        size_t way = 0;
+        size_t set = 0;
+
+	if ( !r_dcache_cleanup_req )
+	{
+	    r_dcache_cleanup_req = r_dcache.inval(dpaddr, &way, &set);
+	    r_dcache_cleanup_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+	    
+	    if ( r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[way*m_dcache_sets+set] ) 
+	    {	
+	        // ins tlb invalidate verification
+	        r_dcache_itlb_inval_req = r_dcache_in_itlb[way*m_dcache_sets+set];
+	        r_dcache_itlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+	        r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+	    
+	        // data tlb invalidate verification
+	        r_dcache_dtlb_inval_req = r_dcache_in_dtlb[way*m_dcache_sets+set];
+	        r_dcache_dtlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
+	        r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+	        r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+	        r_dcache_fsm_save = r_dcache_fsm;
+	        break;
+	    }
+            r_dcache_fsm = DCACHE_IDLE;
+            drsp.valid = true;
+	}
+        break;
+    }
+    /////////////////////////
+    case DCACHE_DCACHE_SYNC:
+    {
+        if ( !r_dcache_write_req ) 
+        {
+            r_dcache_write_req = r_wbuf.rok();
+            drsp.valid = true;
+            r_dcache_fsm = DCACHE_IDLE;
+        }    
+        break;
+    }
+    /////////////////////
+    case DCACHE_MISS_WAIT:
+    {
+        m_cost_data_miss_frz++; 
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_miss_req )
+	{
+            if ( r_vci_rsp_data_error ) 
+            {
+                r_dcache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            } 
+
+            if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                if ( r_dcache_cleanup_req ) break;
+                r_dcache_cleanup_req = true;
+                r_dcache_cleanup_line = r_dcache_paddr_save.read() >> (uint32_log2(m_dcache_words) + 2);  
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_tlb_rsp = false;
+                if ( r_dcache_inval_rsp ) r_dcache_inval_rsp = false;
+                break;
+            }	
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                if ( r_dcache_cleanup_req ) break;
+                r_dcache_cleanup_req = true;
+                r_dcache_cleanup_line = r_dcache_paddr_save.read() >> (uint32_log2(m_dcache_words) + 2);  
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_rsp = false;
+                break;
+	    }
+	    // Miss read response and no tlb invalidation
+	    r_dcache_fsm = DCACHE_MISS_UPDT;
+	}	
+        break;
+    }
+    /////////////////////
+    case DCACHE_MISS_UPDT:
+    {
+        m_cost_data_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        if ( r_dcache_inval_tlb_rsp ) // tlb invalidation
+        {
+            if ( r_dcache_cleanup_req ) break;
+            r_dcache_cleanup_req = true;
+            r_dcache_cleanup_line = r_dcache_paddr_save.read() >> (uint32_log2(m_dcache_words) + 2);  
+            r_dcache_inval_tlb_rsp = false;
+            r_dcache_inval_rsp = false;
+            r_dcache_fsm = DCACHE_IDLE;
+            m_cost_data_tlb_miss_frz++;
+            break;
+        }
+
+        if (!r_dcache_cleanup_req ) // Miss update and no invalidation
+        {
+            paddr_t  victim_index = 0;
+            size_t way = 0;
+            size_t set = 0;
+
+	    m_cpt_dcache_data_write++;
+            m_cpt_dcache_dir_write++;
+
+            // Using tlb entry is in the invalidated cache line  
+            if ( r_dcache_inval_rsp )
+            {
+                r_dcache_cleanup_req = true;
+                r_dcache_cleanup_line = r_dcache_paddr_save.read() >> (uint32_log2(m_dcache_words) + 2);  
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_rsp = false;
+                break;
+            }
+
+            bool cleanup_req = r_dcache.find(r_dcache_paddr_save.read(), r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+
+	    if ( cleanup_req )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		if ( r_dcache_in_itlb[m_dcache_sets*way+set] || r_dcache_in_dtlb[m_dcache_sets*way+set] )
+		{
+		    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                    r_dcache_fsm_save = r_dcache_fsm;
+		    break;
+		}
+	    }
+
+	    r_dcache.update(r_dcache_paddr_save.read(), way, set, r_dcache_miss_buf);
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+	break;
+    }
+    //////////////////////
+    case DCACHE_UNC_WAIT:
+    {
+        m_cost_unc_read_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if ( !r_dcache_unc_req )
+	{
+            if ( r_vci_rsp_data_error ) 
+            {
+                r_dcache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; 
+                r_dcache_bad_vaddr = dreq.addr;
+                r_dcache_fsm = DCACHE_ERROR;
+
+		if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
+		break;
+            }
+
+            if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+            {
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_tlb_rsp = false;
+		break;
+            }
+
+            if(dreq.type == iss_t::DATA_SC) 
+	    {
+		size_t way = 0;
+		size_t set = 0;
+                // Simulate an invalidate request
+		r_dcache_cleanup_req = r_dcache.inval(r_dcache_paddr_save, &way, &set);
+		r_dcache_cleanup_line = r_dcache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2);
+		
+		if ( r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[way*m_dcache_sets+set] ) 
+		{	
+		    // ins tlb invalidate verification
+		    r_dcache_itlb_inval_req = r_dcache_in_itlb[way*m_dcache_sets+set];
+		    r_dcache_itlb_inval_line = r_dcache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2);
+		    r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+		
+		    // data tlb invalidate verification
+		    r_dcache_dtlb_inval_req = r_dcache_in_dtlb[way*m_dcache_sets+set];
+		    r_dcache_dtlb_inval_line = r_dcache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2);
+		    r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+		    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+		    r_dcache_fsm_save = r_dcache_fsm;
+		    break;
+		}
+
+            }		
+            r_dcache_buf_unc_valid = true;
+	    r_dcache_fsm = DCACHE_IDLE;
+	}	
+        break;
+    }
+    ///////////////////////
+    case DCACHE_WRITE_UPDT:
+    {
+        m_cost_write_frz++;
+        size_t way = 0;
+        size_t set = 0;
+	bool write_hit = false;
+        data_t mask = vci_param::be2mask(r_dcache_be_save.read());
+        data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
+        write_hit = r_dcache.write(r_dcache_paddr_save, wdata, &way, &set);
+        assert(write_hit && "Write on miss ignores data");
+        
+        if (r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[m_dcache_sets*way+set])
+        {
+	    // ins tlb invalidate verification    
+            r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+            r_dcache_itlb_inval_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
+            r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+            // data tlb invalidate verification
+            r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+            r_dcache_dtlb_inval_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
+            r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+	    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+            r_dcache_fsm_save = r_dcache_fsm;
+            break;
+	}
+
+        if ( !r_dcache_dirty_save && (r_mmu_mode.read() & DATA_TLB_MASK) )   
+        {
+            if ( dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save) )	// 2M page size, one level page table 
+            {
+                r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                r_dcache_tlb_ll_dirty_req = true;
+                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                m_cpt_data_tlb_write_dirty++;
+            }
+            else
+            {   
+                if (r_dcache_hit_p_save) 
+                {
+                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
+                    r_dcache_tlb_ll_dirty_req = true;
+                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
+                    m_cpt_data_tlb_write_dirty++;
+                }
+                else
+                {
+                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
+                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
+                    r_dcache_tlb_ptba_read = true;
+                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
+                }
+            }
+        }
+        else
+        {
+            r_dcache_fsm = DCACHE_WRITE_REQ;
+            drsp.valid = true;
+            drsp.rdata = 0;
+        }
+        break;
+    }
+    ////////////////////////
+    case DCACHE_WRITE_DIRTY:
+    {
+        m_cost_data_tlb_miss_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            r_dcache_inval_tlb_rsp = false;
+	    break;
+        }
+
+	if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	{
+            r_dcache_fsm = DCACHE_IDLE; 
+            r_dcache_inval_rsp = false;
+	    break;	    
+	}
+
+        r_dcache.write(r_dcache_tlb_paddr, r_dcache_pte_update);
+        dcache_tlb.setdirty(r_dcache_tlb_way_save, r_dcache_tlb_set_save);
+        r_dcache_fsm = DCACHE_WRITE_REQ;
+        drsp.valid = true;
+        drsp.rdata = 0;
+        break;
+    }
+    /////////////////
+    case DCACHE_ERROR:
+    {
+        r_vci_rsp_data_error = false;
+        drsp.valid = true;
+        drsp.error = true;
+        drsp.rdata = 0;
+        r_dcache_fsm = DCACHE_IDLE;
+        break;
+    }   
+    ////////////////////// 
+    case DCACHE_ITLB_READ:
+    {
+        m_cost_data_waste_wait_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+    	if ( !r_dcache_itlb_read_req ) // vci response ok
+        {  
+            if ( r_vci_rsp_data_error )
+            {
+                r_dcache_rsp_itlb_error = true;	
+                r_itlb_read_dcache_req = false;
+                r_vci_rsp_data_error = false;
+                r_dcache_fsm = DCACHE_IDLE;
+
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
+		break;
+            }
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+	        if ( r_dcache_cleanup_req ) break;
+                r_dcache_cleanup_req = true;
+                r_dcache_cleanup_line = r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words) + 2);  
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_rsp = false;
+                break;
+	    }
+
+            r_dcache_fsm = DCACHE_ITLB_UPDT;
+        }
+	break;    	
+    }
+    //////////////////////
+    case DCACHE_ITLB_UPDT:
+    {
+        m_cost_data_waste_wait_frz++;
+
+        // external cache invalidate request
+        if ( r_tgt_dcache_req ) 
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+        if ( !r_dcache_cleanup_req )
+        {
+            data_t rsp_itlb_miss = 0;
+	    data_t rsp_itlb_ppn = 0;
+
+            paddr_t  victim_index = 0;
+            size_t way = 0;
+            size_t set = 0;
+
+	    if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
+	    {
+                r_dcache_cleanup_req = true;
+                r_dcache_cleanup_line = r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words) + 2);  
+                r_dcache_fsm = DCACHE_IDLE;
+                r_dcache_inval_rsp = false;
+                break;
+	    }           
+ 
+            bool cleanup = r_dcache.find(r_icache_paddr_save, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
+
+	    if ( cleanup )
+	    {	    
+		// ins tlb invalidate verification    
+                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                r_dcache_itlb_inval_line = victim_index;
+                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                // data tlb invalidate verification
+                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                r_dcache_dtlb_inval_line = victim_index;
+                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+
+                r_dcache_cleanup_req = true; 
+                r_dcache_cleanup_line = victim_index;
+		if ( r_dcache_in_itlb[m_dcache_sets*way+set] || r_dcache_in_dtlb[m_dcache_sets*way+set] )
+		{
+		    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+                    r_dcache_fsm_save = r_dcache_fsm;
+		    break;
+		}
+	    }
+
+            r_dcache.update(r_icache_paddr_save, way, set, r_dcache_miss_buf);
+
+            r_dcache.setinbit(r_icache_paddr_save, r_dcache_in_itlb, true);
+            bool itlb_hit_dcache = r_dcache.read(r_icache_paddr_save, &rsp_itlb_miss);	
+ 
+	    if ( r_itlb_k_read_dcache && itlb_hit_dcache )
+	    {	
+		r_itlb_k_read_dcache = false;
+            	bool itlb_hit_ppn = r_dcache.read(r_icache_paddr_save.read()+4, &rsp_itlb_ppn);
+		assert(itlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
+	    }
+
+            r_dcache_rsp_itlb_miss = rsp_itlb_miss;
+            r_dcache_rsp_itlb_ppn = rsp_itlb_ppn;
+            r_dcache_rsp_itlb_error = false;	
+            r_itlb_read_dcache_req = false;
+            r_dcache_fsm = DCACHE_IDLE;
+        }
+        break;
+    }
+    //////////////////////////
+    case DCACHE_ITLB_LL_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+
+	if (!r_dcache_itlb_ll_acc_req)
+	{
+            if ( r_vci_rsp_data_error ) // VCI response ko
+            {
+                r_dcache_rsp_itlb_error = true;  
+                r_vci_rsp_data_error = false;
+                r_itlb_acc_dcache_req = false;
+		r_dcache_fsm = DCACHE_IDLE;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+            }
+	    else
+	    {
+	        if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )	// unmapped
+	        {
+                    r_dcache_rsp_itlb_error = true;  
+                    r_itlb_acc_dcache_req = false;
+		    r_dcache_fsm = DCACHE_IDLE;	
+		    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;	
+	        }
+       		else if ( r_dcache_inval_rsp )
+       		{
+       		    r_dcache_inval_rsp = false;
+       		    r_dcache_fsm = DCACHE_IDLE;
+       		    m_cost_data_tlb_miss_frz++;
+       		}
+		else
+		{
+		    r_dcache_itlb_sc_acc_req = true;
+		    r_icache_pte_update = r_dcache_miss_buf[0] | r_icache_pte_update.read();	
+                    r_dcache_fsm = DCACHE_ITLB_SC_WAIT; 
+		}
+	    }
+	}
+	break;
+    }
+    //////////////////////////
+    case DCACHE_ITLB_SC_WAIT:
+    {
+        // external cache invalidate request
+        if ( r_tgt_dcache_req )   
+        {
+            r_dcache_fsm = DCACHE_CC_CHECK;
+            r_dcache_fsm_save = r_dcache_fsm;
+            m_cost_data_waste_wait_frz++;
+            break;
+        }
+	
+        if ( !r_dcache_itlb_sc_acc_req ) 
+	{
+	    if ( r_vci_rsp_data_error ) // VCI response ko
+	    {
+	        r_dcache_rsp_itlb_error = true;  
+	        r_vci_rsp_data_error = false;
+	        r_itlb_acc_dcache_req = false;
+	        r_dcache_fsm = DCACHE_IDLE;
+		if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;		
+	    }
+	    else
+	    {
+	        if ( r_dcache_inval_rsp )
+	        {
+	            r_dcache_inval_rsp = false;
+	            r_dcache_fsm = DCACHE_IDLE;
+	            m_cost_data_tlb_miss_frz++;
+	        }
+	        else if ( r_dcache_itlb_ll_acc_req )
+	        {
+	            r_dcache_fsm = DCACHE_ITLB_LL_WAIT; 
+	        }
+	        else 
+	        {
+	            r_itlb_acc_dcache_req = false;
+	            r_dcache_fsm = DCACHE_IDLE; 
+	        }
+	    }
+	}
+	break;
+    }
+    /////////////////////
+    case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        m_cpt_dcache_dir_read += m_dcache_ways;
+        m_cpt_dcache_data_read += m_dcache_ways;
+
+	// DCACHE_TLB1_LL_WAIT  DCACHE_TLB1_SC_WAIT  DCACHE_LL_DIRTY_WAIT  DCACHE_WRITE_DIRTY DCACHE_ITLB_LL_WAIT  DCACHE_ITLB_SC_WAIT
+	// DCACHE_TLB2_LL_WAIT  DCACHE_TLB2_SC_WAIT  DCACHE_SC_DIRTY_WAIT
+        if((( /*( r_dcache_fsm_save == DCACHE_UNC_WAIT ) ||*/
+	     ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) && 
+           ( (r_dcache_paddr_save.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1)))) 
+        || (( ( r_dcache_fsm_save == DCACHE_TLB1_READ )      || ( r_dcache_fsm_save == DCACHE_TLB2_READ )      ||
+	     ( r_dcache_fsm_save == DCACHE_TLB1_READ_UPDT ) || ( r_dcache_fsm_save == DCACHE_TLB2_READ_UPDT ) ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_UPDT )      || ( r_dcache_fsm_save == DCACHE_TLB2_UPDT )	 /* ||
+	     ( r_dcache_fsm_save == DCACHE_TLB1_LL_WAIT )   || ( r_dcache_fsm_save == DCACHE_TLB2_LL_WAIT )   ||
+	     ( r_dcache_fsm_save == DCACHE_TLB1_SC_WAIT )   || ( r_dcache_fsm_save == DCACHE_TLB2_SC_WAIT )   ||
+	     ( r_dcache_fsm_save == DCACHE_LL_DIRTY_WAIT )  || ( r_dcache_fsm_save == DCACHE_SC_DIRTY_WAIT )  ||
+	     ( r_dcache_fsm_save == DCACHE_WRITE_DIRTY )*/ ) && 
+           ( (r_dcache_tlb_paddr.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1))) ) 
+        || (( ( r_dcache_fsm_save == DCACHE_ITLB_READ ) || ( r_dcache_fsm_save == DCACHE_ITLB_UPDT ) /*||
+             ( r_dcache_fsm_save == DCACHE_ITLB_LL_WAIT ) || ( r_dcache_fsm_save == DCACHE_ITLB_SC_WAIT )*/ ) && 
+           ( (r_icache_paddr_save.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1))) ) ) 
+        {
+            r_dcache_inval_rsp = true;
+            r_tgt_dcache_req = false;
+            if ( r_tgt_update )
+	    {    // Also send a cleanup and answer
+                r_tgt_dcache_rsp = true;
+            } 
+	    else 
+	    {            // Also send a cleanup but don't answer
+                r_tgt_dcache_rsp = false;
+            }
+            r_dcache_fsm = r_dcache_fsm_save;
+        }
+	else
+	{
+            data_t dcache_rdata = 0;
+            size_t way = 0;
+            size_t set = 0;
+
+            bool dcache_hit = r_dcache.read(r_tgt_addr.read(), &dcache_rdata, &way, &set);
+
+            if ( dcache_hit )
+            {
+                if ( r_dcache_in_dtlb[m_dcache_sets*way+set] || r_dcache_in_itlb[m_dcache_sets*way+set] )
+                {
+            	    // ins tlb invalidate verification    
+                    r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
+                    r_dcache_itlb_inval_line = r_tgt_addr.read() >> (uint32_log2(m_dcache_words)+2);
+                    r_dcache_in_itlb[way*m_dcache_sets+set] = false;
+
+                    // data tlb invalidate verification
+                    r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 
+                    r_dcache_dtlb_inval_line = r_tgt_addr.read() >> (uint32_log2(m_dcache_words)+2);
+                    r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
+            	
+            	    r_dcache_cc_check = true;
+            	    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
+            	    break;
+                }
+
+                if ( r_tgt_update ) // update 
+                {
+                    r_dcache_fsm = DCACHE_CC_UPDT;
+                } 
+                else                // invalidate 
+                {
+                    r_dcache_fsm = DCACHE_CC_INVAL;
+                }
+            }
+            else                    // nothing
+            {
+                r_dcache_fsm = DCACHE_CC_NOP;
+            }
+	}
+        break;
+    }
+    ///////////////////
+    case DCACHE_CC_UPDT:    // update directory and data cache        
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        m_cpt_dcache_dir_write++;
+        m_cpt_dcache_data_write++;
+        data_t* buf = r_tgt_buf;
+        for( size_t i = 0; i < m_dcache_words; i++ )
+        {
+            if( r_tgt_val[i] ) r_dcache.write( r_tgt_addr.read() + i*4, buf[i] );
+        }
+           
+        r_tgt_dcache_req = false;
+	r_tgt_dcache_rsp = true;
+        r_dcache_fsm = r_dcache_fsm_save;
+        break;
+    }
+    /////////////////////
+    case DCACHE_CC_INVAL:   // invalidate a cache line
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        r_tgt_dcache_rsp = r_dcache.inval(r_tgt_addr.read());
+        r_tgt_dcache_req = false;
+        r_dcache_fsm = r_dcache_fsm_save;
+        break;
+    }
+    ///////////////////
+    case DCACHE_CC_NOP:     // no external hit
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        r_tgt_dcache_req = false;
+        if ( r_tgt_update )
+	{
+            r_tgt_dcache_rsp = true;
+        } 
+	else 
+	{
+            r_tgt_dcache_rsp = false;
+        }
+
+        r_dcache_fsm = r_dcache_fsm_save;
+        break;
+    }   
+    /////////////////////////
+    case DCACHE_TLB_CC_INVAL:
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+	if ( r_dcache_itlb_inval_req || r_dcache_dtlb_inval_req ) break;
+
+        if( (( r_dcache_fsm_save == DCACHE_TLB1_READ )        || ( r_dcache_fsm_save == DCACHE_TLB2_READ )        ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_READ_UPDT )   || ( r_dcache_fsm_save == DCACHE_TLB2_READ_UPDT )   ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_LL_WAIT )     || ( r_dcache_fsm_save == DCACHE_TLB2_LL_WAIT )     ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_SC_WAIT )     || ( r_dcache_fsm_save == DCACHE_TLB2_SC_WAIT )     ||
+             ( r_dcache_fsm_save == DCACHE_TLB1_UPDT )        || ( r_dcache_fsm_save == DCACHE_TLB2_UPDT )        ||
+             ( r_dcache_fsm_save == DCACHE_DTLB1_READ_CACHE ) || ( r_dcache_fsm_save == DCACHE_DTLB2_READ_CACHE ) ||
+             ( r_dcache_fsm_save == DCACHE_LL_DIRTY_WAIT )    || ( r_dcache_fsm_save == DCACHE_SC_DIRTY_WAIT )    ||
+	     ( r_dcache_fsm_save == DCACHE_WRITE_DIRTY )) && 
+            (((r_dcache_tlb_paddr.read() & ~((m_dcache_words<<2)-1)) >> (uint32_log2(m_dcache_words) + 2)) == r_dcache_dtlb_inval_line.read()) ) 
+        {
+            r_dcache_inval_tlb_rsp = true;
+        } 
+
+        if (((r_dcache_fsm_save == DCACHE_BIS)||(r_dcache_fsm_save == DCACHE_MISS_WAIT) ||
+             (r_dcache_fsm_save == DCACHE_UNC_WAIT)||(r_dcache_fsm_save == DCACHE_MISS_UPDT)) && 
+             (r_dcache_tlb_nline.read() == r_dcache_dtlb_inval_line.read()))
+        {
+            r_dcache_inval_tlb_rsp = true;
+        }
+
+	if ( !r_dcache_cc_check )
+	{
+            r_dcache_fsm = r_dcache_fsm_save;
+	}
+	else
+	{
+            r_dcache_fsm = DCACHE_CC_CHECK;
+	    r_dcache_cc_check = false;
+	}
+	r_dtlb_translation_valid = false;
+        r_dcache_ptba_ok = false;
+        break;
+    }
+    /////////////////////////
+    case DCACHE_ITLB_CLEANUP:
+    {
+        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
+
+        r_dcache.setinbit(((paddr_t)r_dcache_itlb_cleanup_line.read()*m_dcache_words*2), r_dcache_in_itlb, false);
+        r_dcache_itlb_cleanup_req = false;
+        r_dcache_fsm = DCACHE_IDLE;
+        break;
+    }
+    } // end switch r_dcache_fsm
+
+#ifdef SOCLIB_MODULE_DEBUG
+    std::cout << name() << " Data Response: " << drsp << std::endl;
+#endif
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //      INVAL DTLB CHECK FSM 
+    ////////////////////////////////////////////////////////////////////////////////////////
+    switch(r_inval_dtlb_fsm) {
+    /////////////////////
+    case INVAL_DTLB_IDLE:
+    {
+        if ( r_dcache_dtlb_inval_req ) 
+        {
+            r_ccinval_dtlb_way = 0;
+            r_ccinval_dtlb_set = 0;
+            r_inval_dtlb_fsm = INVAL_DTLB_CHECK;    
+            m_cost_data_tlb_inval_frz++;
+        }   
+        break;
+    }
+    ////////////////////////////
+    case INVAL_DTLB_CHECK:
+    {
+        m_cost_data_tlb_inval_frz++;
+
+        size_t way = r_ccinval_dtlb_way; 
+        size_t set = r_ccinval_dtlb_set;
+        bool end = false;        
+        bool tlb_hit = dcache_tlb.cccheck(r_dcache_dtlb_inval_line.read(), way, set, &way, &set, &end); 
+    
+        if ( tlb_hit )
+        {
+            r_ccinval_dtlb_way = way; 
+            r_ccinval_dtlb_set = set;
+            r_dtlb_cc_check_end = end;
+            r_inval_dtlb_fsm = INVAL_DTLB_INVAL;
+            m_cpt_data_tlb_inval++;    
+        }        
+        else
+        {
+            r_inval_dtlb_fsm = INVAL_DTLB_CLEAR;    
+        }
+        break;
+    }
+    /////////////////////////
+    case INVAL_DTLB_INVAL:
+    {
+        m_cost_data_tlb_inval_frz++;
+
+        dcache_tlb.ccinval(r_ccinval_dtlb_way, r_ccinval_dtlb_set);
+
+        if ( !r_dtlb_cc_check_end )
+        {
+            r_inval_dtlb_fsm = INVAL_DTLB_CHECK; 
+        }
+        else
+        {
+            r_inval_dtlb_fsm = INVAL_DTLB_CLEAR;    
+        }
+        break;
+    }
+    ////////////////////
+    case INVAL_DTLB_CLEAR:
+    {
+        r_dcache_dtlb_inval_req = false;
+        r_dtlb_cc_check_end = false;
+        r_ccinval_dtlb_way = 0; 
+        r_ccinval_dtlb_set = 0; 
+        r_inval_dtlb_fsm = INVAL_DTLB_IDLE;   
+        m_cpt_data_tlb_inval++;    
+        break;
+    }
+    } // end switch r_inval_itlb_fsm
+
+    /////////// execute one iss cycle /////////////////////////////////
+    {
+    uint32_t it = 0;
+    for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if(p_irq[i].read()) it |= (1<<i);
+    m_iss.executeNCycles(1, irsp, drsp, it);
+    }
+
+    ////////////// number of frozen cycles //////////////////////////
+    if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) )
+    {
+        m_cpt_frz_cycles++;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    //     VCI_CMD FSM 
+    //
+    // This FSM handles requests from both the DCACHE controler
+    // (request registers) and the ICACHE controler (request registers).
+    // There is 10 VCI transaction types :
+    // - INS_TLB_READ
+    // - INS_TLB_WRITE
+    // - INS_MISS
+    // - INS_UNC_MISS
+    // - DATA_TLB_READ
+    // - DATA_TLB_WRITE
+    // - DATA_TLB_DIRTY
+    // - DATA_MISS
+    // - DATA_UNC 
+    // - DATA_WRITE
+    // The ICACHE requests have the highest priority.
+    // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM and RSP_FSM
+    // exit simultaneously the IDLE state.
+    //////////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_cmd_fsm) {
+    
+    case CMD_IDLE:
+        if (r_vci_rsp_fsm != RSP_IDLE)
+            break;
+
+        r_vci_cmd_cpt = 0;
+
+        if (r_icache_cleanup_req)
+        {
+            r_vci_cmd_fsm = CMD_INS_CLEANUP;
+        }
+        else if (r_dcache_cleanup_req)
+        {
+            r_vci_cmd_fsm = CMD_DATA_CLEANUP;
+        }
+        else if (r_dcache_itlb_read_req)           
+        {            
+            r_vci_cmd_fsm = CMD_ITLB_READ;
+            m_cpt_itlbmiss_transaction++; 
+        } 
+	else if (r_dcache_itlb_ll_acc_req)
+	{
+	    r_vci_cmd_fsm = CMD_ITLB_ACC_LL;
+            m_cpt_itlb_write_transaction++; 
+	}
+	else if (r_dcache_itlb_sc_acc_req)
+	{
+	    r_vci_cmd_fsm = CMD_ITLB_ACC_SC;
+            m_cpt_itlb_write_transaction++; 
+	}
+        else if (r_icache_miss_req) 
+        {    
+            r_vci_cmd_fsm = CMD_INS_MISS;
+            m_cpt_imiss_transaction++; 
+        }
+        else if (r_icache_unc_req) 
+        {    
+            r_vci_cmd_fsm = CMD_INS_UNC;
+            m_cpt_imiss_transaction++; 
+        }  
+        else if (r_dcache_tlb_read_req) 
+        {            
+            r_vci_cmd_fsm = CMD_DTLB_READ;
+            m_cpt_dtlbmiss_transaction++; 
+        } 
+        else if (r_dcache_tlb_ll_acc_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_ACC_LL;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_tlb_sc_acc_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_ACC_SC;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_tlb_ll_dirty_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_DIRTY_LL;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_tlb_sc_dirty_req) 
+        {  
+            r_vci_cmd_fsm = CMD_DTLB_DIRTY_SC;
+            m_cpt_dtlb_write_transaction++; 
+        } 
+        else if (r_dcache_write_req)
+        {
+            r_vci_cmd_fsm = CMD_DATA_WRITE;
+            r_vci_cmd_cpt = r_wbuf.getMin();
+            r_vci_cmd_min = r_wbuf.getMin();
+            r_vci_cmd_max = r_wbuf.getMax(); 
+            m_cpt_write_transaction++; 
+            m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1);
+        }
+        else if (r_dcache_miss_req)  
+        {
+            r_vci_cmd_fsm = CMD_DATA_MISS;
+            m_cpt_dmiss_transaction++; 
+        }
+        else if (r_dcache_unc_req)  
+        {
+            r_vci_cmd_fsm = CMD_DATA_UNC;
+            m_cpt_unc_transaction++; 
+        }
+        break;
+
+    case CMD_DATA_WRITE:
+        if ( p_vci_ini_rw.cmdack.read() ) 
+        {
+            r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
+            if (r_vci_cmd_cpt == r_vci_cmd_max) 
+            {
+                r_vci_cmd_fsm = CMD_IDLE;
+                r_wbuf.reset();
+            }
+        }
+        break;
+
+    case CMD_INS_CLEANUP:
+    case CMD_DATA_CLEANUP:
+        if ( p_vci_ini_c.cmdack.read() ) 
+	{
+            r_vci_cmd_fsm = CMD_IDLE;
+        }
+        break;
+
+    default:
+        if ( p_vci_ini_rw.cmdack.read() )
+        {  
+            r_vci_cmd_fsm = CMD_IDLE;
+        }
+        break;
+
+    } // end  switch r_vci_cmd_fsm
+
+    //////////////////////////////////////////////////////////////////////////
+    //      VCI_RSP FSM 
+    //
+    // This FSM is synchronized with the VCI_CMD FSM, as both FSMs exit the
+    // IDLE state simultaneously.
+    //////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_rsp_fsm) {
+
+    case RSP_IDLE:
+        assert( !p_vci_ini_rw.rspval.read() && !p_vci_ini_c.rspval.read() && "Unexpected response" );
+
+        if (r_vci_cmd_fsm != CMD_IDLE)
+            break;
+
+        r_vci_rsp_cpt = 0;
+        if (r_icache_cleanup_req)	     // ICACHE cleanup response 
+        {
+            r_vci_rsp_fsm = RSP_INS_CLEANUP;
+        }
+        else if (r_dcache_cleanup_req)	     // DCACHE cleanup response
+        {
+            r_vci_rsp_fsm = RSP_DATA_CLEANUP;
+        }
+        else if (r_dcache_itlb_read_req)          // ITLB miss response
+        {            
+            r_vci_rsp_fsm = RSP_ITLB_READ;
+        } 
+        else if (r_dcache_itlb_ll_acc_req)   // ITLB linked load response
+        {   
+            r_vci_rsp_fsm = RSP_ITLB_ACC_LL;
+        } 
+        else if (r_dcache_itlb_sc_acc_req)   // ITLB store conditional response
+        {   
+            r_vci_rsp_fsm = RSP_ITLB_ACC_SC;
+        } 
+        else if (r_icache_miss_req)          // ICACHE cached miss response
+        {   
+            r_vci_rsp_fsm = RSP_INS_MISS;
+        }
+        else if (r_icache_unc_req)           // ICACHE uncached miss response
+        {   
+            r_vci_rsp_fsm = RSP_INS_UNC;
+        }  
+        else if (r_dcache_tlb_read_req)      // ITLB miss response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_READ; 
+        }
+        else if (r_dcache_tlb_ll_acc_req)    // DTLB access bits linked load response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_ACC_LL; 
+        }
+        else if (r_dcache_tlb_sc_acc_req)    // DTLB access bits store conditional response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_ACC_SC; 
+        }
+        else if (r_dcache_tlb_ll_dirty_req)  // DTLB dirty bit linked load response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_DIRTY_LL; 
+        }
+        else if (r_dcache_tlb_sc_dirty_req)  // DTLB dirty bit store conditional response
+        {
+            r_vci_rsp_fsm = RSP_DTLB_DIRTY_SC; 
+        }
+        else if (r_dcache_write_req)         // DCACHE write response
+        {
+            r_vci_rsp_fsm = RSP_DATA_WRITE;
+        }
+        else if (r_dcache_miss_req)          // DCACHE read response
+        {
+            r_vci_rsp_fsm = RSP_DATA_MISS;
+        }
+        else if (r_dcache_unc_req)           // DCACHE uncached read response
+        {
+            r_vci_rsp_fsm = RSP_DATA_UNC;
+        }
+        break;
+
+    case RSP_ITLB_READ:
+        m_cost_itlbmiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                    "illegal VCI response packet for data read miss");
+            r_dcache_itlb_read_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        } 
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_data_error = true;
+        }
+        break;
+
+    case RSP_ITLB_ACC_LL:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for ll tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else
+	{
+	    r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+	}
+        r_dcache_itlb_ll_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_ITLB_ACC_SC:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for sc tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else if ( p_vci_ini_rw.rdata.read() == 1 ) // store conditional is not successful
+	{
+	    r_dcache_itlb_ll_acc_req = true;
+	}
+        r_dcache_itlb_sc_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_INS_MISS:
+        m_cost_imiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert( (r_vci_rsp_cpt < m_icache_words) && 
+               "The VCI response packet for instruction miss is too long");
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            assert( (r_vci_rsp_cpt == m_icache_words - 1) &&
+                       "The VCI response packet for instruction miss is too short");
+            r_icache_miss_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+                
+        } 
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_ins_error = true;
+        }
+        break;
+
+    case RSP_INS_UNC:
+        m_cost_imiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for uncached instruction");
+
+        r_icache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+        r_icache_buf_unc_valid = true;
+        r_icache_unc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_ins_error = true;
+        }
+        break;
+
+    case RSP_DTLB_READ:
+        m_cost_dtlbmiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                    "illegal VCI response packet for data read miss");
+            r_dcache_tlb_read_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        } 
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_data_error = true;
+        }
+        break;
+
+    case RSP_DTLB_ACC_LL:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for ll tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else
+	{
+	    r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+	}
+        r_dcache_tlb_ll_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DTLB_ACC_SC:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for sc tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else if ( p_vci_ini_rw.rdata.read() == 1 ) // store conditional is not successful
+	{
+	    r_dcache_tlb_ll_acc_req = true;
+	}
+        r_dcache_tlb_sc_acc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DTLB_DIRTY_LL:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for ll tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else
+	{
+	    r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+	}
+        r_dcache_tlb_ll_dirty_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DTLB_DIRTY_SC:
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for sc tlb");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+	else if ( p_vci_ini_rw.rdata.read() == 1 ) // store conditional is not successful
+	{
+	    r_dcache_tlb_ll_dirty_req = true;
+	}
+        r_dcache_tlb_sc_dirty_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+	break;
+
+    case RSP_DATA_UNC:
+        m_cost_unc_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() ) 
+            break;
+
+        assert(p_vci_ini_rw.reop.read() &&
+               "illegal VCI response packet for data read uncached");
+
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            r_vci_rsp_data_error = true;
+        }
+        else
+        {
+            r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+            r_dcache_buf_unc_valid = true;
+        }
+        r_dcache_unc_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+        break;
+
+    case RSP_DATA_MISS:
+        m_cost_dmiss_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                    "illegal VCI response packet for data read miss");
+            r_dcache_miss_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        } 
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
+        {
+            r_vci_rsp_data_error = true;
+        }
+        break;
+
+    case RSP_DATA_WRITE:
+        m_cost_write_transaction++;
+        if ( ! p_vci_ini_rw.rspval.read() )
+            break;
+
+        if ( p_vci_ini_rw.reop.read() ) 
+        {
+            r_vci_rsp_fsm = RSP_IDLE;
+            r_dcache_write_req = false;
+        }
+        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) 
+        {
+            m_iss.setWriteBerr();
+        }
+        break;
+
+    case RSP_INS_CLEANUP:
+    case RSP_DATA_CLEANUP:
+        if ( ! p_vci_ini_c.rspval.read() )
+            break;
+        assert( p_vci_ini_c.reop.read() &&
+                "illegal VCI response packet for icache cleanup");
+        assert( (p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL) &&
+                "error in response packet for icache cleanup");
+
+        if ( r_vci_rsp_fsm == RSP_INS_CLEANUP ) 
+        {
+            r_icache_cleanup_req = false;
+        }
+        else
+        {                                    
+            r_dcache_cleanup_req = false;
+        }
+        r_vci_rsp_fsm = RSP_IDLE;
+        break;
+
+    } // end switch r_vci_rsp_fsm
+} // end transition()
+
+///////////////////////
+tmpl(void)::genMoore()
+///////////////////////
+{
+    // VCI initiator response
+
+    p_vci_ini_rw.rspack = true;
+    p_vci_ini_c.rspack = true;
+
+    // VCI initiator command
+
+    p_vci_ini_rw.pktid  = 0;
+    p_vci_ini_rw.srcid  = m_srcid_rw;
+    p_vci_ini_rw.cons   = false;
+    p_vci_ini_rw.wrap   = false;
+    p_vci_ini_rw.contig = true;
+    p_vci_ini_rw.clen   = 0;
+    p_vci_ini_rw.cfixed = false;
+
+    p_vci_ini_c.cmdval  = false;
+    p_vci_ini_c.address = 0;
+    p_vci_ini_c.wdata   = 0;
+    p_vci_ini_c.be      = 0;
+    p_vci_ini_c.plen    = 0;
+    p_vci_ini_c.cmd     = vci_param::CMD_NOP;
+    p_vci_ini_c.trdid   = 0;
+    p_vci_ini_c.pktid   = 0;
+    p_vci_ini_c.srcid   = 0;
+    p_vci_ini_c.cons    = false;
+    p_vci_ini_c.wrap    = false;
+    p_vci_ini_c.contig  = false;
+    p_vci_ini_c.clen    = 0;
+    p_vci_ini_c.cfixed  = false;
+    p_vci_ini_c.eop     = false;
+
+    switch (r_vci_cmd_fsm) {
+
+    case CMD_IDLE:
+        p_vci_ini_rw.cmdval  = false;
+        p_vci_ini_rw.address = 0;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0;
+        p_vci_ini_rw.trdid   = 0;
+        p_vci_ini_rw.plen    = 0;
+        p_vci_ini_rw.cmd     = vci_param::CMD_NOP;
+        p_vci_ini_rw.eop     = false;
+        break;
+
+    case CMD_ITLB_READ:     
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & m_dcache_yzmask;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 1; // via data cache cached read
+        p_vci_ini_rw.plen    = m_dcache_words << 2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+
+    case CMD_ITLB_ACC_LL:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & ~0x3;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini_rw.eop     = true;
+	break;
+
+    case CMD_ITLB_ACC_SC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & ~0x3;
+        p_vci_ini_rw.wdata   = r_icache_pte_update.read();
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_STORE_COND;
+        p_vci_ini_rw.eop     = true;
+	break;	
+
+    case CMD_INS_MISS:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & m_icache_yzmask;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 3; // ins cache cached read
+        p_vci_ini_rw.plen    = m_icache_words << 2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+
+    case CMD_INS_UNC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_icache_paddr_save.read() & ~0x3;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 2; // ins cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+
+    case CMD_DTLB_READ:     
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & m_dcache_yzmask;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 1; // via dcache cached read
+        p_vci_ini_rw.plen    = m_dcache_words << 2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+
+    case CMD_DTLB_ACC_LL:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini_rw.eop     = true;
+	break;
+
+    case CMD_DTLB_ACC_SC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini_rw.wdata   = r_dcache_pte_update.read();
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_STORE_COND;
+        p_vci_ini_rw.eop     = true;
+	break;	
+
+    case CMD_DTLB_DIRTY_LL:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_LOCKED_READ;
+        p_vci_ini_rw.eop     = true;
+	break;
+
+    case CMD_DTLB_DIRTY_SC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
+        p_vci_ini_rw.wdata   = r_dcache_pte_update.read();
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.cmd     = vci_param::CMD_STORE_COND;
+        p_vci_ini_rw.eop     = true;
+	break;	
+
+    case CMD_DATA_UNC:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_paddr_save.read() & ~0x3;
+        p_vci_ini_rw.trdid   = 0; // data cache uncached read
+        p_vci_ini_rw.plen    = 4;
+        p_vci_ini_rw.eop     = true;
+        switch(r_dcache_type_save) {
+        case iss_t::DATA_READ:
+            p_vci_ini_rw.wdata = 0;
+            p_vci_ini_rw.be    = r_dcache_be_save.read();
+            p_vci_ini_rw.cmd   = vci_param::CMD_READ;
+            break;
+        case iss_t::DATA_LL:
+            p_vci_ini_rw.wdata = 0;
+            p_vci_ini_rw.be    = 0xF;
+            p_vci_ini_rw.cmd   = vci_param::CMD_LOCKED_READ;
+            break;
+        case iss_t::DATA_SC:
+            p_vci_ini_rw.wdata = r_dcache_wdata_save.read();
+            p_vci_ini_rw.be    = 0xF;
+            p_vci_ini_rw.cmd   = vci_param::CMD_STORE_COND;
+            break;
+        default:
+            assert("this should not happen");
+        }
+        break;
+
+    case CMD_DATA_WRITE:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_wbuf.getAddress(r_vci_cmd_cpt);
+        p_vci_ini_rw.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
+        p_vci_ini_rw.be      = r_wbuf.getBe(r_vci_cmd_cpt);
+        p_vci_ini_rw.trdid   = 0; // data cache write
+        p_vci_ini_rw.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_WRITE;
+        p_vci_ini_rw.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
+        break;
+
+    case CMD_DATA_MISS:
+        p_vci_ini_rw.cmdval  = true;
+        p_vci_ini_rw.address = r_dcache_paddr_save.read() & m_dcache_yzmask;
+        p_vci_ini_rw.wdata   = 0;
+        p_vci_ini_rw.be      = 0xF;
+        p_vci_ini_rw.trdid   = 1; // data cache cached read
+        p_vci_ini_rw.plen    = m_dcache_words << 2;
+        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
+        p_vci_ini_rw.eop     = true;
+        break;
+
+    case CMD_INS_CLEANUP:
+    case CMD_DATA_CLEANUP:
+        p_vci_ini_rw.cmdval = false;
+        p_vci_ini_rw.address = 0;
+        p_vci_ini_rw.wdata  = 0;
+        p_vci_ini_rw.be     = 0;
+        p_vci_ini_rw.trdid  = 0;
+        p_vci_ini_rw.plen   = 0;
+        p_vci_ini_rw.cmd    = vci_param::CMD_NOP;
+        p_vci_ini_rw.eop    = false;
+
+        p_vci_ini_c.cmdval  = true;
+        if ( r_vci_cmd_fsm == CMD_INS_CLEANUP ) 
+	{
+	    p_vci_ini_c.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
+            p_vci_ini_c.trdid  = 1; // cleanup instruction
+	}
+        else
+	{                                    
+	    p_vci_ini_c.address = r_dcache_cleanup_line.read() * (m_dcache_words<<2);
+            p_vci_ini_c.trdid  = 0; // cleanup data
+	}
+        p_vci_ini_c.wdata  = 0;
+        p_vci_ini_c.be     = 0;
+        p_vci_ini_c.plen   = 4;
+        p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+        p_vci_ini_c.pktid  = 0;
+        p_vci_ini_c.srcid  = m_srcid_c;
+        p_vci_ini_c.cons   = false;
+        p_vci_ini_c.wrap   = false;
+        p_vci_ini_c.contig = false;
+        p_vci_ini_c.clen   = 0;
+        p_vci_ini_c.cfixed = false;
+        p_vci_ini_c.eop = true;
+        break;
+
+    } // end switch r_vci_cmd_fsm
+
+    // VCI_TGT
+    switch ( r_vci_tgt_fsm.read() ) {
+
+    case TGT_IDLE:
+    case TGT_UPDT_WORD:
+    case TGT_UPDT_DATA:
+        p_vci_tgt.cmdack  = true;
+        p_vci_tgt.rspval  = false;
+        break;
+
+    case TGT_RSP_BROADCAST:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
+        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+        p_vci_tgt.rpktid  = r_tgt_pktid.read();
+        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = true;
+        break;
+
+    case TGT_RSP_ICACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = !r_tgt_icache_req.read() && r_tgt_icache_rsp.read();
+        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+        p_vci_tgt.rpktid  = r_tgt_pktid.read();
+        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = true;
+        break;
+
+    case TGT_RSP_DCACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = !r_tgt_dcache_req.read() && r_tgt_dcache_rsp.read();
+        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+        p_vci_tgt.rpktid  = r_tgt_pktid.read();
+        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = true;
+        break;
+
+    case TGT_REQ_BROADCAST:
+    case TGT_REQ_ICACHE:
+    case TGT_REQ_DCACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = false;
+        break;
+
+    } // end switch TGT_FSM
+
+#ifdef SOCLIB_MODULE_DEBUG 
+   std::cout << name() 
+      	     << "Moore R/W:" << std::hex
+      	     << " p_vci_ini_rw.cmdval: " << p_vci_ini_rw.cmdval
+      	     << " p_vci_ini_rw.address: " << p_vci_ini_rw.address
+      	     << " p_vci_ini_rw.wdata: " << p_vci_ini_rw.wdata
+      	     << " p_vci_ini_rw.cmd: " << p_vci_ini_rw.cmd
+      	     << " p_vci_ini_rw.eop: " << p_vci_ini_rw.eop
+      	     << std::endl;
+
+   std::cout << name() 
+      	     << "Moore TGT:" << std::hex
+      	     << " p_vci_tgt.rspval: " << p_vci_tgt.rspval
+      	     << std::endl;
+
+   std::cout << name() 
+      	     << "Moore Cleanup:" << std::hex
+      	     << " p_vci_ini_c.cmdval: " << p_vci_ini_c.cmdval
+      	     << " p_vci_ini_c.address: " << p_vci_ini_c.address
+      	     << " p_vci_ini_c.trdid: " << p_vci_ini_c.trdid
+      	     << " p_vci_ini_c.cmd: " << p_vci_ini_c.cmd
+      	     << " p_vci_ini_c.eop: " << p_vci_ini_c.eop
+      	     << std::endl;
+
+#endif
+}
+
+}}
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
+
+
+
+
+
+
Index: trunk/modules/vci_cc_xcache_wrapper/caba/metadata/vci_cc_xcache_wrapper.sd
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper/caba/metadata/vci_cc_xcache_wrapper.sd	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper/caba/metadata/vci_cc_xcache_wrapper.sd	(revision 2)
@@ -0,0 +1,52 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_cc_xcache_wrapper',
+	classname = 'soclib::caba::VciCcXcacheWrapper',
+	tmpl_parameters = [
+		parameter.Module('vci_param', default = 'caba:vci_param'),
+		parameter.Module('iss_t'),
+		],
+	header_files = [
+		'../source/include/vci_cc_xcache_wrapper.h',
+		],
+	implementation_files = [
+		'../source/src/vci_cc_xcache_wrapper.cpp',
+		],
+	uses = [
+		Uses('caba:base_module'),
+		Uses('common:mapping_table'),
+		Uses('common:iss2'),
+		Uses('caba:write_buffer'),
+		Uses('caba:generic_cache', addr_t = 'uint32_t'),
+		],
+	ports = [
+		Port('caba:vci_initiator', 'p_vci_ini'),
+		Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:bit_in', 'p_irq', parameter.Constant('n_irq')),
+		Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+		Port('caba:clock_in', 'p_clk', auto = 'clock'),
+		],
+	instance_parameters = [
+		parameter.Int('proc_id'),
+		parameter.Module('mt', 'common:mapping_table', auto='env:mapping_table'),
+		parameter.IntTab('initiator_index'),
+		parameter.IntTab('target_indext'),
+		parameter.Int('icache_ways'),
+		parameter.Int('icache_sets'),
+		parameter.Int('icache_words'),
+		parameter.Int('dcache_ways'),
+		parameter.Int('dcache_sets'),
+		parameter.Int('dcache_words'),
+		],
+	   extensions = [
+		'dsx:get_ident=initiator_index:p_vci_ini',
+		'dsx:cpu=wrapper:iss_t',
+		'dsx:mapping_type=processor:proc_id',
+		],
+)
+
+
Index: trunk/modules/vci_cc_xcache_wrapper/caba/source/include/vci_cc_xcache_wrapper.h
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper/caba/source/include/vci_cc_xcache_wrapper.h	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper/caba/source/include/vci_cc_xcache_wrapper.h	(revision 2)
@@ -0,0 +1,287 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain
+ */
+ 
+#ifndef SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_H
+#define SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_H
+
+#include <inttypes.h>
+#include <systemc>
+#include "caba_base_module.h"
+#include "write_buffer.h"
+#include "generic_cache.h"
+#include "vci_initiator.h"
+#include "vci_target.h"
+#include "mapping_table.h"
+#include "static_assert.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+////////////////////////////////////////////
+template<typename vci_param, typename iss_t>
+class VciCcXcacheWrapper
+///////////////////////////////////////////
+    : public soclib::caba::BaseModule
+{
+    typedef uint32_t    addr_t;
+    typedef uint32_t    data_t;
+    typedef uint32_t    tag_t;
+    typedef uint32_t    be_t;
+
+    enum dcache_fsm_state_e {
+        DCACHE_IDLE,
+        DCACHE_WRITE_UPDT,
+        DCACHE_WRITE_REQ,
+        DCACHE_MISS_WAIT,
+        DCACHE_MISS_UPDT,
+        DCACHE_UNC_WAIT,
+        DCACHE_INVAL,
+        DCACHE_ERROR,
+        DCACHE_CC_CHECK,
+        DCACHE_CC_INVAL,
+        DCACHE_CC_UPDT,
+        DCACHE_CC_NOP,
+    };
+
+    enum icache_fsm_state_e {
+        ICACHE_IDLE,
+        ICACHE_MISS_WAIT,
+        ICACHE_MISS_UPDT,
+        ICACHE_UNC_WAIT,
+        ICACHE_ERROR,
+        ICACHE_CC_INVAL,
+    };
+
+    enum cmd_fsm_state_e {
+        CMD_IDLE,
+        CMD_INS_MISS,
+        CMD_INS_UNC,
+        CMD_DATA_MISS,
+        CMD_DATA_UNC,
+        CMD_DATA_WRITE,
+        CMD_INS_CLEANUP,
+        CMD_DATA_CLEANUP,
+    };
+
+    enum rsp_fsm_state_e {
+        RSP_IDLE,
+        RSP_INS_MISS,
+        RSP_INS_UNC,
+        RSP_DATA_MISS,
+        RSP_DATA_UNC,
+        RSP_DATA_WRITE,
+        RSP_INS_CLEANUP,
+        RSP_DATA_CLEANUP,
+    };
+
+    enum tgt_fsm_state_e {
+        TGT_IDLE,
+        TGT_UPDT_WORD,
+        TGT_UPDT_DATA,
+        TGT_REQ_BROADCAST,
+        TGT_REQ_DCACHE,
+        TGT_RSP_BROADCAST,
+        TGT_RSP_DCACHE,
+    };
+
+public:
+
+    // PORTS
+    sc_in<bool>                             p_clk;
+    sc_in<bool>                             p_resetn;
+    sc_in<bool>                             p_irq[iss_t::n_irq];
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini;
+    soclib::caba::VciTarget<vci_param>      p_vci_tgt;
+
+private:
+
+    // STRUCTURAL PARAMETERS
+    const soclib::common::AddressDecodingTable<uint32_t, bool>  m_cacheability_table;
+    const soclib::common::Segment                               m_segment;
+    iss_t                                                       m_iss;
+    const uint32_t                                              m_srcid;   
+    addr_t                                                      m_cleanup_address;
+    
+    const size_t                                                m_dcache_ways;
+    const size_t                                                m_dcache_words;
+    const size_t                                                m_dcache_yzmask;
+    const size_t                                                m_icache_ways;
+    const size_t                                                m_icache_words;
+    const size_t                                                m_icache_yzmask;
+
+    // REGISTERS
+    sc_signal<int>          r_dcache_fsm;
+    sc_signal<int>          r_dcache_fsm_save;
+    sc_signal<addr_t>       r_dcache_addr_save;
+    sc_signal<data_t>       r_dcache_wdata_save;
+    sc_signal<data_t>       r_dcache_rdata_save;
+    sc_signal<int>          r_dcache_type_save;
+    sc_signal<be_t>         r_dcache_be_save;
+    sc_signal<bool>         r_dcache_cached_save;
+    sc_signal<bool>         r_dcache_cleanup_req;
+    sc_signal<data_t>       r_dcache_cleanup_line;
+    sc_signal<bool>         r_dcache_miss_req;
+    sc_signal<bool>         r_dcache_unc_req;
+    sc_signal<bool>         r_dcache_write_req;
+    sc_signal<bool>         r_dcache_inval_rsp;
+
+    sc_signal<int>          r_icache_fsm;
+    sc_signal<int>          r_icache_fsm_save;
+    sc_signal<addr_t>       r_icache_addr_save;
+    sc_signal<bool>         r_icache_miss_req;
+    sc_signal<bool>         r_icache_unc_req;
+    sc_signal<bool>         r_icache_cleanup_req;
+    sc_signal<data_t>       r_icache_cleanup_line;
+    sc_signal<bool>         r_icache_inval_rsp;
+
+    sc_signal<int>          r_vci_cmd_fsm;
+    sc_signal<size_t>       r_vci_cmd_min;       
+    sc_signal<size_t>       r_vci_cmd_max;       
+    sc_signal<size_t>       r_vci_cmd_cpt;       
+      
+    sc_signal<int>          r_vci_rsp_fsm;
+    sc_signal<bool>         r_vci_rsp_ins_error;    
+    sc_signal<bool>         r_vci_rsp_data_error;    
+    sc_signal<size_t>       r_vci_rsp_cpt;  
+
+    data_t                  *r_icache_miss_buf;    
+    data_t                  *r_dcache_miss_buf;    
+    sc_signal<bool>         r_icache_buf_unc_valid;
+    sc_signal<bool>         r_dcache_buf_unc_valid;
+
+    data_t                  *r_tgt_buf;
+    bool                    *r_tgt_val;
+
+    sc_signal<int>          r_vci_tgt_fsm;
+    sc_signal<size_t>       r_tgt_addr;
+    sc_signal<size_t>       r_tgt_word;
+    sc_signal<bool>         r_tgt_update;
+    sc_signal<size_t>       r_tgt_srcid;
+    sc_signal<size_t>       r_tgt_pktid;
+    sc_signal<size_t>       r_tgt_trdid;
+    sc_signal<size_t>       r_tgt_plen;
+    sc_signal<bool>         r_tgt_icache_req;
+    sc_signal<bool>         r_tgt_dcache_req;
+    sc_signal<bool>         r_tgt_icache_rsp;
+    sc_signal<bool>         r_tgt_dcache_rsp;
+
+    WriteBuffer<addr_t>     r_wbuf;
+    GenericCache<addr_t>    r_icache;
+    GenericCache<addr_t>    r_dcache;
+
+    // Activity counters
+    uint32_t m_cpt_dcache_data_read;        // DCACHE DATA READ
+    uint32_t m_cpt_dcache_data_write;       // DCACHE DATA WRITE
+    uint32_t m_cpt_dcache_dir_read;         // DCACHE DIR READ
+    uint32_t m_cpt_dcache_dir_write;        // DCACHE DIR WRITE
+
+    uint32_t m_cpt_icache_data_read;        // ICACHE DATA READ
+    uint32_t m_cpt_icache_data_write;       // ICACHE DATA WRITE
+    uint32_t m_cpt_icache_dir_read;         // ICACHE DIR READ
+    uint32_t m_cpt_icache_dir_write;        // ICACHE DIR WRITE
+
+    uint32_t m_cpt_cc_update;               // number of coherence update packets 
+    uint32_t m_cpt_cc_inval;                // number of coherence inval packets
+
+    uint32_t m_cpt_frz_cycles;	            // number of cycles where the cpu is frozen
+    uint32_t m_cpt_total_cycles;	        // total number of cycles 
+
+    uint32_t m_cpt_read;                    // total number of read instructions
+    uint32_t m_cpt_write;                   // total number of write instructions
+    uint32_t m_cpt_data_miss;               // number of read miss
+    uint32_t m_cpt_ins_miss;                // number of instruction miss
+    uint32_t m_cpt_unc_read;                // number of read uncached
+    uint32_t m_cpt_write_cached;            // number of cached write
+
+    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
+    uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
+    uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
+    uint32_t m_cost_ins_miss_frz;           // number of frozen cycles related to ins miss
+
+    uint32_t m_cpt_imiss_transaction;       // number of VCI instruction miss transactions
+    uint32_t m_cpt_dmiss_transaction;       // number of VCI data miss transactions
+    uint32_t m_cpt_unc_transaction;         // number of VCI uncached read transactions
+    uint32_t m_cpt_write_transaction;       // number of VCI write transactions
+
+    uint32_t m_cost_imiss_transaction;      // cumulated duration for VCI IMISS transactions
+    uint32_t m_cost_dmiss_transaction;      // cumulated duration for VCI DMISS transactions
+    uint32_t m_cost_unc_transaction;        // cumulated duration for VCI UNC transactions
+    uint32_t m_cost_write_transaction;      // cumulated duration for VCI WRITE transactions
+    uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions
+
+protected:
+    SC_HAS_PROCESS(VciCcXcacheWrapper);
+
+public:
+
+    VciCcXcacheWrapper(
+                       sc_module_name insname,
+                       int proc_id,
+                       const soclib::common::MappingTable &mtp,
+                       const soclib::common::MappingTable &mtc,
+                       const soclib::common::IntTab &initiator_index,
+                       const soclib::common::IntTab &target_index,
+                       size_t icache_ways,
+                       size_t icache_sets,
+                       size_t icache_words,
+                       size_t dcache_ways,
+                       size_t dcache_sets,
+                       size_t dcache_words,
+                       addr_t cleanup_offset );
+
+    ~VciCcXcacheWrapper();
+
+    void print_cpi();
+    void print_stats();
+
+private:
+
+    void transition();
+    void genMoore();
+
+    soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC);
+    soclib_static_assert((int)iss_t::SC_NOT_ATOMIC == (int)vci_param::STORE_COND_NOT_ATOMIC);
+};
+
+}}
+
+#endif /* SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
Index: trunk/modules/vci_cc_xcache_wrapper/caba/source/src/vci_cc_xcache_wrapper.cpp
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper/caba/source/src/vci_cc_xcache_wrapper.cpp	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper/caba/source/src/vci_cc_xcache_wrapper.cpp	(revision 2)
@@ -0,0 +1,1564 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu nipo
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+// History
+// - 25/04/2008
+//   The existing vci_xcache component has been extended to include 
+//   a VCI target port to support a directory based coherence protocol.
+//   Two types of packets can be send by the L2 cache to the L1 cache
+//   * INVALIDATE packets : length = 1
+//   * UPDATE packets : length = n + 2   
+//   The CLEANUP packets are sent by the L1 cache to the L2 cache, 
+//   to signal a replaced cache line.
+// - 12/08/2008
+//   The vci_cc_xcache_wrapper component instanciates directly the processsor 
+//   iss, in order to supress the processor/cache interface.
+//   According to the VCI advanced specification, this component uses one 
+//   word VCI CMD packets for MISS transactions, and accept one word VCI RSP
+//   packets for Write burst  transactions.
+//   The write buffer has been modified to use the WriteBuffer object. 
+//   A VCI write burst is constructed when two conditions are satisfied :
+//   The processor make strictly successive write requests, and they are
+//   in the same cache line. The write buffer performs re-ordering, to
+//   respect the contiguous addresses VCI constraint. In case of several
+//   WRITE_WORD requests in the same word, only the last request is conserved.
+//   In case of several WRITE_HALF or WRITE_WORD requests in the same word,
+//   the requests are merged in the same word. In case of uncached write
+//   requests, each request is transmited as a single VCI transaction.
+//   Both the data & instruction caches can be flushed in one single cycle.
+///////////////////////////////////////////////////////////////////////////////
+
+#include <cassert>
+#include "arithmetics.h"
+#include "../include/vci_cc_xcache_wrapper.h"
+
+#define DEBUG_CC_XCACHE_WRAPPER 0
+
+namespace soclib { 
+namespace caba {
+
+#if DEBUG_CC_XCACHE_WRAPPER
+namespace {
+const char *dcache_fsm_state_str[] = {
+    "DCACHE_IDLE",
+    "DCACHE_WRITE_UPDT",
+    "DCACHE_WRITE_REQ",
+    "DCACHE_MISS_WAIT",
+    "DCACHE_MISS_UPDT",
+    "DCACHE_UNC_WAIT",
+    "DCACHE_INVAL",
+    "DCACHE_ERROR",
+    "DCACHE_CC_CHECK",
+    "DCACHE_CC_INVAL",
+    "DCACHE_CC_UPDT",
+    "DCACHE_CC_NOP",
+};
+const char *icache_fsm_state_str[] = {
+    "ICACHE_IDLE",
+    "ICACHE_MISS_WAIT",
+    "ICACHE_MISS_UPDT",
+    "ICACHE_UNC_WAIT",
+    "ICACHE_ERROR",
+    "ICACHE_CC_INVAL",
+};
+const char *cmd_fsm_state_str[] = {
+    "CMD_IDLE",
+    "CMD_INS_MISS",
+    "CMD_INS_UNC",
+    "CMD_DATA_MISS",
+    "CMD_DATA_UNC",
+    "CMD_DATA_WRITE",
+};
+const char *rsp_fsm_state_str[] = {
+    "RSP_IDLE",
+    "RSP_INS_MISS",
+    "RSP_INS_UNC",
+    "RSP_DATA_MISS",
+    "RSP_DATA_UNC",
+    "RSP_DATA_WRITE",
+};
+const char *tgt_fsm_state_str[] = {
+    "TGT_IDLE",
+    "TGT_UPDT_WORD",
+    "TGT_UPDT_DATA",
+    "TGT_REQ_BROADCAST",
+    "TGT_REQ_DCACHE",
+    "TGT_RSP_BROADCAST",
+    "TGT_RSP_DCACHE",
+};
+}
+#endif
+
+#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXcacheWrapper<vci_param, iss_t>
+
+using soclib::common::uint32_log2;
+
+/////////////////////////////////
+tmpl(/**/)::VciCcXcacheWrapper(
+                               /////////////////////////////////
+                               sc_module_name name,
+                               int proc_id,
+                               const soclib::common::MappingTable &mtp,
+                               const soclib::common::MappingTable &mtc,
+                               const soclib::common::IntTab &initiator_index,
+                               const soclib::common::IntTab &target_index,
+                               size_t icache_ways,
+                               size_t icache_sets,
+                               size_t icache_words,
+                               size_t dcache_ways,
+                               size_t dcache_sets,
+                               size_t dcache_words,
+                               addr_t cleanup_offset )
+           : 
+           soclib::caba::BaseModule(name),
+
+           p_clk("clk"),
+           p_resetn("resetn"),
+           p_vci_ini("vci_ini"),
+           p_vci_tgt("vci_tgt"),
+
+           m_cacheability_table(mtp.getCacheabilityTable()),
+           m_segment(mtc.getSegment(target_index)),
+           m_iss(this->name(), proc_id),
+           m_srcid(mtp.indexForId(initiator_index)),
+           m_cleanup_address(cleanup_offset),
+
+           m_dcache_ways(dcache_ways),
+           m_dcache_words(dcache_words),
+           m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
+           m_icache_ways(icache_ways),
+           m_icache_words(icache_words),
+           m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
+
+           r_dcache_fsm("r_dcache_fsm"),
+           r_dcache_fsm_save("r_dcache_fsm_save"),
+           r_dcache_addr_save("r_dcache_addr_save"),
+           r_dcache_wdata_save("r_dcache_wdata_save"),
+           r_dcache_rdata_save("r_dcache_rdata_save"),
+           r_dcache_type_save("r_dcache_type_save"),
+           r_dcache_be_save("r_dcache_be_save"),
+           r_dcache_cached_save("r_dcache_cached_save"),
+           r_dcache_cleanup_req("r_dcache_cleanup_req"),
+           r_dcache_cleanup_line("r_dcache_cleanup_line"),
+           r_dcache_miss_req("r_dcache_miss_req"),
+           r_dcache_unc_req("r_dcache_unc_req"),
+           r_dcache_write_req("r_dcache_write_req"),
+
+           r_icache_fsm("r_icache_fsm"),
+           r_icache_fsm_save("r_icache_fsm_save"),
+           r_icache_addr_save("r_icache_addr_save"),
+           r_icache_miss_req("r_icache_miss_req"),
+           r_icache_cleanup_req("r_icache_cleanup_req"),
+           r_icache_cleanup_line("r_icache_cleanup_line"),
+
+           r_vci_cmd_fsm("r_vci_cmd_fsm"),
+           r_vci_cmd_min("r_vci_cmd_min"),
+           r_vci_cmd_max("r_vci_cmd_max"),
+           r_vci_cmd_cpt("r_vci_cmd_cpt"),
+
+           r_vci_rsp_fsm("r_vci_rsp_fsm"),
+           r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
+           r_vci_rsp_data_error("r_vci_rsp_data_error"),
+           r_vci_rsp_cpt("r_vci_rsp_cpt"),
+
+           r_dcache_buf_unc_valid("r_dcache_buf_unc_valid"),
+           r_icache_buf_unc_valid("r_icache_buf_unc_valid"),
+
+           r_vci_tgt_fsm("r_vci_tgt_fsm"),
+           r_tgt_addr("r_tgt_addr"),
+           r_tgt_word("r_tgt_word"),
+           r_tgt_update("r_tgt_update"),
+           r_tgt_srcid("r_tgt_srcid"),
+           r_tgt_pktid("r_tgt_pktid"),
+           r_tgt_trdid("r_tgt_trdid"),
+           r_tgt_icache_req("r_tgt_icache_req"),
+           r_tgt_dcache_req("r_tgt_dcache_req"),
+
+           r_wbuf("r_wbuf", dcache_words ),
+           r_icache("icache", icache_ways, icache_sets, icache_words),
+           r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
+
+{
+    r_icache_miss_buf = new data_t[icache_words];
+    r_dcache_miss_buf = new data_t[dcache_words];
+    r_tgt_buf         = new data_t[dcache_words];
+    r_tgt_val         = new bool[dcache_words];
+
+    SC_METHOD(transition);
+    dont_initialize();
+    sensitive << p_clk.pos();
+  
+    SC_METHOD(genMoore);
+    dont_initialize();
+    sensitive << p_clk.neg();
+
+    typename iss_t::CacheInfo cache_info;
+    cache_info.has_mmu = false;
+    cache_info.icache_line_size = icache_words*sizeof(data_t);
+    cache_info.icache_assoc = icache_ways;
+    cache_info.icache_n_lines = icache_sets;
+    cache_info.dcache_line_size = dcache_words*sizeof(data_t);
+    cache_info.dcache_assoc = dcache_ways;
+    cache_info.dcache_n_lines = dcache_sets;
+    m_iss.setCacheInfo(cache_info);
+} // end constructor
+
+///////////////////////////////////
+tmpl(/**/)::~VciCcXcacheWrapper()
+           ///////////////////////////////////
+{
+    delete [] r_icache_miss_buf;
+    delete [] r_dcache_miss_buf;
+    delete [] r_tgt_val;
+    delete [] r_tgt_buf;
+}
+
+////////////////////////
+tmpl(void)::print_cpi()
+           ////////////////////////
+{
+    std::cout << "CPU " << m_srcid << " : CPI = " 
+              << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
+}
+////////////////////////
+tmpl(void)::print_stats()
+           ////////////////////////
+{
+    float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
+    std::cout << "------------------------------------" << std:: dec << std::endl;
+    std::cout << "CPU " << m_srcid << " / Time = " << m_cpt_total_cycles << std::endl;
+    std::cout << "- CPI                = " << (float)m_cpt_total_cycles/run_cycles << std::endl ;
+    std::cout << "- READ RATE          = " << (float)m_cpt_read/run_cycles << std::endl ;
+    std::cout << "- WRITE RATE         = " << (float)m_cpt_write/run_cycles << std::endl;
+    std::cout << "- UNCACHED READ RATE = " << (float)m_cpt_unc_read/m_cpt_read << std::endl ;
+    std::cout << "- CACHED WRITE RATE  = " << (float)m_cpt_write_cached/m_cpt_write << std::endl ;
+    std::cout << "- IMISS_RATE         = " << (float)m_cpt_ins_miss/run_cycles << std::endl;
+    std::cout << "- DMISS RATE         = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl ;
+    std::cout << "- INS MISS COST      = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl;
+    std::cout << "- IMISS TRANSACTION  = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl;
+    std::cout << "- DMISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl;
+    std::cout << "- DMISS TRANSACTION  = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl;
+    std::cout << "- UNC COST           = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl;
+    std::cout << "- UNC TRANSACTION    = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl;
+    std::cout << "- WRITE COST         = " << (float)m_cost_write_frz/m_cpt_write << std::endl;
+    std::cout << "- WRITE TRANSACTION  = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl;
+    std::cout << "- WRITE LENGTH       = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl;
+}
+
+//////////////////////////
+tmpl(void)::transition()
+           //////////////////////////
+{
+    if ( ! p_resetn.read() ) {
+
+        m_iss.reset();
+
+        // FSM states
+        r_dcache_fsm = DCACHE_IDLE;
+        r_icache_fsm = ICACHE_IDLE;
+        r_vci_cmd_fsm = CMD_IDLE;
+        r_vci_rsp_fsm = RSP_IDLE;
+        r_vci_tgt_fsm = TGT_IDLE;
+
+        // write buffer & caches
+        r_wbuf.reset();
+        r_icache.reset();
+        r_dcache.reset();
+
+        // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI  FSMs
+        r_icache_miss_req    = false;
+        r_icache_unc_req     = false;
+        r_icache_cleanup_req = false;
+        r_dcache_miss_req    = false;
+        r_dcache_unc_req     = false;
+        r_dcache_write_req   = false;
+        r_dcache_cleanup_req = false;
+
+        // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
+        r_tgt_icache_req     = false;
+        r_tgt_dcache_req     = false;
+
+        // internal messages in DCACHE et ICACHE FSMs
+        r_icache_inval_rsp   = false;
+        r_dcache_inval_rsp   = false;
+
+        // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs
+        r_dcache_buf_unc_valid = false;
+        r_icache_buf_unc_valid = false;
+        r_vci_rsp_data_error   = false;
+        r_vci_rsp_ins_error    = false;
+
+        // activity counters
+        m_cpt_dcache_data_read  = 0;
+        m_cpt_dcache_data_write = 0;
+        m_cpt_dcache_dir_read  = 0;
+        m_cpt_dcache_dir_write = 0;
+        m_cpt_icache_data_read  = 0;
+        m_cpt_icache_data_write = 0;
+        m_cpt_icache_dir_read  = 0;
+        m_cpt_icache_dir_write = 0;
+
+        m_cpt_cc_update = 0;
+        m_cpt_cc_inval = 0;
+
+        m_cpt_frz_cycles = 0;
+        m_cpt_total_cycles = 0;
+
+        m_cpt_read = 0;
+        m_cpt_write = 0;
+        m_cpt_data_miss = 0;
+        m_cpt_ins_miss = 0;
+        m_cpt_unc_read = 0;
+        m_cpt_write_cached = 0;
+
+        m_cost_write_frz = 0;
+        m_cost_data_miss_frz = 0;
+        m_cost_unc_read_frz = 0;
+        m_cost_ins_miss_frz = 0;
+
+        m_cpt_imiss_transaction = 0;
+        m_cpt_dmiss_transaction = 0;
+        m_cpt_unc_transaction = 0;
+        m_cpt_write_transaction = 0;
+
+        m_cost_imiss_transaction = 0;
+        m_cost_dmiss_transaction = 0;
+        m_cost_unc_transaction = 0;
+        m_cost_write_transaction = 0;
+        m_length_write_transaction = 0;
+
+        return;
+    }
+
+#if DEBUG_CC_XCACHE_WRAPPER
+    std::cout << "--------------------------------------------" << std::endl;
+    std::cout << std::dec << "CC_XCACHE_WRAPPER " << m_srcid << " / Time = " << m_cpt_total_cycles << std::endl;
+    std::cout             << " tgt fsm    = " << tgt_fsm_state_str[r_vci_tgt_fsm] << std::endl
+                          << " dcache fsm = " << dcache_fsm_state_str[r_dcache_fsm] << std::endl
+                          << " icache fsm = " << icache_fsm_state_str[r_icache_fsm] << std::endl
+                          << " cmd fsm    = " << cmd_fsm_state_str[r_vci_cmd_fsm] << std::endl
+                          << " rsp fsm    = " << rsp_fsm_state_str[r_vci_rsp_fsm] << std::endl;
+#endif
+
+    m_cpt_total_cycles++;
+
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_FSM controls the following ressources:
+    // - r_vci_tgt_fsm
+    // - r_tgt_buf[nwords]
+    // - r_tgt_val[nwords]
+    // - r_tgt_update
+    // - r_tgt_word
+    // - r_tgt_addr
+    // - r_tgt_srcid
+    // - r_tgt_trdid
+    // - r_tgt_pktid
+    // All VCI commands must be CMD_WRITE.
+    // If the VCI address offset is null, the command is an invalidate 
+    // request. It is an update request otherwise.
+    // The VCI_TGT FSM stores the external request arguments in the
+    // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 
+    // & r_tgt_dcache_req flip-flops to signal the external request to 
+    // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
+    // of the update or invalidate request in the RSP state.
+    // -  for an invalidate request the VCI packet length is 1 word.
+    // The WDATA field contains the line index (i.e. the Z & Y fields).
+    // -  for an update request the VCI packet length is (n+2) words.
+    // The WDATA field of the first VCI word contains the line number.
+    // The WDATA field of the second VCI word contains the word index.
+    // The WDATA field of the n following words contains the values.
+    // -  for both invalidate & update requests, the VCI response
+    // is one single word.
+    // In case of errors in the VCI command packet, the simulation
+    // is stopped with an error message.
+    /////////////////////////////////////////////////////////////////////
+    
+    switch(r_vci_tgt_fsm) {
+
+    case TGT_IDLE:
+        if ( p_vci_tgt.cmdval.read() ) 
+        {
+            addr_t address = p_vci_tgt.address.read();
+
+            if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) 
+            {
+                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the received VCI command is not a write" << std::endl;
+                exit(0);
+            }
+
+            // multi-update or multi-invalidate for data type
+            if ( (address != 0x3) && (! m_segment.contains(address)) ) 
+            {
+                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "out of segment VCI command received for a multi-updt or multi-inval request" << std::endl;
+                exit(0);
+            }
+
+            r_tgt_srcid = p_vci_tgt.srcid.read();
+            r_tgt_trdid = p_vci_tgt.trdid.read();
+            r_tgt_pktid = p_vci_tgt.pktid.read();
+            r_tgt_plen  = p_vci_tgt.plen.read();    // todo: wait L2 modification
+            r_tgt_addr = (addr_t)p_vci_tgt.wdata.read() * m_dcache_words * 4;
+            
+            if ( address == 0x3 )   // broadcast invalidate for data or instruction type
+            {
+                if ( ! p_vci_tgt.eop.read() ) 
+                {
+                    std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                    std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
+                    exit(0);
+                }
+                r_tgt_update = false; 
+                r_vci_tgt_fsm = TGT_REQ_BROADCAST;
+                m_cpt_cc_inval++ ;
+            }
+            else                    // multi-update or multi-invalidate for data type
+            { 
+                addr_t cell = address - m_segment.baseAddress();
+                if (cell == 0) 
+                {                               // invalidate 
+                    if ( ! p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_update = false; 
+                    r_vci_tgt_fsm = TGT_REQ_DCACHE;
+                    m_cpt_cc_inval++ ;
+                } 
+                else 
+                {                                // update
+                    if ( p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_update = true; 
+                    r_vci_tgt_fsm = TGT_UPDT_WORD;
+                    m_cpt_cc_update++ ;
+                }
+            } // end if address
+        } // end if cmdval
+        break;
+
+    case TGT_UPDT_WORD:
+        if (p_vci_tgt.cmdval.read()) 
+        {
+            if ( p_vci_tgt.eop.read() ) 
+            {
+                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                exit(0);
+            }
+            for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_val[i] = false;
+            r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
+            r_vci_tgt_fsm = TGT_UPDT_DATA;
+        }
+        break;
+
+    case TGT_UPDT_DATA:
+        if (p_vci_tgt.cmdval.read()) 
+        {
+            size_t word = r_tgt_word.read();
+            if ( word >= m_dcache_words ) 
+            {
+                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
+                exit(0);
+            }
+            r_tgt_buf[word] = p_vci_tgt.wdata.read();
+            if(p_vci_tgt.be.read())    r_tgt_val[word] = true;
+            r_tgt_word = word + 1;
+            if (p_vci_tgt.eop.read())  r_vci_tgt_fsm = TGT_REQ_DCACHE;
+        }
+        break;
+
+    case TGT_REQ_BROADCAST:
+        if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_RSP_BROADCAST; 
+            r_tgt_icache_req = true;
+            r_tgt_dcache_req = true;
+        }
+        break;
+
+    case TGT_REQ_DCACHE:
+        if ( !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_RSP_DCACHE; 
+            r_tgt_dcache_req = true;
+        }
+        break;
+
+    case TGT_RSP_BROADCAST:
+        if ( p_vci_tgt.rspack.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+        {
+            // one response
+            if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
+            {
+                r_vci_tgt_fsm = TGT_IDLE; 
+                r_tgt_icache_rsp = false;
+                r_tgt_dcache_rsp = false;
+            }
+
+            // if data and instruction have the inval line, need two responses  
+            if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
+            {
+                r_tgt_icache_rsp = false; // only reset one for respond the second time 
+            }
+        }
+        break;
+
+    case TGT_RSP_DCACHE:
+        if ( p_vci_tgt.rspack.read() && !r_tgt_dcache_req.read() ) 
+        {
+            r_vci_tgt_fsm = TGT_IDLE;
+            r_tgt_dcache_rsp = false; 
+        }
+        break;
+
+    } // end switch TGT_FSM
+
+    /////////////////////////////////////////////////////////////////////
+    // The ICACHE FSM controls the following ressources:
+    // - r_icache_fsm
+    // - r_icache_fsm_save
+    // - r_icache instruction cache access
+    // - r_icache_addr_save
+    // - r_icache_miss_req set
+    // - r_icache_unc_req set
+    // - r_icache_buf_unc_valid set
+    // - r_vci_rsp_ins_error reset
+    // - r_tgt_icache_req reset
+    // - ireq & irsp structures for communication with the processor
+    //
+    // 1/ External requests (update or invalidate) have highest priority.
+    //    They are taken into account in the IDLE and WAIT states.
+    //    As external hit should be extremly rare on the ICACHE,
+    //    all external requests are handled as invalidate...
+    //    In case of external request the ICACHE FSM goes to the CC_CHECK
+    //    state to test the external hit, and returns in the
+    //    pre-empted state after completion.
+    // 2/ Processor requests are taken into account only in the IDLE state.
+    //    In case of MISS, or in case of uncached instruction, the FSM 
+    //    writes the missing address line in the  r_icache_addr_save register 
+    //    and sets the r_icache_miss_req or the r_icache_unc_req flip-flops.
+    //    These request flip-flops are reset by the VCI_RSP FSM
+    //    when the VCI transaction is completed and the r_icache_buf_unc_valid
+    //    is set in case of uncached access.
+    //    In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 
+    //    flip-flop. It is reset by the ICACHE FSM.
+    ///////////////////////////////////////////////////////////////////////
+
+    typename iss_t::InstructionRequest  ireq = ISS_IREQ_INITIALIZER;
+    typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
+
+    typename iss_t::DataRequest  dreq = ISS_DREQ_INITIALIZER;
+    typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
+
+    m_iss.getRequests( ireq, dreq );
+
+#if DEBUG_CC_XCACHE_WRAPPER
+    std::cout << " Instruction Request: " << ireq << std::endl;
+#endif
+
+    switch(r_icache_fsm) {
+        /////////////////
+    case ICACHE_IDLE:
+        {
+            if ( r_tgt_icache_req ) {   // external request
+                if ( ireq.valid ) m_cost_ins_miss_frz++;
+                r_icache_fsm = ICACHE_CC_INVAL;
+                r_icache_fsm_save = r_icache_fsm;
+                break;
+            } 
+            if ( ireq.valid ) {
+                data_t  icache_ins = 0;
+                bool    icache_hit = false;
+                bool    icache_cached = m_cacheability_table[ireq.addr];
+                // icache_hit & icache_ins evaluation
+                if ( icache_cached ) {
+                    icache_hit = r_icache.read(ireq.addr, &icache_ins);
+                } else {
+                    icache_hit = ( r_icache_buf_unc_valid && (ireq.addr == r_icache_addr_save) );
+                    icache_ins = r_icache_miss_buf[0];
+                }
+                if ( ! icache_hit ) {
+                    m_cpt_ins_miss++;
+                    m_cost_ins_miss_frz++;
+                    r_icache_addr_save = ireq.addr;
+                    if ( icache_cached ) {
+                        r_icache_fsm = ICACHE_MISS_WAIT;
+                        r_icache_miss_req = true;
+                    } else {
+                        r_icache_fsm = ICACHE_UNC_WAIT;
+                        r_icache_unc_req = true;
+                    }
+                } else {
+                    r_icache_buf_unc_valid = false;
+                }
+                m_cpt_icache_dir_read += m_icache_ways;
+                m_cpt_icache_data_read += m_icache_ways;
+                irsp.valid          = icache_hit;
+                irsp.instruction    = icache_ins;
+            }
+            break;
+        }
+        //////////////////////
+    case ICACHE_MISS_WAIT:
+        {
+            m_cost_ins_miss_frz++;
+            if ( r_tgt_icache_req ) {   // external request
+                r_icache_fsm = ICACHE_CC_INVAL;
+                r_icache_fsm_save = r_icache_fsm;
+                break;
+            } 
+            if ( !r_icache_miss_req && !r_icache_inval_rsp ) { // Miss read response and no invalidation
+                if ( r_vci_rsp_ins_error ) {
+                    r_icache_fsm = ICACHE_ERROR;
+                } else {
+                    r_icache_fsm = ICACHE_MISS_UPDT;
+                }
+            }
+            if ( !r_icache_miss_req && r_icache_inval_rsp ) { // Miss read response and invalidation
+                if ( r_vci_rsp_ins_error ) {
+                    r_icache_inval_rsp = false;
+                    r_icache_fsm = ICACHE_ERROR;
+                } else {
+                    r_icache_inval_rsp = false;
+                    r_icache_fsm = ICACHE_IDLE;
+                }
+            }
+            break;
+        }
+        /////////////////////
+    case ICACHE_UNC_WAIT:
+        {
+            m_cost_ins_miss_frz++;
+            if ( r_tgt_icache_req ) {   // external request
+                r_icache_fsm = ICACHE_CC_INVAL;
+                r_icache_fsm_save = r_icache_fsm;
+                break;
+            } 
+            if ( !r_icache_unc_req ) {
+                if ( r_vci_rsp_ins_error ) {
+                    r_icache_fsm = ICACHE_ERROR;
+                } else {
+                    r_icache_fsm = ICACHE_IDLE;
+                    r_icache_buf_unc_valid = true;
+                }
+            }
+            break;
+        }
+        //////////////////
+    case ICACHE_ERROR:
+        {
+            r_icache_fsm = ICACHE_IDLE;
+            r_vci_rsp_ins_error = false;
+            irsp.error          = true;
+            irsp.valid          = true;
+            break;
+        }
+        //////////////////////
+    case ICACHE_MISS_UPDT: 
+        {
+            if ( r_tgt_icache_req ) {   // external request
+                r_icache_fsm = ICACHE_CC_INVAL;
+                r_icache_fsm_save = r_icache_fsm;
+                break;
+            } 
+            if(!r_icache_cleanup_req.read() && !r_icache_inval_rsp){
+                addr_t    ad  = r_icache_addr_save;
+                data_t*   buf = r_icache_miss_buf;
+                data_t    victim_index = 0;
+                m_cpt_icache_dir_write++;
+                m_cpt_icache_data_write++;
+                if ( ireq.valid ) m_cost_ins_miss_frz++;
+
+                r_icache_cleanup_req = r_icache.update(ad, buf, &victim_index);
+                r_icache_cleanup_line = victim_index;
+
+                r_icache_fsm        = ICACHE_IDLE;
+                break;
+            }
+            if(r_icache_inval_rsp){
+                if ( ireq.valid ) m_cost_ins_miss_frz++;
+                r_icache_inval_rsp  = false;
+                r_icache_fsm        = ICACHE_IDLE;
+                break;
+            }
+            if ( ireq.valid ) m_cost_ins_miss_frz++;
+        }
+        /////////////////////
+    case ICACHE_CC_INVAL:  
+        {                       
+            addr_t    ad  = r_tgt_addr;
+            if ( ireq.valid ) m_cost_ins_miss_frz++;
+            m_cpt_icache_dir_read += m_icache_ways;
+            if( (( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT )) && 
+                ((r_icache_addr_save.read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1))) ) {
+                r_icache_inval_rsp = true;
+            } else {
+                r_tgt_icache_rsp = r_icache.inval(ad);
+            }
+            r_tgt_icache_req = false;
+            r_icache_fsm = r_icache_fsm_save;
+            break;
+        }
+
+    } // end switch r_icache_fsm
+
+#if DEBUG_CC_XCACHE_WRAPPER
+    std::cout << " Instruction Response: " << irsp << std::endl;
+#endif
+
+    //////////////////////////////////////////////////////////////////////://///////////
+    // The DCACHE FSM controls the following ressources:
+    // - r_dcache_fsm
+    // - r_dcache_fsm_save
+    // - r_dcache (data cache access)
+    // - r_dcache_addr_save
+    // - r_dcache_wdata_save
+    // - r_dcache_rdata_save
+    // - r_dcache_type_save
+    // - r_dcache_be_save
+    // - r_dcache_cached_save
+    // - r_dcache_miss_req set
+    // - r_dcache_unc_req set
+    // - r_dcache_write_req set
+    // - r_dcache_cleanup_req set
+    // - r_vci_rsp_data_error reset
+    // - r_tgt_dcache_req reset
+    // - r_wbuf write
+    // - dreq & drsp structures for communication with the processor
+    //
+    // 1/ EXTERNAL REQUEST : 
+    //    There is an external request when the tgt_dcache req flip-flop is set,
+    //    requesting a line invalidation or a line update. 
+    //    External requests are taken into account in the states  IDLE, WRITE_REQ,  
+    //    UNC_WAIT, MISS_WAIT, and have the highest priority :
+    //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
+    //    goes to the CC_CHECK state to execute the requested action, and returns to the
+    //    pre-empted state.
+    //  2/ PROCESSOR REQUEST : 
+    //   In order to support VCI write burst, the processor requests are taken into account
+    //   in the WRITE_REQ state as well as in the IDLE state.
+    //   - In the IDLE state, the processor request cannot be satisfied if
+    //   there is a cached read miss, or an uncached read.
+    //   - In the WRITE_REQ state, the request cannot be satisfied if
+    //   there is a cached read miss, or an uncached read,
+    //   or when the write buffer is full.
+    //   - In all other states, the processor request is not satisfied.
+    //
+    //   The cache access takes into account the cacheability_table.
+    //   In case of processor request, there is five conditions to exit the IDLE state:
+    //   - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal), 
+    //     then to the MISS_UPDT state, and finally to the IDLE state.
+    //   - UNCACHED READ  => to the UNC_WAIT state (waiting the r_miss_ok signal), 
+    //     and to the IDLE state.
+    //   - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state.
+    //   - WRITE MISS => directly to the WRITE_REQ state to access the write buffer.
+    //   - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state.
+    //
+    // Error handling :  Read Bus Errors are synchronous events, but
+    // Write Bus Errors are asynchronous events (processor is not frozen).
+    // - If a Read Bus Error is detected, the VCI_RSP FSM sets the
+    //   r_vci_rsp_data_error flip-flop, and the synchronous error is signaled
+    //   by the DCACHE FSM.
+    // - If a Write Bus Error is detected, the VCI_RSP FSM  signals
+    //   the asynchronous error using the setWriteBerr() method.
+    ///////////////////////////////////////////////////////////////////////////////////
+
+#if DEBUG_CC_XCACHE_WRAPPER
+    std::cout << " Data Request: " << dreq << std::endl;
+#endif
+
+    //if( (m_cpt_total_cycles % 10000) ==0 ) std::cout << std::dec << "Proc " << m_srcid << " Data Request: " << dreq << std::endl;
+
+    switch ( r_dcache_fsm ) {
+
+        /////////////////////
+    case DCACHE_WRITE_REQ:
+        { 
+            if ( r_tgt_dcache_req ) {   // external request
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            }
+
+            // try to post the write request in the write buffer
+            if ( !r_dcache_write_req ) {    // no previous write transaction     
+                if ( r_wbuf.wok(r_dcache_addr_save) ) {   // write request in the same cache line 
+                    r_wbuf.write(r_dcache_addr_save, r_dcache_be_save, r_dcache_wdata_save);
+                    // close the write packet if uncached
+                    if ( !r_dcache_cached_save ) r_dcache_write_req = true ;
+                } else {    
+                    // close the write packet if write request not in the same cache line
+                    r_dcache_write_req = true;  
+                    m_cost_write_frz++;
+                    break;  // posting request not possible : stay in DCACHE_WRITEREQ state
+                }
+            } else {    //  previous write transaction not completed
+                m_cost_write_frz++;
+                break;  // posting request not possible : stay in DCACHE_WRITEREQ state  
+            }
+
+            // close the write packet if the next processor request is not a write 
+            if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE) ) r_dcache_write_req = true ;
+
+            // The next state and the processor request parameters are computed 
+            // as in the DCACHE_IDLE state (see below ...)
+        }
+        /////////////////
+    case DCACHE_IDLE:
+        {
+            if ( r_tgt_dcache_req ) {   // external request
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            } 
+
+            if ( dreq.valid ) {              
+                bool        dcache_hit     = false;
+                data_t      dcache_rdata   = 0;
+                bool        dcache_cached;
+                m_cpt_dcache_data_read += m_dcache_ways;
+                m_cpt_dcache_dir_read += m_dcache_ways;
+
+                // dcache_cached evaluation
+                switch (dreq.type) {
+                case iss_t::DATA_LL:
+                case iss_t::DATA_SC:
+                case iss_t::XTN_READ:
+                case iss_t::XTN_WRITE:
+                    dcache_cached = false;
+                    break;
+                default:
+                    dcache_cached = m_cacheability_table[dreq.addr];
+                }
+
+                // dcache_hit & dcache_rdata evaluation
+                if ( dcache_cached ) {
+                    dcache_hit = r_dcache.read(dreq.addr, &dcache_rdata);
+                } else {
+                    dcache_hit = ( !r_dcache_unc_req && (dreq.addr == r_dcache_addr_save) );
+                    dcache_rdata = r_dcache_miss_buf[0];
+                }
+
+                switch( dreq.type ) {
+                case iss_t::DATA_READ:
+                case iss_t::DATA_LL:
+                case iss_t::DATA_SC:
+                    m_cpt_read++;
+                    if ( dcache_hit ) {
+                        r_dcache_fsm = DCACHE_IDLE;
+                        drsp.valid = true;
+                        drsp.rdata = dcache_rdata;
+                        r_dcache_buf_unc_valid = false;
+                    } else {
+                        if ( dcache_cached ) {
+                            m_cpt_data_miss++;
+                            m_cost_data_miss_frz++;
+                            r_dcache_miss_req = true;
+                            r_dcache_fsm = DCACHE_MISS_WAIT;
+                        } else {
+                            m_cpt_unc_read++;
+                            m_cost_unc_read_frz++;
+                            r_dcache_unc_req = true;
+                            r_dcache_fsm = DCACHE_UNC_WAIT;
+                        }
+                    }
+                    break;
+                case iss_t::XTN_READ:
+                case iss_t::XTN_WRITE:
+                    // only DCACHE INVALIDATE request are supported
+                    if ( dreq.addr/4 == iss_t::XTN_DCACHE_INVAL )
+                        r_dcache_fsm = DCACHE_INVAL;
+                    drsp.valid = true;
+                    drsp.rdata = 0;
+                    break;
+                case iss_t::DATA_WRITE:
+                    m_cpt_write++;
+                    if ( dcache_hit && dcache_cached ) {
+                        r_dcache_fsm = DCACHE_WRITE_UPDT;
+                        m_cpt_write_cached++;
+                    } else {
+                        r_dcache_fsm = DCACHE_WRITE_REQ;
+                    }
+                    drsp.valid = true;
+                    drsp.rdata = 0;
+                    break;
+                } // end switch dreq.type
+
+                r_dcache_addr_save      = dreq.addr;
+                r_dcache_type_save      = dreq.type;
+                r_dcache_wdata_save     = dreq.wdata;
+                r_dcache_be_save        = dreq.be;
+                r_dcache_rdata_save     = dcache_rdata;
+                r_dcache_cached_save    = dcache_cached;
+
+            } else {    // end if dreq.valid
+                r_dcache_fsm = DCACHE_IDLE;
+            }
+            // processor request are not accepted in the WRITE_REQUEST state
+            // when the write buffer is not writeable
+            if ( (r_dcache_fsm == DCACHE_WRITE_REQ) &&
+                 (r_dcache_write_req || !r_wbuf.wok(r_dcache_addr_save)) ) {
+                drsp.valid = false;
+                drsp.rdata = 0;
+            }
+            break;
+        }
+        ///////////////////////
+    case DCACHE_WRITE_UPDT:
+        {
+            m_cpt_dcache_data_write++;
+            data_t mask = vci_param::be2mask(r_dcache_be_save);
+            data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
+            r_dcache.write(r_dcache_addr_save, wdata);
+            r_dcache_fsm = DCACHE_WRITE_REQ;
+            break;
+        }
+        //////////////////////
+    case DCACHE_MISS_WAIT:
+        {
+            if ( dreq.valid ) m_cost_data_miss_frz++;
+            if ( r_tgt_dcache_req.read() ) {   // external request
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            }
+            if ( !r_dcache_miss_req && !r_dcache_inval_rsp ) { // Miss read response and no invalidation
+                if ( r_vci_rsp_data_error ) {
+                    r_dcache_fsm = DCACHE_ERROR;
+                } else {
+                    r_dcache_fsm = DCACHE_MISS_UPDT;
+                }
+                break;
+            }
+            if ( !r_dcache_miss_req && r_dcache_inval_rsp ) { // Miss read response and invalidation
+                if ( r_vci_rsp_data_error ) {
+                    r_dcache_inval_rsp  = false;
+                    r_dcache_fsm = DCACHE_ERROR;
+                } else {
+                    r_dcache_inval_rsp  = false;
+                    r_dcache_fsm = DCACHE_IDLE;
+                }
+                break;
+            }
+            break;
+        }
+        //////////////////////
+    case DCACHE_MISS_UPDT:
+        {
+            if ( r_tgt_dcache_req.read() ) {   // external request
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            }
+            if( !r_dcache_cleanup_req.read() && !r_dcache_inval_rsp ){
+                addr_t  ad  = r_dcache_addr_save;
+                data_t* buf = new data_t[m_dcache_words];
+                for(size_t i=0; i<m_dcache_words; i++) {
+                    buf[i] = r_dcache_miss_buf[i];
+                }
+                data_t  victim_index = 0;
+                if ( dreq.valid ) m_cost_data_miss_frz++;
+                m_cpt_dcache_data_write++;
+                m_cpt_dcache_dir_write++;
+
+                r_dcache_cleanup_req = r_dcache.update(ad, buf, &victim_index);
+                r_dcache_cleanup_line = victim_index;
+            
+                r_dcache_fsm = DCACHE_IDLE;
+                delete [] buf;
+                break;
+            }
+            if( r_dcache_inval_rsp ){
+                r_dcache_inval_rsp  = false;
+                r_dcache_fsm = DCACHE_IDLE;
+                break;
+            }
+            break;
+        }
+        ////////////////////
+    case DCACHE_UNC_WAIT:
+        {
+            if ( dreq.valid ) m_cost_unc_read_frz++;
+            if ( r_tgt_dcache_req ) {   // external request
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            } 
+            if ( !r_dcache_unc_req ) {
+                if ( r_vci_rsp_data_error ) {
+                    r_dcache_fsm = DCACHE_ERROR;
+                } else {
+                    r_dcache_fsm = DCACHE_IDLE;
+	                // If request was a DATA_SC we need to invalidate the corresponding cache line,
+	                // so that subsequent access to this line are read from RAM
+	                if (dreq.type == iss_t::DATA_SC) {
+	                    r_dcache_fsm = DCACHE_INVAL;
+	                    r_dcache_wdata_save = r_dcache_addr_save;
+	                }
+                    r_dcache_buf_unc_valid = true;
+                }
+            }
+            break;
+        }
+        //////////////////
+    case DCACHE_ERROR:
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            r_vci_rsp_data_error = false;
+            drsp.error = true;
+            drsp.valid = true;
+            break;
+        }
+        /////////////////    
+    case DCACHE_INVAL:
+        {
+            m_cpt_dcache_dir_read += m_dcache_ways;
+            r_dcache.inval(r_dcache_addr_save);
+            r_dcache_fsm = DCACHE_IDLE;
+            break;
+        }
+        /////////////////////
+    case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
+        {
+            m_cpt_dcache_dir_read += m_dcache_ways;
+            m_cpt_dcache_data_read += m_dcache_ways;
+            addr_t  ad           = r_tgt_addr;
+            data_t  dcache_rdata = 0;
+
+            if(( ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) && 
+               ( (r_dcache_addr_save.read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) {
+                r_dcache_inval_rsp = true;
+                r_tgt_dcache_req = false;
+                r_dcache_fsm = r_dcache_fsm_save;
+            } else {
+                bool    dcache_hit   = r_dcache.read(ad, &dcache_rdata);
+                if ( dcache_hit && r_tgt_update ) {
+                    r_dcache_fsm = DCACHE_CC_UPDT;
+                    // complete the line buffer in case of update
+                    for ( size_t word = 0 ; word < m_dcache_words ; word++ ) {
+                        if ( !r_tgt_val[word] ) {
+                            addr_t  ad = r_tgt_addr + (addr_t)word;
+                            r_dcache.read(ad, &dcache_rdata);
+                            r_tgt_buf[word] = dcache_rdata;
+                        }
+                    }
+                } else if ( dcache_hit && !r_tgt_update ) {
+                    r_dcache_fsm = DCACHE_CC_INVAL;
+                } else {
+                    r_dcache_fsm = DCACHE_CC_NOP;
+                }
+            }
+            break;
+        }
+        ///////////////////
+    case DCACHE_CC_UPDT:    // update directory and data cache        
+        {
+            m_cpt_dcache_dir_write++;
+            m_cpt_dcache_data_write++;
+            addr_t  ad      = r_tgt_addr;
+            data_t* buf     = r_tgt_buf;
+            for(size_t i=0; i<m_dcache_words; i++){
+                if(r_tgt_val[i]) r_dcache.write( ad + i*4, buf[i]);
+            }
+            r_tgt_dcache_req = false;
+            r_dcache_fsm = r_dcache_fsm_save;
+            break;
+        }
+        /////////////////////
+    case DCACHE_CC_INVAL:   // invalidate a cache line
+        {
+            addr_t  ad      = r_tgt_addr;
+            r_tgt_dcache_rsp = r_dcache.inval(ad);
+            r_tgt_dcache_req = false;
+            r_dcache_fsm = r_dcache_fsm_save;
+            break;
+        }
+        ///////////////////
+    case DCACHE_CC_NOP:     // no external hit
+        {
+            r_tgt_dcache_req = false;
+            r_dcache_fsm = r_dcache_fsm_save;
+            break;
+        }    
+    } // end switch r_dcache_fsm
+
+#if DEBUG_CC_XCACHE_WRAPPER
+    std::cout << " Data Response: " << drsp << std::endl;
+#endif
+
+    /////////// execute one iss cycle /////////////////////////////////////////////
+    {
+        uint32_t it = 0;
+        for (size_t i=0; i<(size_t)iss_t::n_irq; i++) 
+            if(p_irq[i].read()) it |= (1<<i);
+        m_iss.executeNCycles(1, irsp, drsp, it);
+    }
+
+    if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) ) m_cpt_frz_cycles++;
+    
+
+    ////////////////////////////////////////////////////////////////////////////
+    // The VCI_CMD FSM controls the following ressources:
+    // - r_vci_cmd_fsm
+    // - r_vci_cmd_min
+    // - r_vci_cmd_max
+    // - r_vci_cmd_cpt
+    // - wbuf reset
+    //
+    // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
+    // There is 7 request types, with the following priorities : 
+    // 1 - Instruction Miss     : r_icache_miss_req
+    // 2 - Data Write           : r_dcache_write_req
+    // 3 - Data Read Miss       : r_dcache_miss_req 
+    // 4 - Data Read Uncached   : r_dcache_unc_req 
+    // 5 - Instruction Cleanup  : r_icache_cleanup_req 
+    // 6 - Data Cleanup         : r_dcache_cleanup_req 
+    // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM 
+    // and RSP_FSM exit simultaneously the IDLE state.
+    //
+    // VCI formats:
+    // According to the VCI advanced specification, all read requests packets 
+    // (read Uncached, Miss data, Miss instruction) are one word packets.
+    // For write burst packets, all words must be in the same cache line,
+    // and addresses must be contiguous (the BE field is 0 in case of "holes").
+    //////////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_cmd_fsm) {
+    
+    case CMD_IDLE:
+        if (r_vci_rsp_fsm != RSP_IDLE) break;
+
+        r_vci_cmd_cpt = 0;
+        if ( r_icache_miss_req ) { 
+            r_vci_cmd_fsm = CMD_INS_MISS; 
+            m_cpt_imiss_transaction++;
+        } else if ( r_icache_unc_req ) { 
+            r_vci_cmd_fsm = CMD_INS_UNC; 
+            m_cpt_imiss_transaction++;
+        } else if ( r_dcache_write_req ) { 
+            r_vci_cmd_fsm = CMD_DATA_WRITE;
+            r_vci_cmd_cpt = r_wbuf.getMin();
+            r_vci_cmd_min = r_wbuf.getMin();
+            r_vci_cmd_max = r_wbuf.getMax(); 
+            m_cpt_write_transaction++; 
+            m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1); 
+        } else if ( r_dcache_miss_req ) { 
+            r_vci_cmd_fsm = CMD_DATA_MISS;
+            m_cpt_dmiss_transaction++; 
+        } else if ( r_dcache_unc_req ) { 
+            r_vci_cmd_fsm = CMD_DATA_UNC;
+            m_cpt_unc_transaction++; 
+        } else if ( r_icache_cleanup_req ) { 
+            r_vci_cmd_fsm = CMD_INS_CLEANUP; 
+        } else if ( r_dcache_cleanup_req ) { 
+            r_vci_cmd_fsm = CMD_DATA_CLEANUP;
+        }
+        break;
+            
+    case CMD_DATA_WRITE:
+        if ( p_vci_ini.cmdack.read() ) {
+            r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
+            if (r_vci_cmd_cpt == r_vci_cmd_max) {
+                r_vci_cmd_fsm = CMD_IDLE ;
+                r_wbuf.reset() ;
+            }
+        }
+        break;
+
+    case CMD_INS_MISS:
+    case CMD_INS_UNC:
+    case CMD_DATA_MISS:
+    case CMD_DATA_UNC:
+    case CMD_INS_CLEANUP:
+    case CMD_DATA_CLEANUP:
+        if ( p_vci_ini.cmdack.read() ) {
+            r_vci_cmd_fsm = CMD_IDLE;
+        }
+        break;
+
+    } // end  switch r_vci_cmd_fsm
+
+    //////////////////////////////////////////////////////////////////////////
+    // The VCI_RSP FSM controls the following ressources:
+    // - r_vci_rsp_fsm:
+    // - r_icache_miss_buf[m_icache_words]
+    // - r_dcache_miss_buf[m_dcache_words]
+    // - r_icache_miss_req reset
+    // - r_icache_unc_req reset
+    // - r_dcache_miss_req reset
+    // - r_icache_cleanup_req reset
+    // - r_dcache_cleanup_req reset
+    // - r_vci_rsp_data_error set
+    // - r_vci_rsp_ins_error set
+    // - r_vci_rsp_cpt
+    // In order to have only one active VCI transaction, this VCI_RSP_FSM 
+    // is synchronized with the VCI_CMD FSM, and both FSMs exit the
+    // IDLE state simultaneously.
+    // 
+    // VCI formats:
+    // This component accepts single word or multi-word response packets for
+    // write response packets. 
+    //
+    // Error handling:
+    // This FSM analyzes the VCI error code and signals directly the
+    // Write Bus Error. 
+    // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error 
+    // flip_flop and the error is signaled by the DCACHE FSM.  
+    // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 
+    // flip_flop and the error is signaled by the DCACHE FSM.  
+    // In case of Cleanup Error, the simulation stops with an error message...
+    //////////////////////////////////////////////////////////////////////////
+
+    switch (r_vci_rsp_fsm) {
+
+    case RSP_IDLE:
+        if(p_vci_ini.rspval.read())
+            {
+                std::cout << "CC_XCache " << m_srcid << " Unexpected response" << std::endl;
+            }
+        assert( ! p_vci_ini.rspval.read() && "Unexpected response" );
+        if (r_vci_cmd_fsm != CMD_IDLE) break;
+
+        r_vci_rsp_cpt = 0;
+        if      ( r_icache_miss_req )       r_vci_rsp_fsm = RSP_INS_MISS;
+        else if ( r_icache_unc_req )        r_vci_rsp_fsm = RSP_DATA_WRITE;
+        else if ( r_dcache_write_req )      r_vci_rsp_fsm = RSP_DATA_WRITE;
+        else if ( r_dcache_miss_req )       r_vci_rsp_fsm = RSP_DATA_MISS;
+        else if ( r_dcache_unc_req )        r_vci_rsp_fsm = RSP_DATA_UNC;
+        else if ( r_icache_cleanup_req )    r_vci_rsp_fsm = RSP_INS_CLEANUP;
+        else if ( r_dcache_cleanup_req )    r_vci_rsp_fsm = RSP_DATA_CLEANUP;
+        break;
+
+    case RSP_INS_MISS:
+        m_cost_imiss_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+        assert( (r_vci_rsp_cpt < m_icache_words) &&
+                "The VCI response packet for instruction miss is too long" );
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini.rdata.read();
+
+        if ( p_vci_ini.reop.read() ) {
+            assert( (r_vci_rsp_cpt == m_icache_words - 1) &&
+                    "The VCI response packet for instruction miss is too short");
+            r_icache_miss_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        }
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+        break;
+
+    case RSP_INS_UNC:
+        m_cost_imiss_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for uncached instruction");
+        r_icache_miss_buf[0] = (data_t)p_vci_ini.rdata.read();
+        r_vci_rsp_fsm = RSP_IDLE;
+        r_icache_unc_req = false;
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+        break;
+
+    case RSP_DATA_MISS:
+        m_cost_dmiss_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+        assert(r_vci_rsp_cpt != m_dcache_words &&
+               "illegal VCI response packet for data read miss");
+        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini.rdata.read();
+        if ( p_vci_ini.reop.read() ) {
+            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                   "illegal VCI response packet for data read miss");
+            r_dcache_miss_req = false;
+            r_vci_rsp_fsm = RSP_IDLE;
+        }
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+        break;
+
+    case RSP_DATA_WRITE:
+        m_cost_write_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+        if ( p_vci_ini.reop.read() ) {
+            r_vci_rsp_fsm = RSP_IDLE;
+            r_dcache_write_req = false;
+        }
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) m_iss.setWriteBerr();
+        break;
+
+    case RSP_DATA_UNC:
+        m_cost_unc_transaction++;
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+        assert(p_vci_ini.reop.read() &&
+               "illegal VCI response packet for data read uncached");
+        r_dcache_miss_buf[0] = (data_t)p_vci_ini.rdata.read();
+        r_vci_rsp_fsm = RSP_IDLE;
+        r_dcache_unc_req = false;
+        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+        break;
+
+    case RSP_INS_CLEANUP:
+    case RSP_DATA_CLEANUP:
+        if ( ! p_vci_ini.rspval.read() )
+            break;
+        assert( p_vci_ini.reop.read() &&
+                "illegal VCI response packet for icache cleanup");
+        assert( (p_vci_ini.rerror.read() == vci_param::ERR_NORMAL) &&
+                "error in response packet for icache cleanup");
+        if ( r_vci_rsp_fsm == RSP_INS_CLEANUP ) r_icache_cleanup_req = false;
+        else                                    r_dcache_cleanup_req = false;
+        r_vci_rsp_fsm = RSP_IDLE;
+        break;
+        
+    } // end switch r_vci_rsp_fsm
+
+} // end transition()
+
+//////////////////////////////////////////////////////////////////////////////////
+tmpl(void)::genMoore()
+           //////////////////////////////////////////////////////////////////////////////////
+{
+    // VCI initiator response
+
+    p_vci_ini.rspack = true;
+
+    // VCI initiator command
+
+    switch (r_vci_cmd_fsm.read() ) {
+
+    case CMD_IDLE:
+        p_vci_ini.cmdval  = false;
+        p_vci_ini.address = 0;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0;
+        p_vci_ini.plen    = 0;
+        p_vci_ini.cmd     = vci_param::CMD_NOP;
+        p_vci_ini.trdid   = 0;
+        p_vci_ini.pktid   = 0;
+        p_vci_ini.srcid   = 0;
+        p_vci_ini.cons    = false;
+        p_vci_ini.wrap    = false;
+        p_vci_ini.contig  = false;
+        p_vci_ini.clen    = 0;
+        p_vci_ini.cfixed  = false;
+        p_vci_ini.eop     = false;
+        break;
+
+    case CMD_DATA_UNC:
+        p_vci_ini.cmdval = true;
+        p_vci_ini.address = r_dcache_addr_save & ~0x3;
+        switch( r_dcache_type_save ) {
+        case iss_t::DATA_READ:
+            p_vci_ini.wdata = 0;
+            p_vci_ini.be  = r_dcache_be_save.read();
+            p_vci_ini.cmd = vci_param::CMD_READ;
+            break;
+        case iss_t::DATA_LL:
+            p_vci_ini.wdata = 0;
+            p_vci_ini.be  = 0xF;
+            p_vci_ini.cmd = vci_param::CMD_LOCKED_READ;
+            break;
+        case iss_t::DATA_SC:
+            p_vci_ini.wdata = r_dcache_wdata_save.read();
+            p_vci_ini.be  = 0xF;
+            p_vci_ini.cmd = vci_param::CMD_STORE_COND;
+            break;
+        default:
+            assert("this should not happen");
+        }
+        p_vci_ini.plen = 4;
+        p_vci_ini.trdid  = 0;   // data cache uncached read
+        p_vci_ini.pktid  = 0;
+        p_vci_ini.srcid  = m_srcid;
+        p_vci_ini.cons   = false;
+        p_vci_ini.wrap   = false;
+        p_vci_ini.contig = true;
+        p_vci_ini.clen   = 0;
+        p_vci_ini.cfixed = false;
+        p_vci_ini.eop    = true;
+        break;
+
+    case CMD_DATA_WRITE:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = r_wbuf.getAddress(r_vci_cmd_cpt);
+        p_vci_ini.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
+        p_vci_ini.be      = r_wbuf.getBe(r_vci_cmd_cpt);
+        p_vci_ini.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
+        p_vci_ini.cmd     = vci_param::CMD_WRITE;
+        p_vci_ini.trdid   = 0;  // data cache write
+        p_vci_ini.pktid   = 0;
+        p_vci_ini.srcid   = m_srcid;
+        p_vci_ini.cons    = false;
+        p_vci_ini.wrap    = false;
+        p_vci_ini.contig  = true;
+        p_vci_ini.clen    = 0;
+        p_vci_ini.cfixed  = false;
+        p_vci_ini.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
+        break;
+
+    case CMD_DATA_MISS:
+        p_vci_ini.cmdval = true;
+        p_vci_ini.address = r_dcache_addr_save & m_dcache_yzmask;
+        p_vci_ini.be     = 0xF;
+        p_vci_ini.plen   = m_dcache_words << 2;
+        p_vci_ini.cmd    = vci_param::CMD_READ;
+        p_vci_ini.trdid  = 1;   // data cache cached read
+        p_vci_ini.pktid  = 0;
+        p_vci_ini.srcid  = m_srcid;
+        p_vci_ini.cons   = false;
+        p_vci_ini.wrap   = false;
+        p_vci_ini.contig = true;
+        p_vci_ini.clen   = 0;
+        p_vci_ini.cfixed = false;
+        p_vci_ini.eop = true;
+        break;
+
+    case CMD_INS_MISS:
+        p_vci_ini.cmdval = true;
+        p_vci_ini.address = r_icache_addr_save & m_icache_yzmask;
+        p_vci_ini.be     = 0xF;
+        p_vci_ini.plen   = m_icache_words << 2;
+        p_vci_ini.cmd    = vci_param::CMD_READ;
+        p_vci_ini.trdid  = 3;   // ins cache cached read
+        p_vci_ini.pktid  = 0;
+        p_vci_ini.srcid  = m_srcid;
+        p_vci_ini.cons   = false;
+        p_vci_ini.wrap   = false;
+        p_vci_ini.contig = true;
+        p_vci_ini.clen   = 0;
+        p_vci_ini.cfixed = false;
+        p_vci_ini.eop = true;
+        break;
+
+    case CMD_INS_UNC:
+        p_vci_ini.cmdval = true;
+        p_vci_ini.address = r_icache_addr_save & ~0x3;
+        p_vci_ini.be     = 0xF;
+        p_vci_ini.plen   = 4;
+        p_vci_ini.cmd    = vci_param::CMD_READ;
+        p_vci_ini.trdid  = 2;   // ins cache uncached read
+        p_vci_ini.pktid  = 0;
+        p_vci_ini.srcid  = m_srcid;
+        p_vci_ini.cons   = false;
+        p_vci_ini.wrap   = false;
+        p_vci_ini.contig = true;
+        p_vci_ini.clen   = 0;
+        p_vci_ini.cfixed = false;
+        p_vci_ini.eop = true;
+        break;
+
+    case CMD_INS_CLEANUP:
+    case CMD_DATA_CLEANUP:
+        p_vci_ini.cmdval = true;
+        if ( r_vci_cmd_fsm == CMD_INS_CLEANUP ) p_vci_ini.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
+        else                                    p_vci_ini.address = r_dcache_cleanup_line.read() * (m_icache_words<<2);
+        p_vci_ini.wdata  = 0;
+        p_vci_ini.be     = 0;
+        p_vci_ini.plen   = 4;
+        p_vci_ini.cmd    = vci_param::CMD_WRITE;
+        p_vci_ini.trdid  = 1; // cleanup for distinguish from a write
+        p_vci_ini.pktid  = 0;
+        p_vci_ini.srcid  = m_srcid;
+        p_vci_ini.cons   = false;
+        p_vci_ini.wrap   = false;
+        p_vci_ini.contig = false;
+        p_vci_ini.clen   = 0;
+        p_vci_ini.cfixed = false;
+        p_vci_ini.eop = true;
+        break;
+
+    } // end switch r_vci_cmd_fsm
+
+    // VCI_TGT
+
+    switch ( r_vci_tgt_fsm.read() ) {
+
+    case TGT_IDLE:
+    case TGT_UPDT_WORD:
+    case TGT_UPDT_DATA:
+        p_vci_tgt.cmdack  = true;
+        p_vci_tgt.rspval  = false;
+        break;
+
+    case TGT_RSP_BROADCAST:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
+        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+        p_vci_tgt.rpktid  = r_tgt_pktid.read();
+        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = true;
+        break;
+
+    case TGT_RSP_DCACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = !r_tgt_dcache_req.read();
+        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+        p_vci_tgt.rpktid  = r_tgt_pktid.read();
+        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = true;
+        break;
+
+    case TGT_REQ_BROADCAST:
+    case TGT_REQ_DCACHE:
+        p_vci_tgt.cmdack  = false;
+        p_vci_tgt.rspval  = false;
+        break;
+
+    } // end switch TGT_FSM
+} // end genMoore()
+
+}} // end namespace
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
+
Index: trunk/modules/vci_cc_xcache_wrapper_multi/caba/metadata/vci_cc_xcache_wrapper_multi.sd
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_multi/caba/metadata/vci_cc_xcache_wrapper_multi.sd	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper_multi/caba/metadata/vci_cc_xcache_wrapper_multi.sd	(revision 2)
@@ -0,0 +1,57 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_cc_xcache_wrapper_multi',
+	classname = 'soclib::caba::VciCcXCacheWrapperMulti',
+	tmpl_parameters = [
+		parameter.Module('vci_param', default = 'caba:vci_param'),
+		parameter.Module('iss_t'),
+		],
+	header_files = [
+		'../source/include/vci_cc_xcache_wrapper_multi.h',
+		],
+	implementation_files = [
+		'../source/src/vci_cc_xcache_wrapper_multi.cpp',
+		],
+	uses = [
+		Uses('caba:base_module'),
+		Uses('common:mapping_table'),
+		Uses('common:iss2'),
+		Uses('caba:multi_write_buffer'),
+		Uses('caba:generic_cache', addr_t = 'uint32_t'),
+		],
+	ports = [
+		Port('caba:vci_initiator', 'p_vci_ini_d'),
+    Port('caba:vci_initiator', 'p_vci_ini_c'),
+		Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:bit_in', 'p_irq', parameter.Constant('n_irq')),
+		Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+		Port('caba:clock_in', 'p_clk', auto = 'clock'),
+		],
+	instance_parameters = [
+		parameter.Int('proc_id'),
+		parameter.Module('mtp', 'common:mapping_table'),
+		parameter.Module('mtc', 'common:mapping_table'),
+		parameter.IntTab('initiator_rw_index'),
+		parameter.IntTab('initiator_c_index'),
+		parameter.IntTab('target_index'),
+		parameter.Int('icache_ways'),
+		parameter.Int('icache_sets'),
+		parameter.Int('icache_words'),
+		parameter.Int('dcache_ways'),
+		parameter.Int('dcache_sets'),
+		parameter.Int('dcache_words'),
+		parameter.Int('wbuf_nwords'),
+		parameter.Int('wbuf_nlines'),
+		],
+	   extensions = [
+		'dsx:get_ident=initiator_index:p_vci_ini_rw',
+		'dsx:cpu=wrapper:iss_t',
+		'dsx:mapping_type=processor:proc_id',
+		],
+)
+
+
Index: trunk/modules/vci_cc_xcache_wrapper_multi/caba/source/include/vci_cc_xcache_wrapper_multi.h
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_multi/caba/source/include/vci_cc_xcache_wrapper_multi.h	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper_multi/caba/source/include/vci_cc_xcache_wrapper_multi.h	(revision 2)
@@ -0,0 +1,310 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain
+ */
+ 
+#ifndef SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_MULTI_H
+#define SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_MULTI_H
+
+#include <inttypes.h>
+#include <systemc>
+#include "caba_base_module.h"
+#include "multi_write_buffer.h"
+#include "generic_cache.h"
+#include "vci_initiator.h"
+#include "vci_target.h"
+#include "mapping_table.h"
+#include "static_assert.h"
+
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+////////////////////////////////////////////
+template<typename vci_param, typename iss_t>
+class VciCcXCacheWrapperMulti
+///////////////////////////////////////////
+    : public soclib::caba::BaseModule
+{
+    typedef 		uint32_t    		data_t;
+    typedef 		uint32_t    		be_t;
+    typedef typename 	vci_param::fast_addr_t 	addr_t;
+
+    enum dcache_fsm_state_e {
+        DCACHE_IDLE,
+        DCACHE_WRITE_UPDT,
+        DCACHE_WRITE_REQ,
+        DCACHE_MISS_SELECT,
+        DCACHE_MISS_CLEANUP,
+        DCACHE_MISS_WAIT,
+        DCACHE_MISS_UPDT,
+        DCACHE_UNC_WAIT,
+        DCACHE_INVAL,
+        DCACHE_SYNC,
+        DCACHE_ERROR,
+        DCACHE_CC_CHECK,
+        DCACHE_CC_INVAL,
+        DCACHE_CC_UPDT,
+    };
+
+    enum icache_fsm_state_e {
+        ICACHE_IDLE,
+        ICACHE_MISS_SELECT,
+        ICACHE_MISS_CLEANUP,
+        ICACHE_MISS_WAIT,
+        ICACHE_MISS_UPDT,
+        ICACHE_UNC_WAIT,
+        ICACHE_ERROR,
+        ICACHE_CC_CHECK,
+        ICACHE_CC_INVAL,
+        ICACHE_CC_UPDT,
+    };
+
+    enum cmd_fsm_state_e {
+        CMD_IDLE,
+        CMD_INS_MISS,
+        CMD_INS_UNC,
+        CMD_DATA_MISS,
+        CMD_DATA_UNC,
+        CMD_DATA_WRITE,
+    };
+
+    enum rsp_fsm_state_e {
+        RSP_IDLE,
+        RSP_INS_MISS,
+        RSP_INS_UNC,
+        RSP_DATA_MISS,
+        RSP_DATA_UNC,
+        RSP_DATA_WRITE,
+    };
+
+    enum tgt_fsm_state_e {
+        TGT_IDLE,
+        TGT_UPDT_WORD,
+        TGT_UPDT_DATA,
+        TGT_REQ_BROADCAST,
+        TGT_REQ_ICACHE,
+        TGT_REQ_DCACHE,
+        TGT_RSP_BROADCAST,
+        TGT_RSP_ICACHE,
+        TGT_RSP_DCACHE,
+    };
+
+    enum cleanup_fsm_state_e {
+        CLEANUP_CMD,
+        CLEANUP_DCACHE_RSP,
+        CLEANUP_ICACHE_RSP,
+    };
+
+    enum transaction_type_e {
+        TYPE_DATA_UNC = 0,
+        TYPE_DATA_MISS = 1,
+        TYPE_INS_UNC = 2,
+        TYPE_INS_MISS = 3,
+    };
+
+public:
+
+    // PORTS
+    sc_in<bool>                             p_clk;
+    sc_in<bool>                             p_resetn;
+    sc_in<bool>                             p_irq[iss_t::n_irq];
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_d;
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_c;
+    soclib::caba::VciTarget<vci_param>      p_vci_tgt_c;
+
+private:
+
+    // STRUCTURAL PARAMETERS
+    const soclib::common::AddressDecodingTable<addr_t, bool>    	m_cacheability_table;
+    const soclib::common::Segment                                   	m_segment;
+    iss_t               						m_iss;
+    const uint32_t      						m_srcid_d;   
+    const uint32_t      						m_srcid_c;   
+   
+    const size_t                                m_wbuf_nlines; 
+    const size_t        						m_dcache_ways;
+    const size_t        						m_dcache_words;
+    const size_t        						m_dcache_yzmask;
+    const size_t        						m_icache_ways;
+    const size_t        						m_icache_words;
+    const size_t        						m_icache_yzmask;
+
+    // REGISTERS
+    sc_signal<int>          r_dcache_fsm;		// controls the data cache interface
+    sc_signal<int>          r_dcache_fsm_save;
+    sc_signal<addr_t>       r_dcache_addr_save;
+    sc_signal<data_t>       r_dcache_wdata_save;
+    sc_signal<data_t>       r_dcache_rdata_save;
+    sc_signal<int>          r_dcache_type_save;
+    sc_signal<be_t>         r_dcache_be_save;
+    sc_signal<addr_t>       r_dcache_cleanup_save;	// victim line index for cleanup
+    sc_signal<size_t>       r_dcache_way_save;		// selected slot for the replacement
+    sc_signal<bool>         r_dcache_cleanup_req;	// send a cleanup request to CLEANUP FSM
+    sc_signal<addr_t>       r_dcache_cleanup_line;	// define the victim line index
+    sc_signal<bool>         r_dcache_miss_req;          // send a miss request to CMD FSM
+    sc_signal<bool>         r_dcache_unc_req;		// send a uncached request to CMD FSM
+    sc_signal<bool>         r_dcache_inval_pending;	// external inval or update request pending
+
+    sc_signal<int>          r_icache_fsm;		// controls the instruction cache interface
+    sc_signal<int>          r_icache_fsm_save;
+    sc_signal<addr_t>       r_icache_addr_save;
+    sc_signal<addr_t>       r_icache_cleanup_save;	// victim line index for cleanup
+    sc_signal<size_t>       r_icache_way_save;		// selected slot for the replacement
+    sc_signal<bool>         r_icache_miss_req;          // send a miss request to to CMD FSM
+    sc_signal<bool>         r_icache_unc_req;		// send an uncached request to CMD FSM
+    sc_signal<bool>         r_icache_cleanup_req;	// send a cleanup request to CLEANUP FSM
+    sc_signal<addr_t>       r_icache_cleanup_line;      // define the victim line index
+    sc_signal<bool>         r_icache_inval_pending;	// external inval or update request pending
+
+    sc_signal<int>          r_cmd_fsm;			// controls the command on the direct network
+    sc_signal<size_t>       r_cmd_min;       
+    sc_signal<size_t>       r_cmd_max;       
+    sc_signal<size_t>       r_cmd_cpt;       
+      
+    sc_signal<int>          r_rsp_fsm;			// controls the response on the direct network
+    sc_signal<bool>         r_rsp_ins_error;    	// signals an error to the ICACHE FSM
+    sc_signal<bool>         r_rsp_data_error;    	// signals an error to the DCACHE FSM
+    sc_signal<size_t>       r_rsp_cpt;  
+    sc_signal<bool>         r_rsp_ins_ok;		// signals an available data to the ICACHE FSM
+    sc_signal<bool>         r_rsp_data_ok;		// signals an available data to the DCACHE FSM;
+
+    data_t                  *r_icache_miss_buf;    
+    data_t                  *r_dcache_miss_buf;    
+
+    data_t                  *r_tgt_buf;
+    bool                    *r_tgt_val;
+
+    sc_signal<int>          r_tgt_fsm;			// controls the target port of the coherence network
+    sc_signal<addr_t>       r_tgt_addr;
+    sc_signal<size_t>       r_tgt_word;
+    sc_signal<bool>         r_tgt_update;
+    sc_signal<bool>         r_tgt_data;
+    sc_signal<bool>         r_tgt_brdcast;
+    sc_signal<size_t>       r_tgt_srcid;
+    sc_signal<size_t>       r_tgt_pktid;
+    sc_signal<size_t>       r_tgt_trdid;
+    sc_signal<size_t>       r_tgt_plen;
+    sc_signal<bool>         r_tgt_icache_req;		// coherence request from TGT FSM to ICACHE FSM
+    sc_signal<bool>         r_tgt_dcache_req;		// coherence request from TGT FSM to DCACHE FSM
+    sc_signal<bool>         r_tgt_icache_rsp;   	// response from ICACHE FSM to TGT FSM : true == hit
+    sc_signal<bool>         r_tgt_dcache_rsp;   	// response from DCACHE FSM to TGT FSM : true == hit
+
+    sc_signal<int>          r_cleanup_fsm;		// controls initiator port of the coherence network
+
+    MultiWriteBuffer<addr_t>	r_wbuf;
+    GenericCache<addr_t>    	r_icache;
+    GenericCache<addr_t>    	r_dcache;
+
+    // Activity counters
+    uint32_t m_cpt_dcache_data_read;        // DCACHE DATA READ
+    uint32_t m_cpt_dcache_data_write;       // DCACHE DATA WRITE
+    uint32_t m_cpt_dcache_dir_read;         // DCACHE DIR READ
+    uint32_t m_cpt_dcache_dir_write;        // DCACHE DIR WRITE
+
+    uint32_t m_cpt_icache_data_read;        // ICACHE DATA READ
+    uint32_t m_cpt_icache_data_write;       // ICACHE DATA WRITE
+    uint32_t m_cpt_icache_dir_read;         // ICACHE DIR READ
+    uint32_t m_cpt_icache_dir_write;        // ICACHE DIR WRITE
+
+    uint32_t m_cpt_cc_update;               // number of coherence update packets 
+    uint32_t m_cpt_cc_inval;                // number of coherence inval packets
+
+    uint32_t m_cpt_frz_cycles;	            // number of cycles where the cpu is frozen
+    uint32_t m_cpt_total_cycles;	    // total number of cycles 
+
+    uint32_t m_cpt_read;                    // total number of read instructions
+    uint32_t m_cpt_write;                   // total number of write instructions
+    uint32_t m_cpt_data_miss;               // number of read miss
+    uint32_t m_cpt_ins_miss;                // number of instruction miss
+    uint32_t m_cpt_unc_read;                // number of read uncached
+    uint32_t m_cpt_write_cached;            // number of cached write
+
+    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
+    uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
+    uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
+    uint32_t m_cost_ins_miss_frz;           // number of frozen cycles related to ins miss
+
+    uint32_t m_cpt_imiss_transaction;       // number of VCI instruction miss transactions
+    uint32_t m_cpt_dmiss_transaction;       // number of VCI data miss transactions
+    uint32_t m_cpt_unc_transaction;         // number of VCI uncached read transactions
+    uint32_t m_cpt_write_transaction;       // number of VCI write transactions
+
+    uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions
+
+protected:
+    SC_HAS_PROCESS(VciCcXCacheWrapperMulti);
+
+public:
+
+    VciCcXCacheWrapperMulti(
+                       sc_module_name insname,
+                       int proc_id,
+                       const soclib::common::MappingTable &mtp,
+                       const soclib::common::MappingTable &mtc,
+                       const soclib::common::IntTab &initiator_index_p,
+                       const soclib::common::IntTab &initiator_index_c,
+                       const soclib::common::IntTab &target_index_c,
+                       size_t icache_ways,
+                       size_t icache_sets,
+                       size_t icache_words,
+                       size_t dcache_ways,
+                       size_t dcache_sets,
+                       size_t dcache_words,
+                       size_t wbuf_nwords,
+                       size_t wbuf_nlines );
+
+    ~VciCcXCacheWrapperMulti();
+
+    void print_cpi();
+    void print_stats();
+
+private:
+
+    void transition();
+    void genMoore();
+
+    soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC);
+    soclib_static_assert((int)iss_t::SC_NOT_ATOMIC == (int)vci_param::STORE_COND_NOT_ATOMIC);
+};
+
+}}
+
+#endif /* SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_MULTI_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
Index: trunk/modules/vci_cc_xcache_wrapper_multi/caba/source/src/vci_cc_xcache_wrapper_multi.cpp
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_multi/caba/source/src/vci_cc_xcache_wrapper_multi.cpp	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper_multi/caba/source/src/vci_cc_xcache_wrapper_multi.cpp	(revision 2)
@@ -0,0 +1,1927 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain 
+ *              eric.guthmuller@polytechnique.edu 
+ *              nipo
+ *              malek <abdelmalek.si-merabet@lip6.fr> 
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+// History
+// - 25/04/2008
+//   The existing vci_xcache component has been extended to include 
+//   a VCI target port to support a directory based coherence protocol.
+//   Three types of packets can be send by the L2 cache to the L1 cache
+//   * MULTICAST INVALIDATE packets : length = 1
+//   * MULTICAST UPDATE packets : length = n + 2   
+//   * BROADCAST INVALIDATE packets : length = 1
+//   The CLEANUP packets are sent by the L1 cache to the L2 cache, 
+//   to signal a replaced cache line.
+// - 12/08/2008
+//   The vci_cc_xcache_wrapper component instanciates directly the processsor 
+//   iss, in order to supress the processor/cache interface.
+//   According to the VCI advanced specification, this component uses one 
+//   word VCI CMD packets for MISS transactions, and accept one word VCI RSP
+//   packets for Write burst  transactions.
+//   The write buffer has been modified to use the WriteBuffer object. 
+//   A VCI write burst is constructed when two conditions are satisfied :
+//   The processor make strictly successive write requests, and they are
+//   in the same cache line. The write buffer performs re-ordering, to
+//   respect the contiguous addresses VCI constraint. In case of several
+//   WRITE_WORD requests in the same word, only the last request is conserved.
+//   In case of several WRITE_HALF or WRITE_WORD requests in the same word,
+//   the requests are merged in the same word. In case of uncached write
+//   requests, each request is transmited as a single VCI transaction.
+//   Both the data & instruction caches can be flushed in one single cycle.
+// - 08/12/2009
+//   The update instruction coherence request (code 0XC) are supported. 
+// - 26/12/2009
+//   The VCI_CC_XCACHE_WRAPPER_MULTI is derived from the VCI_CC_XCACHE_WRAPPER_V1
+//   to support several concurrent VCI transactions, in order to improve the CPI.
+//   A new write buffer supporting simultaneous write transactions has been 
+//   introduced. The VCI command & response FSMs are not synchronized anymore:
+//   The read requests can be transmitted before previous write requests
+//   (if the missing address does not match apending write in the write buffer)
+//   and several read & write requests can be simultaneously transmitted.
+//   The transactions can complete in any order, depending on the network.
+//   Two new flip-flops have been introduced to signal completion of the
+//   read transactions from the RSP FSM to the DCACHE & ICACHE FSMs: 
+//   r_rsp_data_ok, r_rsp_ins_ok
+//   As simultaneous VCI transactions are supported, the TRDID & RTRDID fields
+//   are used to transport the transaction index.
+//   The transaction index has an odd value for a write transaction, depending
+//   on the line index in the write buffer: PKTID = 2*wbuf_index + 1
+//   The transaction index has an even value for a read transaction, with only
+//   only four possible values, depending on cached/uncached & data/instruction.
+//   A new CLEANUP FSM has been introduced to transmit the cleanups 
+//   request from the DCACHE & ICACHE FSM on the coherence network.
+//   The LL/SC requests are still uncached.
+///////////////////////////////////////////////////////////////////////////////
+
+//#define SOCLIB_MODULE_DEBUG 1
+
+#include <cassert>
+#include "arithmetics.h"
+#include "../include/vci_cc_xcache_wrapper_multi.h"
+
+namespace soclib { 
+namespace caba {
+
+#if SOCLIB_MODULE_DEBUG
+    namespace {
+        const char *dcache_fsm_state_str[] = {
+            "DCACHE_IDLE        ",
+            "DCACHE_WRITE_UPDT  ",
+            "DCACHE_WRITE_REQ   ",
+            "DCACHE_MISS_SELECT ",
+            "DCACHE_MISS_CLEANUP",
+            "DCACHE_MISS_WAIT   ",
+            "DCACHE_MISS_UPDT   ",
+            "DCACHE_UNC_WAIT    ",
+            "DCACHE_INVAL       ",
+            "DCACHE_SYNC        ",
+            "DCACHE_ERROR       ",
+            "DCACHE_CC_CHECK    ",
+            "DCACHE_CC_INVAL    ",
+            "DCACHE_CC_UPDT     ",
+        };
+        const char *icache_fsm_state_str[] = {
+            "ICACHE_IDLE        ",
+            "ICACHE_MISS_SELECT ",
+            "ICACHE_MISS_CLEANUP",
+            "ICACHE_MISS_WAIT   ",
+            "ICACHE_MISS_UPDT   ",
+            "ICACHE_UNC_WAIT    ",
+            "ICACHE_ERROR       ",
+            "ICACHE_CC_CHECK    ",
+            "ICACHE_CC_INVAL    ",
+            "ICACHE_CC_UPDT     ",
+        };
+        const char *cmd_fsm_state_str[] = {
+            "CMD_IDLE      ",
+            "CMD_INS_MISS  ",
+            "CMD_INS_UNC   ",
+            "CMD_DATA_MISS ",
+            "CMD_DATA_UNC  ",
+            "CMD_DATA_WRITE",
+        };
+        const char *rsp_fsm_state_str[] = {
+            "RSP_IDLE      ",
+            "RSP_INS_MISS  ",
+            "RSP_INS_UNC   ",
+            "RSP_DATA_MISS ",
+            "RSP_DATA_UNC  ",
+            "RSP_DATA_WRITE",
+        };
+        const char *tgt_fsm_state_str[] = {
+            "TGT_IDLE         ",
+            "TGT_UPDT_WORD    ",
+            "TGT_UPDT_DATA    ",
+            "TGT_REQ_BROADCAST",
+            "TGT_REQ_ICACHE   ",
+            "TGT_REQ_DCACHE   ",
+            "TGT_RSP_BROADCAST",
+            "TGT_RSP_ICACHE   ",
+            "TGT_RSP_DCACHE   ",
+        };
+        const char *cleanup_fsm_state_str[] = {
+            "CLEANUP_CMD",
+            "CLEANUP_DCACHE_RSP",
+            "CLEANUP_ICACHE_RSP",
+        };
+    }
+#endif
+
+#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXCacheWrapperMulti<vci_param, iss_t>
+
+    using soclib::common::uint32_log2;
+
+    /////////////////////////////////////
+    tmpl(/**/)::VciCcXCacheWrapperMulti(
+    /////////////////////////////////////
+            sc_module_name name,
+            int proc_id,
+            const soclib::common::MappingTable &mtp,
+            const soclib::common::MappingTable &mtc,
+            const soclib::common::IntTab &initiator_index_p,
+            const soclib::common::IntTab &initiator_index_c,
+            const soclib::common::IntTab &target_index_c,
+            size_t icache_ways,
+            size_t icache_sets,
+            size_t icache_words,
+            size_t dcache_ways,
+            size_t dcache_sets,
+            size_t dcache_words,
+            size_t wbuf_nwords,
+            size_t wbuf_nlines )
+        : 
+            soclib::caba::BaseModule(name),
+
+            p_clk("clk"),
+            p_resetn("resetn"),
+            p_vci_ini_d("vci_ini_p"),
+            p_vci_ini_c("vci_ini_c"),
+            p_vci_tgt_c("vci_tgt_c"),
+
+            m_cacheability_table(mtp.getCacheabilityTable<addr_t>()),
+            m_segment(mtc.getSegment(target_index_c)),
+            m_iss(this->name(), proc_id),
+            m_srcid_d(mtp.indexForId(initiator_index_p)),
+            m_srcid_c(mtc.indexForId(initiator_index_c)),
+            
+            m_dcache_ways(dcache_ways),
+            m_dcache_words(dcache_words),
+            m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
+            m_icache_ways(icache_ways),
+            m_icache_words(icache_words),
+            m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
+            m_wbuf_nlines(wbuf_nlines),
+
+            r_dcache_fsm("r_dcache_fsm"),
+            r_dcache_fsm_save("r_dcache_fsm_save"),
+            r_dcache_addr_save("r_dcache_addr_save"),
+            r_dcache_wdata_save("r_dcache_wdata_save"),
+            r_dcache_rdata_save("r_dcache_rdata_save"),
+            r_dcache_type_save("r_dcache_type_save"),
+            r_dcache_be_save("r_dcache_be_save"),
+            r_dcache_cleanup_save("r_dcache_cleanup_save"),
+            r_dcache_way_save("r_dcache_way_save"),
+            r_dcache_cleanup_req("r_dcache_cleanup_req"),
+            r_dcache_cleanup_line("r_dcache_cleanup_line"),
+            r_dcache_miss_req("r_dcache_miss_req"),
+            r_dcache_unc_req("r_dcache_unc_req"),
+            r_dcache_inval_pending("r_dcache_inval_pending"),
+
+            r_icache_fsm("r_icache_fsm"),
+            r_icache_fsm_save("r_icache_fsm_save"),
+            r_icache_addr_save("r_icache_addr_save"),
+            r_icache_cleanup_save("r_icache_cleanup_save"),
+            r_icache_way_save("r_icache_way_save"),
+            r_icache_miss_req("r_icache_miss_req"),
+            r_icache_cleanup_req("r_icache_cleanup_req"),
+            r_icache_cleanup_line("r_icache_cleanup_line"),
+            r_icache_inval_pending("r_icache_inval_pending"),
+
+            r_cmd_fsm("r_cmd_fsm"),
+            r_cmd_min("r_cmd_min"),
+            r_cmd_max("r_cmd_max"),
+            r_cmd_cpt("r_cmd_cpt"),
+
+            r_rsp_fsm("r_rsp_fsm"),
+            r_rsp_ins_error("r_rsp_ins_error"),
+            r_rsp_data_error("r_rsp_data_error"),
+            r_rsp_cpt("r_rsp_cpt"),
+            r_rsp_ins_ok("r_rsp_ins_ok"),
+            r_rsp_data_ok("r_rsp_data_ok"),
+
+            r_tgt_fsm("r_tgt_fsm"),
+            r_tgt_addr("r_tgt_addr"),
+            r_tgt_word("r_tgt_word"),
+            r_tgt_update("r_tgt_update"),
+            r_tgt_data("r_tgt_data"),
+            r_tgt_srcid("r_tgt_srcid"),
+            r_tgt_pktid("r_tgt_pktid"),
+            r_tgt_trdid("r_tgt_trdid"),
+            r_tgt_icache_req("r_tgt_icache_req"),
+            r_tgt_dcache_req("r_tgt_dcache_req"),
+            r_tgt_icache_rsp("r_tgt_icache_rsp"),
+            r_tgt_dcache_rsp("r_tgt_dcache_rsp"),
+
+            r_cleanup_fsm("r_cleanup_fsm"),
+
+            r_wbuf("r_wbuf", wbuf_nwords, wbuf_nlines),
+            r_icache("icache", icache_ways, icache_sets, icache_words),
+            r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
+
+            {
+
+                assert( (m_wbuf_nlines== 1 || m_wbuf_nlines == 2 || m_wbuf_nlines == 4 || m_wbuf_nlines == 8 || m_wbuf_nlines == 16) &&
+                      "number of lines must be power of 2, no larger than 16");
+
+                r_icache_miss_buf = new data_t[icache_words];
+                r_dcache_miss_buf = new data_t[dcache_words];
+                r_tgt_buf         = new data_t[dcache_words];
+                r_tgt_val         = new bool[dcache_words];
+
+                SC_METHOD(transition);
+                dont_initialize();
+                sensitive << p_clk.pos();
+
+                SC_METHOD(genMoore);
+                dont_initialize();
+                sensitive << p_clk.neg();
+
+                typename iss_t::CacheInfo cache_info;
+                cache_info.has_mmu = false;
+                cache_info.icache_line_size = icache_words*sizeof(data_t);
+                cache_info.icache_assoc = icache_ways;
+                cache_info.icache_n_lines = icache_sets;
+                cache_info.dcache_line_size = dcache_words*sizeof(data_t);
+                cache_info.dcache_assoc = dcache_ways;
+                cache_info.dcache_n_lines = dcache_sets;
+                m_iss.setCacheInfo(cache_info);
+
+            } // end constructor
+
+    //////////////////////////////////////
+    tmpl(/**/)::~VciCcXCacheWrapperMulti()
+    //////////////////////////////////////
+    {
+        delete [] r_icache_miss_buf;
+        delete [] r_dcache_miss_buf;
+        delete [] r_tgt_val;
+        delete [] r_tgt_buf;
+    }
+
+    ////////////////////////
+    tmpl(void)::print_cpi()
+    ////////////////////////
+    {
+        std::cout << "CPU " << m_srcid_d << " : CPI = " 
+            << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
+    }
+    ////////////////////////
+    tmpl(void)::print_stats()
+        ////////////////////////
+    {
+        float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
+        std::cout << "------------------------------------" << std:: dec << std::endl
+        << "CPU " << m_srcid_d << " / Time = " << m_cpt_total_cycles << std::endl
+        << "- CPI               = " << (float)m_cpt_total_cycles/run_cycles << std::endl
+        << "- READ RATE         = " << (float)m_cpt_read/run_cycles << std::endl
+        << "- UNC READ RATE     = " << (float)m_cpt_unc_read/m_cpt_read << std::endl
+        << "- WRITE RATE        = " << (float)m_cpt_write/run_cycles << std::endl
+        << "- CACHED WRITE RATE = " << (float)m_cpt_write_cached/m_cpt_write << std::endl
+        << "- IMISS_RATE        = " << (float)m_cpt_ins_miss/run_cycles << std::endl
+        << "- IMISS COST        = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl
+        << "- DMISS RATE        = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl
+        << "- DMISS COST        = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl
+        << "- UNC COST          = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl
+        << "- WRITE COST        = " << (float)m_cost_write_frz/m_cpt_write << std::endl
+        << "- WRITE LENGTH      = " << (float)m_length_write_transaction/m_cpt_write_transaction 
+        << std::endl;
+    }
+
+    //////////////////////////
+    tmpl(void)::transition()
+    //////////////////////////
+    {
+        if ( ! p_resetn.read() ) {
+
+            m_iss.reset();
+
+            // FSM states
+            r_dcache_fsm 	= DCACHE_IDLE;
+            r_icache_fsm 	= ICACHE_IDLE;
+            r_cmd_fsm 		= CMD_IDLE;
+            r_rsp_fsm 		= RSP_IDLE;
+            r_tgt_fsm 		= TGT_IDLE;
+            r_cleanup_fsm 	= CLEANUP_CMD;
+
+            // write buffer & caches
+            r_wbuf.reset();
+            r_icache.reset();
+            r_dcache.reset();
+
+            // synchronisation flip-flops from ICACHE & DCACHE FSMs to CMD  FSM
+            r_icache_miss_req    = false;
+            r_icache_unc_req     = false;
+            r_dcache_miss_req    = false;
+            r_dcache_unc_req     = false;
+
+            // synchronisation flip-flops from ICACHE & DCACHE FSMs to CLEANUP FSM
+            r_icache_cleanup_req = false;
+            r_dcache_cleanup_req = false;
+
+            // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
+            r_tgt_icache_req     = false;
+            r_tgt_dcache_req     = false;
+            r_tgt_icache_rsp     = false;
+            r_tgt_dcache_rsp     = false;
+
+            // internal messages in DCACHE et ICACHE FSMs
+            r_icache_inval_pending   = false;
+            r_dcache_inval_pending   = false;
+
+            // synchronisation flip-flops from the RSP FSM to the ICACHE or DCACHE FSMs
+            r_rsp_data_ok 	= false;
+            r_rsp_ins_ok	= false;
+            r_rsp_data_error   	= false;
+            r_rsp_ins_error    	= false;
+
+            // activity counters
+            m_cpt_dcache_data_read  = 0;
+            m_cpt_dcache_data_write = 0;
+            m_cpt_dcache_dir_read  = 0;
+            m_cpt_dcache_dir_write = 0;
+            m_cpt_icache_data_read  = 0;
+            m_cpt_icache_data_write = 0;
+            m_cpt_icache_dir_read  = 0;
+            m_cpt_icache_dir_write = 0;
+
+            m_cpt_cc_update = 0;
+            m_cpt_cc_inval = 0;
+
+            m_cpt_frz_cycles = 0;
+            m_cpt_total_cycles = 0;
+
+            m_cpt_read = 0;
+            m_cpt_write = 0;
+            m_cpt_data_miss = 0;
+            m_cpt_ins_miss = 0;
+            m_cpt_unc_read = 0;
+            m_cpt_write_cached = 0;
+
+            m_cost_write_frz = 0;
+            m_cost_data_miss_frz = 0;
+            m_cost_unc_read_frz = 0;
+            m_cost_ins_miss_frz = 0;
+
+            m_cpt_imiss_transaction = 0;
+            m_cpt_dmiss_transaction = 0;
+            m_cpt_unc_transaction = 0;
+            m_cpt_write_transaction = 0;
+
+            return;
+        }
+
+#if SOCLIB_MODULE_DEBUG
+if ( m_srcid_d == 0 )
+{
+std::cout << "--------------------------------------------" << std::endl
+          << std::dec << "CACHE " << m_srcid_d << " / Time = " << m_cpt_total_cycles << std::endl
+          << "  " << dcache_fsm_state_str[r_dcache_fsm] 
+          << "  " << icache_fsm_state_str[r_icache_fsm]
+          << "  " << cmd_fsm_state_str[r_cmd_fsm] 
+          << "  " << rsp_fsm_state_str[r_rsp_fsm]
+          << "  " << cleanup_fsm_state_str[r_cleanup_fsm]
+          << "  " << tgt_fsm_state_str[r_tgt_fsm] << std::endl;
+r_wbuf.print();
+}
+#endif
+
+        m_cpt_total_cycles++;
+
+        /////////////////////////////////////////////////////////////////////
+        // The TGT_FSM controls the following ressources:
+        // - r_tgt_fsm
+        // - r_tgt_buf[nwords]
+        // - r_tgt_val[nwords]
+        // - r_tgt_update
+        // - r_tgt_data
+        // - r_tgt_word
+        // - r_tgt_addr
+        // - r_tgt_srcid
+        // - r_tgt_trdid
+        // - r_tgt_pktid
+        // All VCI commands must be CMD_WRITE.
+        // If the VCI address offset is null, the command is an invalidate 
+        // request. It is an update request otherwise.
+        // The VCI_TGT FSM stores the external request arguments in the
+        // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 
+        // & r_tgt_dcache_req flip-flops to signal the external request to 
+        // the ICACHE & DCACHE FSMs in the REQ states. It waits the completion
+        // of the update or invalidate request in the RSP states.
+        // -  for an invalidate request the VCI packet length is 1 word.
+        // The WDATA field contains the line index (i.e. the Z & Y fields).
+        // -  for an update request the VCI packet length is (n+2) words.
+        // The WDATA field of the first VCI word contains the line index.
+        // The WDATA field of the second VCI word contains the word index.
+        // The WDATA field of the n following words contains the values.
+        // -  for both invalidate & update requests, the VCI response
+        // is one single word.
+        // In case of errors in the VCI command packet, the simulation
+        // is stopped with an error message.
+        /////////////////////////////////////////////////////////////////////
+
+        switch( r_tgt_fsm ) {
+
+            case TGT_IDLE:
+            {
+                if ( p_vci_tgt_c.cmdval.read() ) 
+                {
+                    addr_t address = p_vci_tgt_c.address.read();
+
+                    if ( p_vci_tgt_c.cmd.read() != vci_param::CMD_WRITE) 
+                    {
+                        std::cout << "error in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the received coherence request from " << p_vci_tgt_c.srcid.read() 
+                                  << " is not a write" << std::endl;
+                        exit(0);
+                    }
+
+                    if ( (address != 0x3) && (! m_segment.contains(address)) ) 
+                    {
+                        std::cout << "error in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "out of segment coherence request" << std::endl;
+                        exit(0);
+                    }
+
+                    r_tgt_addr = (((addr_t) ((p_vci_tgt_c.be.read() & 0x3) << 32)) | 
+                                 ((addr_t) (p_vci_tgt_c.wdata.read()))) * m_dcache_words * 4;      
+                    r_tgt_srcid = p_vci_tgt_c.srcid.read();
+                    r_tgt_trdid = p_vci_tgt_c.trdid.read();
+                    r_tgt_pktid = p_vci_tgt_c.pktid.read();
+                    r_tgt_plen  = p_vci_tgt_c.plen.read();
+                    
+                    if ( address == 0x3 ) // broadcast invalidate 
+                    {
+                        if ( ! p_vci_tgt_c.eop.read() ) 
+                        {
+                            std::cout << "error in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                            std::cout << "a broascast request must be one word" << std::endl;
+                            exit(0);
+                        }
+                        r_tgt_update = false; 
+                        r_tgt_brdcast= true;
+                        r_tgt_fsm = TGT_REQ_BROADCAST;
+                        m_cpt_cc_inval++ ;
+                    }
+                    else                    // multicast-update or multicast-invalidate
+                    { 
+                        uint32_t cell = address - m_segment.baseAddress(); 
+                        if (cell == 0)                  // invalidate data
+                        {
+                            if ( ! p_vci_tgt_c.eop.read() ) 
+                            {
+                                std::cout << "error in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "an invalidate requestn must be one word" << std::endl;
+                                exit(0);
+                            }
+                            r_tgt_brdcast = false;
+                            r_tgt_update  = false; 
+                            r_tgt_data    = true;
+                            r_tgt_fsm = TGT_REQ_DCACHE;
+                            m_cpt_cc_inval++ ;
+                        } 
+                        else if (cell == 4)             // update data
+                        {                                
+                            if ( p_vci_tgt_c.eop.read() ) 
+                            {
+                                std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "an update request must be N+2 words" << std::endl;
+                                exit(0);
+                            }
+                            r_tgt_brdcast  = false;
+                            r_tgt_update   = true; 
+                            r_tgt_data     = true;
+                            r_tgt_fsm  = TGT_UPDT_WORD;
+                            m_cpt_cc_update++ ;
+                        } 
+                        else if (cell == 8)              // invalidate instruction
+                        {                         
+                            if ( ! p_vci_tgt_c.eop.read() ) 
+                            {
+                                std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "an invalidate request must be one word" << std::endl;
+                                exit(0);
+                            }
+                            r_tgt_brdcast = false;
+                            r_tgt_data    = false;
+                            r_tgt_update  = false; 
+                            r_tgt_fsm = TGT_REQ_ICACHE;
+                            m_cpt_cc_inval++ ;
+                        } 
+                        else if (cell == 12)             // update ins
+                        {                                
+                            if ( p_vci_tgt_c.eop.read() ) 
+                            {
+                                std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "an update request must be N+2 words" << std::endl;
+                                exit(0);
+                            }
+                            r_tgt_brdcast = false;
+                            r_tgt_update  = true; 
+                            r_tgt_data    = false;
+                            r_tgt_fsm = TGT_UPDT_WORD;
+                            m_cpt_cc_update++ ;
+                        } 
+
+                    } // end if address
+                } // end if cmdval
+                break;
+            }
+            case TGT_UPDT_WORD:
+            {
+                if (p_vci_tgt_c.cmdval.read()) 
+                {
+                    if ( p_vci_tgt_c.eop.read() ) 
+                    {
+                        std::cout << "error in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "an update command length must be N+2 words" << std::endl;
+                        exit(0);
+                    }
+                    for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_val[i] = false;
+                    r_tgt_word = p_vci_tgt_c.wdata.read(); // the first modified word index
+                    r_tgt_fsm = TGT_UPDT_DATA;
+                }
+                break;
+            }
+            case TGT_UPDT_DATA:
+            {
+                if (p_vci_tgt_c.cmdval.read()) 
+                {
+                    size_t word = r_tgt_word.read();
+                    if ( word >= m_dcache_words ) 
+                    {
+                        std::cout << "error in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the word index in an update request is wrong" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_buf[word] = p_vci_tgt_c.wdata.read();
+                    if(p_vci_tgt_c.be.read())    r_tgt_val[word] = true;
+                    r_tgt_word = word + 1;
+                    if (p_vci_tgt_c.eop.read()) {
+                        if (r_tgt_data.read())  r_tgt_fsm = TGT_REQ_DCACHE;
+                        else                    r_tgt_fsm = TGT_REQ_ICACHE;
+                    }
+                }
+                break;
+            }
+            case TGT_REQ_ICACHE:
+            {
+                if ( !r_tgt_icache_req.read() ) 
+                {
+                    r_tgt_fsm = TGT_RSP_ICACHE; 
+                    r_tgt_icache_req = true;
+                }
+                break;
+            }
+            case TGT_REQ_DCACHE:
+            {
+                if ( !r_tgt_dcache_req.read() ) 
+                {
+                    r_tgt_fsm = TGT_RSP_DCACHE; 
+                    r_tgt_dcache_req = true;
+                }
+                break;
+            }
+            case TGT_REQ_BROADCAST:
+            {
+                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+                {
+                    r_tgt_fsm = TGT_RSP_BROADCAST; 
+                    r_tgt_icache_req = true;
+                    r_tgt_dcache_req = true;
+                }
+                break;
+            }
+            case TGT_RSP_BROADCAST:
+            {
+                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+                {
+                    // one response
+                    if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
+                    {
+                        if ( p_vci_tgt_c.rspack.read() )
+                        {
+                            r_tgt_fsm = TGT_IDLE; 
+                            r_tgt_icache_rsp = false;
+                            r_tgt_dcache_rsp = false;
+                        }
+                    }
+                    //  two responses  
+                    if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
+                    {
+                        if ( p_vci_tgt_c.rspack.read() )
+                        {
+                            r_tgt_icache_rsp = false; // reset one to prepare the second response
+                        }
+                    }
+                    // no need for a response
+                    if ( !r_tgt_icache_rsp && !r_tgt_dcache_rsp )
+                    {
+                        r_tgt_fsm = TGT_IDLE;
+                    }
+                }
+                break;
+            }
+            case TGT_RSP_ICACHE:
+            {
+                if ( (p_vci_tgt_c.rspack.read() || !r_tgt_icache_rsp.read()) && !r_tgt_icache_req.read() ) 
+                {
+                    r_tgt_fsm = TGT_IDLE;
+                    r_tgt_icache_rsp = false; 
+                }
+                break;
+            }
+            case TGT_RSP_DCACHE:
+            {
+                if ( (p_vci_tgt_c.rspack.read() || !r_tgt_dcache_rsp.read()) && !r_tgt_dcache_req.read() ) 
+                {
+                    r_tgt_fsm = TGT_IDLE;
+                    r_tgt_dcache_rsp = false; 
+                }
+                break;
+            }
+        } // end switch TGT_FSM
+
+        //////////////////////////////////////////////////////////////////////////////
+        // The ICACHE FSM controls the following ressources:
+        // - r_icache_fsm
+        // - r_icache_fsm_save
+        // - r_icache instruction cache access
+        // - r_icache_addr_save
+        // - r_icache_miss_req set
+        // - r_icache_unc_req set
+        // - r_rsp_ins_ok reset
+        // - r_rsp_ins_error reset
+        // - r_tgt_icache_req reset
+        // - r_tgt_icache_rsp
+        // - r_icache_cleanup_req set
+        // - r_icache_cleanup_ine
+        // - ireq & irsp structures for communication with the processor
+        //
+        // 1/ External requests (update or invalidate) 
+        //    There is an external request when the r_tgt_icache_req flip-flop is set,
+        //    These requests are taken into account in the IDLE and WAIT states.
+        //    In case of external request the ICACHE FSM goes to the CC_CHECK
+        //    state to test the external hit, and returns in the
+        //    pre-empted state after this external request is completed.
+        //
+        // 2/ Processor requests are taken into account only in the IDLE state.
+        //    In case of MISS, or in case of uncached instruction, the FSM 
+        //    writes the missing address line in the  r_icache_addr_save register 
+        //    and sets the r_icache_miss_req or the r_icache_unc_req flip-flops.
+        //    These request flip-flops are reset by the CMD FSM.
+        //    The r_rsp_ins_ok flip-flop is set by the RSP FSM when the 
+        //    transaction is completed. In case of bus error, the RSP FSM sets 
+        //    the r_rsp_ins_error flip-flop. They must be reset by the ICACHE FSM.
+        //   - CACHED READ MISS => to the MISS_WAIT state, waiting the r_rsp_ins_ok signal.
+        //     It can be delayed in the MISS_DELAY state in case of matching pending
+        //     cleanup request.  Then it goes to the MISS_UPDT state, then to the CLEANUP_REQ
+        //     state (if necessary), and finally to the IDLE state.
+        //   - UNCACHED READ  => to the UNC_WAIT state (waiting the r_rsp_ins_ok signal), 
+        //     and back to the IDLE state. 
+        ////////////////////////////////////////////////////////////////////////////////////
+
+        typename iss_t::InstructionRequest  ireq = ISS_IREQ_INITIALIZER;
+        typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
+
+        typename iss_t::DataRequest  dreq = ISS_DREQ_INITIALIZER;
+        typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
+
+        m_iss.getRequests( ireq, dreq );
+
+        switch(r_icache_fsm) {
+ 
+            case ICACHE_IDLE:
+            {
+                if ( r_tgt_icache_req )    // external request
+                {
+                    if ( ireq.valid ) m_cost_ins_miss_frz++;
+                    r_icache_fsm = ICACHE_CC_CHECK;
+                    r_icache_fsm_save = r_icache_fsm;
+                    break;
+                } 
+                if ( ireq.valid ) 
+                {
+                    data_t  icache_ins = 0;
+                    bool    icache_hit = false;
+                    bool    icache_cached = m_cacheability_table[(addr_t)ireq.addr];
+                    // icache_hit & icache_ins evaluation
+                    if ( icache_cached ) 
+                    {
+                        icache_hit = r_icache.read((addr_t)ireq.addr, &icache_ins);
+                    } 
+                    else 
+                    {
+                        icache_hit = (r_rsp_ins_ok && ( (addr_t)ireq.addr == (addr_t)r_icache_addr_save));
+                        icache_ins = r_icache_miss_buf[0];
+                    }
+                    if ( ! icache_hit )  // miss
+                    {
+                        m_cpt_ins_miss++;
+                        m_cost_ins_miss_frz++;
+                        r_icache_addr_save = (addr_t)ireq.addr;
+                        if ( icache_cached ) 	// cached line
+                        {
+                            // if the missing line corresponds to a pending cleanup
+                            // the miss request to the CMD FSM must be delayed
+                            if ( r_icache_cleanup_req && 
+                               ((addr_t)r_icache_cleanup_line == (addr_t)(ireq.addr/(m_icache_words*4))) ) 
+                            {
+                                break;
+                            }
+                            else
+                            {
+                                r_icache_fsm 		= ICACHE_MISS_SELECT;
+                                r_icache_miss_req 	= true;
+                                r_rsp_ins_ok		= false;
+                            }
+                        } 
+                        else 			// uncached line
+                        {
+                            r_icache_fsm 	= ICACHE_UNC_WAIT;
+                            r_icache_unc_req 	= true;
+                            r_rsp_ins_ok	= false;
+                        }
+                    } 
+                    else  // hit : the uncached data should not be re-used
+                    {
+                        r_rsp_ins_ok = false;
+                    } 
+                    m_cpt_icache_dir_read += m_icache_ways;
+                    m_cpt_icache_data_read += m_icache_ways;
+                    irsp.valid          = icache_hit;
+                    irsp.instruction    = icache_ins;
+                } // end if ireq.valid
+                break;
+            }
+            case ICACHE_MISS_SELECT:
+            {
+                m_cost_ins_miss_frz++;
+                size_t	way;
+                addr_t	index;
+                addr_t  ad = r_icache_addr_save;
+                if ( r_icache.select_before_update( ad, &way, &index) )
+                {
+                    r_icache_fsm          = ICACHE_MISS_CLEANUP; 
+                    r_icache_cleanup_save = index;
+                    r_icache_way_save     = way;
+                }
+                else
+                {
+                    r_icache_way_save     = way;
+                    r_icache_fsm          = ICACHE_MISS_WAIT;
+                }
+                break;
+            }
+            case ICACHE_MISS_CLEANUP: // try to post a cleanup request to the CLEANUP FSM
+            {
+                m_cost_ins_miss_frz++;
+                if ( r_tgt_icache_req )    // coherence request 
+                {
+                    r_icache_fsm = ICACHE_CC_CHECK;
+                    r_icache_fsm_save = r_icache_fsm;
+                    break;
+                } 
+                if ( !r_icache_cleanup_req )	// no pending cleanup
+                {
+                    r_icache_cleanup_req 	= true;
+                    r_icache_cleanup_line   = r_icache_cleanup_save.read();
+                    r_icache_fsm	    	= ICACHE_MISS_WAIT;
+                }
+                break;                
+            }
+            case ICACHE_MISS_WAIT:  // waiting the response from the RSP FSM
+            {
+                m_cost_ins_miss_frz++;
+                if ( r_tgt_icache_req )    // coherence request
+                {
+                    r_icache_fsm = ICACHE_CC_CHECK;
+                    r_icache_fsm_save = r_icache_fsm;
+                    break;
+                } 
+                if ( r_rsp_ins_ok )  // there is a response
+                {
+                    if      ( r_rsp_ins_error )		r_icache_fsm = ICACHE_ERROR;
+                    else if ( !r_icache_inval_pending )	r_icache_fsm = ICACHE_MISS_UPDT;
+                    else
+                    {
+                        if ( r_icache_cleanup_req ) 
+                        {
+                            break;
+                        }
+                        else
+                        {
+                            r_icache_cleanup_req = true;
+                            r_icache_cleanup_line = r_icache_addr_save.read() >> (uint32_log2(m_icache_words) + 2);
+                            r_icache_fsm = ICACHE_IDLE;
+                            r_icache_inval_pending = false;
+                        }
+                    }
+                }
+                break;
+            }
+            case ICACHE_MISS_UPDT:  // update the cache 
+            {
+                m_cost_ins_miss_frz++;
+                m_cpt_icache_dir_write++;
+                m_cpt_icache_data_write++;
+                addr_t 		ad   	= (addr_t) r_icache_addr_save;
+                data_t*   	buf   	= (data_t*) r_icache_miss_buf;
+                size_t		way	= (size_t) r_icache_way_save;
+                r_icache.update_after_select( buf, way, ad );
+                r_icache_fsm = ICACHE_IDLE;
+                break;
+            }
+            case ICACHE_UNC_WAIT:
+            {
+                m_cost_ins_miss_frz++;
+                if ( r_tgt_icache_req )    // external request
+                {
+                    r_icache_fsm = ICACHE_CC_CHECK;
+                    r_icache_fsm_save = r_icache_fsm;
+                    break;
+                } 
+                if ( r_rsp_ins_ok ) 
+                {
+                    if ( r_rsp_ins_error ) 	r_icache_fsm = ICACHE_ERROR;
+                    else 			r_icache_fsm = ICACHE_IDLE;
+                }
+                break;
+            }
+            case ICACHE_ERROR:
+            {
+                r_icache_fsm = ICACHE_IDLE;
+                r_rsp_ins_error     = false;
+                irsp.error          = true;
+                irsp.valid          = true;
+                break;
+            } 
+            case ICACHE_CC_CHECK:   // read directory in case of external request
+            {
+                m_cpt_icache_dir_read += m_icache_ways;
+                m_cpt_icache_data_read += m_icache_ways;
+                if ( ( (r_icache_fsm_save == ICACHE_MISS_WAIT) || (r_icache_fsm_save == ICACHE_MISS_CLEANUP) ) && // external request matches a miss
+                ((r_icache_addr_save & ~((m_icache_words<<2)-1))==(r_tgt_addr & ~((m_icache_words<<2)-1))))
+                {
+                    r_icache_inval_pending 	= true;
+                    r_tgt_icache_req       	= false;
+                    r_tgt_icache_rsp       	= r_tgt_update;  // always a response n case of update 
+                    r_icache_fsm 		= r_icache_fsm_save;
+                } 
+                else  // the external request is not matching a pending miss
+                {
+                    data_t  data;
+                    bool    icache_hit   	= r_icache.read(r_tgt_addr, &data);
+                    if ( icache_hit && r_tgt_update )  // hit update
+                    {
+                        r_icache_fsm = ICACHE_CC_UPDT;
+                    } 
+                    else if ( icache_hit && !r_tgt_update ) // hit inval
+                    {
+                        r_icache_fsm = ICACHE_CC_INVAL;
+                    } 
+                    else	// miss 
+                    { 
+                        r_tgt_icache_req 	= false;
+                        r_tgt_icache_rsp 	= r_tgt_update; // alaways a response in case of update
+                        r_icache_fsm 		= r_icache_fsm_save;
+                    }
+                }
+                break;
+            }
+            case ICACHE_CC_UPDT:    // update the cache line        
+            {
+                m_cpt_icache_dir_write++;
+                m_cpt_icache_data_write++;
+                for(size_t i=0; i<m_icache_words; i++)
+                {
+                    if(r_tgt_val[i]) r_icache.write( (r_tgt_addr + i*4), r_tgt_buf[i] );
+                }
+                r_tgt_icache_rsp = true;
+                r_tgt_icache_req = false;
+                r_icache_fsm = r_icache_fsm_save;
+                break;
+            }
+            case ICACHE_CC_INVAL:   // invalidate a cache line
+            {
+                r_icache.inval(r_tgt_addr);
+                r_tgt_icache_rsp = true;
+                r_tgt_icache_req = false;
+                r_icache_fsm = r_icache_fsm_save;
+                break;
+            }
+        } // end switch r_icache_fsm
+
+        //////////////////////////////////////////////////////////////////////://///////////
+        // The DCACHE FSM controls the following ressources:
+        // - r_dcache_fsm
+        // - r_dcache_fsm_save
+        // - r_dcache (data cache access)
+        // - r_dcache_addr_save
+        // - r_dcache_wdata_save
+        // - r_dcache_rdata_save
+        // - r_dcache_type_save
+        // - r_dcache_be_save
+        // - r_dcache_miss_req set
+        // - r_dcache_unc_req set
+        // - r_rsp_data_ok reset
+        // - r_rsp_data_error reset
+        // - r_dcache_cleanup_req set
+        // - r_dcache_cleanup_ine
+        // - r_tgt_dcache_req reset
+        // - r_tgt_dcache_rsp
+        // - r_wbuf write()
+        // - dreq & drsp structures for communication with the processor
+        //
+        // 1/ external request (invalidate or update)
+        //    There is an external request when the r_tgt_dcache_req flip-flop is set.
+        //    External requests are taken into account in the states  IDLE, WRITE_REQ,  
+        //    UNC_WAIT, MISS_WAIT, and have the highest priority :
+        //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
+        //    goes to the CC_CHECK state to execute the requested action, and returns to the
+        //    pre-empted state.
+        //
+        //  2/ processor request  
+        //   In order to support VCI write burst, the processor requests are taken into account
+        //   in the WRITE_REQ state as well as in the IDLE state.
+        //   - In the IDLE state, the processor request cannot be satisfied if
+        //   there is a cached read miss, or an uncached read.
+        //   - In the WRITE_REQ state, the request cannot be satisfied if
+        //   there is a cached read miss, or an uncached read,
+        //   or when the write buffer is full.
+        //   - In all other states, the processor request is not satisfied.
+        //
+        //   The cache access takes into account the cacheability_table.
+        //   In case of processor request, there is six conditions to exit the IDLE state:
+        //   - CACHED READ MISS => to the MISS_WAIT state, waiting the r_rsp_data_ok signal.
+        //     It can be delayed in the MISS_DELAY state in case of matching pending
+        //     cleanup request.  Then it goes to the MISS_UPDT state, then to the CLEANUP_REQ
+        //     state (if necessary), and finally to the IDLE state.
+        //   - UNCACHED READ  => to the UNC_WAIT state, waiting the r_rsp_data_ok signal, 
+        //     and back to the IDLE state. LL & SC are handled as uncached read.
+        //   - WRITE MISS => directly to the WRITE_REQ state to post a request in the
+        //     write buffer.
+        //   - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state.
+        //   - LINE INVALIDATE => to the INVAL state for one cycle, then to IDLE state.
+        //   - SYNC REQUEST => to the SYNC state until the write buffer is empty.
+        //
+        // Error handling :  Read Bus Errors are synchronous events, but
+        // Write Bus Errors are asynchronous events (processor is not frozen).
+        // - If a Read Bus Error is detected, the VCI_RSP FSM sets the
+        //   r_rsp_data_error flip-flop, and the synchronous error is signaled
+        //   by the DCACHE FSM.
+        // - If a Write Bus Error is detected, the VCI_RSP FSM  signals
+        //   the asynchronous error using the setWriteBerr() method.
+        ///////////////////////////////////////////////////////////////////////////////////
+
+        switch ( r_dcache_fsm ) {
+
+        case DCACHE_WRITE_REQ:
+	{
+            if ( r_tgt_dcache_req )    // coherence request
+            {
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            }
+            if( !r_wbuf.wok(r_dcache_addr_save) ) 
+            {
+                // stay in DCACHE_WRITEREQ state if the write request is not accepted 
+                // by the write buffer 
+                m_cost_write_frz++;
+                drsp.valid = false;
+                drsp.rdata = 0;
+                break;
+            }
+                // If the write request is accepted by the write buffer
+                // the next state and the response to processor request are evaluated
+                // as in the DCACHE_IDLE state  below ...
+        }     
+        case DCACHE_IDLE:
+        {
+            if ( r_tgt_dcache_req )   // coherence request
+            {
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            } 
+            if ( dreq.valid ) 
+            {              
+                bool        dcache_hit     = false;
+                data_t      dcache_rdata   = 0;
+                bool        dcache_cached;
+                m_cpt_dcache_data_read += m_dcache_ways;
+                m_cpt_dcache_dir_read += m_dcache_ways;
+
+                // dcache_cached evaluation
+                switch (dreq.type) {
+                    case iss_t::DATA_LL:
+                    case iss_t::DATA_SC:
+                    case iss_t::XTN_READ:
+                    case iss_t::XTN_WRITE:
+                        dcache_cached = false;
+                        break;
+                    default:
+                        dcache_cached = m_cacheability_table[dreq.addr];
+                }
+
+                // dcache_hit & dcache_rdata evaluation
+                if ( dcache_cached ) 
+                {
+                    dcache_hit = r_dcache.read((addr_t) dreq.addr, &dcache_rdata);
+                } 
+                else 
+                {
+                    dcache_hit = ( r_rsp_data_ok && ( dreq.addr == r_dcache_addr_save) );
+                    dcache_rdata = r_dcache_miss_buf[0];
+                }
+
+                // next state & response evaluation
+                switch( dreq.type ) {
+                    case iss_t::DATA_READ:
+                    case iss_t::DATA_LL:
+                    case iss_t::DATA_SC:
+                        m_cpt_read++;
+                        if ( dcache_hit ) 
+                        {
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = dcache_rdata;
+                            r_rsp_data_ok = false;
+                        } 
+                        else 		
+                        {
+                            if ( dcache_cached )   // miss
+                            {
+                                m_cpt_data_miss++;
+                                m_cost_data_miss_frz++;
+                                // if the missing line corresponds to a pending cleanup
+                                // the miss request to the CMD FSM must be delayed
+                                if ( r_dcache_cleanup_req &&
+                                   ((addr_t)r_dcache_cleanup_line == (addr_t)(dreq.addr/(m_dcache_words*4))) )
+                                {
+                                    break;
+                                }
+                                else
+                                {
+                                    r_dcache_miss_req = true;
+                                    r_rsp_data_ok = false;
+                                    r_dcache_fsm = DCACHE_MISS_SELECT;
+                                }
+                                drsp.valid = false;
+                                drsp.rdata = 0;
+                            } 
+                            else 		// uncached
+                            {
+                                m_cpt_unc_read++;
+                                m_cost_unc_read_frz++;
+                                r_dcache_unc_req = true;
+                                r_rsp_data_ok = false;
+                                r_dcache_fsm = DCACHE_UNC_WAIT;
+                                drsp.valid = false;
+                                drsp.rdata = 0;
+                            }
+                        }
+                        break;
+                    case iss_t::XTN_READ:
+                    case iss_t::XTN_WRITE:
+                        // only DCACHE_INVAL & SYNC requests are supported
+                        if ( dreq.addr/4 == iss_t::XTN_DCACHE_INVAL )
+                        {
+                            r_dcache_fsm = DCACHE_INVAL;
+                        } 
+                        else if ( dreq.addr/4 == iss_t::XTN_SYNC )
+                        {
+                            r_dcache_fsm = DCACHE_SYNC;
+                        }
+                        else
+                        {
+//                          std::cout << "warning in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+//                          std::cout << "unsupported external access " << dreq.addr/4 << std::endl;
+//                          std::cout << "only XTN_DCACHE_INVAL & XTN_SYNC are supported" << std::endl;
+                        }
+                        r_dcache_fsm = DCACHE_IDLE; 
+                        drsp.valid = true;
+                        drsp.rdata = 0;
+                        break;
+                    case iss_t::DATA_WRITE:
+                        m_cpt_write++;
+                        if ( dcache_hit && dcache_cached ) 
+                        {
+                            m_cpt_write_cached++;
+                            r_dcache_fsm = DCACHE_WRITE_UPDT;
+                            drsp.valid = true;
+                            drsp.rdata = 0;
+                        } 
+                        else 
+                        {
+                            r_dcache_fsm = DCACHE_WRITE_REQ;
+                            drsp.valid = true;
+                            drsp.rdata = 0;
+                        }
+                        break;
+                } // end switch dreq.type
+
+                r_dcache_addr_save      = dreq.addr;
+                r_dcache_type_save      = dreq.type;
+                r_dcache_wdata_save     = dreq.wdata;
+                r_dcache_be_save        = dreq.be;
+                r_dcache_rdata_save     = dcache_rdata;
+            } 
+            else  // no dreq.valid
+            {
+                drsp.valid 	= false;
+                drsp.rdata 	= 0;
+                r_dcache_fsm 	= DCACHE_IDLE;
+            }
+            break;
+        }       
+        case DCACHE_WRITE_UPDT:
+        {
+            m_cpt_dcache_data_write++;
+            data_t mask = vci_param::be2mask(r_dcache_be_save);
+            data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
+            r_dcache.write( r_dcache_addr_save, wdata );
+            r_dcache_fsm = DCACHE_WRITE_REQ;
+            break;
+        }
+        case DCACHE_MISS_SELECT: // select a victim
+        {
+            m_cost_data_miss_frz++;
+            size_t	way;
+            addr_t	index;
+            addr_t  ad = r_dcache_addr_save;
+            if ( r_dcache.select_before_update( ad, &way, &index) )
+            {
+                r_dcache_fsm          = DCACHE_MISS_CLEANUP; 
+                r_dcache_cleanup_save = index;
+                r_dcache_way_save     = way;
+            }
+            else
+            {
+                r_dcache_way_save     = way;
+                r_dcache_fsm          = DCACHE_MISS_WAIT;
+            }
+            break;
+        }
+        case DCACHE_MISS_CLEANUP: // try to post a cleanup request to the CLEANUP FSM
+        {
+            m_cost_data_miss_frz++;
+            if ( r_tgt_dcache_req )    // coherence request 
+            {
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            } 
+            if ( !r_dcache_cleanup_req )	// no pending cleanup
+            {
+                r_dcache_cleanup_req 	= true;
+                r_dcache_cleanup_line   = r_dcache_cleanup_save;
+                r_dcache_fsm		= DCACHE_MISS_WAIT;
+            }
+            break;                
+        }
+        case DCACHE_MISS_WAIT:  // waiting the response from the RSP FSM
+        {
+            m_cost_data_miss_frz++;
+            if ( r_tgt_dcache_req )    // coherence request
+            {
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            } 
+            if ( r_rsp_data_ok )  // there is a response
+            {
+                if      ( r_rsp_data_error )		r_dcache_fsm = DCACHE_ERROR;
+                else if ( !r_dcache_inval_pending )	r_dcache_fsm = DCACHE_MISS_UPDT;
+                else
+                {
+                    if ( r_dcache_cleanup_req ) 
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        r_dcache_cleanup_req = true;
+                        r_dcache_cleanup_line = r_dcache_addr_save >> (uint32_log2(m_icache_words) + 2);
+                        r_dcache_fsm = DCACHE_IDLE;
+                        r_dcache_inval_pending = false;
+                    }
+                }
+            }
+            break;
+        }
+        case DCACHE_MISS_UPDT:  // update the cache 
+        {
+            m_cost_data_miss_frz++;
+            m_cpt_dcache_dir_write++;
+            m_cpt_dcache_data_write++;
+            addr_t 	ad   	= (addr_t) r_dcache_addr_save;
+            data_t*   	buf   	= (data_t*) r_dcache_miss_buf;
+            size_t	way	= (size_t) r_dcache_way_save;
+            r_dcache.update_after_select( buf, way, ad );
+            r_dcache_fsm = DCACHE_IDLE;
+            break;
+        }
+        case DCACHE_UNC_WAIT:
+        {
+            if ( dreq.valid ) m_cost_unc_read_frz++;
+            if ( r_tgt_dcache_req )    // external request
+            {
+                r_dcache_fsm = DCACHE_CC_CHECK;
+                r_dcache_fsm_save = r_dcache_fsm;
+                break;
+            } 
+            if ( r_rsp_data_ok ) 
+            {
+                if ( r_rsp_data_error ) r_dcache_fsm = DCACHE_ERROR;
+                else 
+                {
+                    // If request is a DATA_SC we need to invalidate the corresponding cache line,
+                    // so that subsequent access to this line are read from RAM
+                    if (dreq.type == iss_t::DATA_SC)    
+                    {
+                        r_dcache_fsm = DCACHE_INVAL;
+                        r_dcache_wdata_save = r_dcache_addr_save;
+                    }
+                    else
+                    {
+                       r_dcache_fsm = DCACHE_IDLE;
+                    }
+                }
+            }
+            break;
+        }
+        case DCACHE_ERROR:
+        {
+            r_dcache_fsm = DCACHE_IDLE;
+            r_rsp_data_error = false;
+            drsp.error = true;
+            drsp.valid = true;
+            break;
+        }
+        case DCACHE_INVAL:
+        {
+            if( !r_dcache_cleanup_req )
+            {
+                m_cpt_dcache_dir_read += m_dcache_ways;
+                r_dcache_cleanup_req = r_dcache.inval( r_dcache_addr_save );
+                r_dcache_cleanup_line = r_dcache_addr_save.read() >> (uint32_log2(m_dcache_words)+2);
+                r_dcache_fsm = DCACHE_IDLE;
+            }
+            break;
+        }
+        case DCACHE_SYNC:
+        {
+            if ( r_wbuf.empty() ) r_dcache_fsm = DCACHE_IDLE; 
+            break;
+        }
+        case DCACHE_CC_CHECK:   // read directory in case of external request
+            m_cpt_dcache_dir_read += m_dcache_ways;
+            m_cpt_dcache_data_read += m_dcache_ways;
+            if ( ( (r_dcache_fsm_save == DCACHE_MISS_WAIT) || (r_dcache_fsm_save == DCACHE_MISS_CLEANUP) ) && // external request matches a miss
+            ((r_dcache_addr_save & ~((m_dcache_words<<2)-1))==(r_tgt_addr & ~((m_dcache_words<<2)-1))))
+                {
+                    r_dcache_inval_pending 	= true;
+                    r_tgt_dcache_req       	= false;
+                    r_tgt_dcache_rsp       	= r_tgt_update; // always a response to an update
+                    r_dcache_fsm 		= r_dcache_fsm_save;
+                } 
+                else  // the external request is not matching a pending miss
+                {
+                    data_t  data;
+                    bool    dcache_hit   	= r_dcache.read(r_tgt_addr, &data);
+                    if ( dcache_hit && r_tgt_update )  // hit update
+                    {
+                        r_dcache_fsm = DCACHE_CC_UPDT;
+                    } 
+                    else if ( dcache_hit && !r_tgt_update ) // hit inval
+                    {
+                        r_dcache_fsm = DCACHE_CC_INVAL;
+                    } 
+                    else	// miss 
+                    { 
+                        r_tgt_dcache_req = false;
+                        r_tgt_dcache_rsp = r_tgt_update;  // always a respons in case of update
+                        r_dcache_fsm = r_dcache_fsm_save;
+                    }
+                }
+                break;
+            
+            case DCACHE_CC_UPDT:    // update the cache line        
+                m_cpt_dcache_dir_write++;
+                m_cpt_dcache_data_write++;
+                for(size_t i=0; i<m_dcache_words; i++)
+                {
+                    if(r_tgt_val[i]) r_dcache.write( (r_tgt_addr + i*4), r_tgt_buf[i] );
+                }
+                r_tgt_dcache_rsp = true;
+                r_tgt_dcache_req = false;
+                r_dcache_fsm = r_dcache_fsm_save;
+                break;
+ 
+            case DCACHE_CC_INVAL:   // invalidate a cache line
+                r_dcache.inval(r_tgt_addr);
+                r_tgt_dcache_rsp = true;
+                r_tgt_dcache_req = false;
+                r_dcache_fsm = r_dcache_fsm_save;
+                break;
+        } // end switch r_dcache_fsm
+
+        ////////// write buffer handling //////////////////
+        if( r_dcache_fsm == DCACHE_WRITE_REQ ) 
+            r_wbuf.write(true, r_dcache_addr_save, r_dcache_be_save, r_dcache_wdata_save);
+        else 
+            r_wbuf.write(false, 0, 0, 0);
+
+#if SOCLIB_MODULE_DEBUG
+if ( m_srcid_d == 0 )
+std::cout << ireq << std::endl << irsp << std::endl << dreq << std::endl << drsp << std::endl;
+#endif
+
+        /////////// execute one iss cycle /////////////////////////////////////////////
+        {
+            uint32_t it = 0;
+            for (size_t i=0; i<(size_t)iss_t::n_irq; i++) 
+                if(p_irq[i].read()) it |= (1<<i);
+            m_iss.executeNCycles(1, irsp, drsp, it);
+        }
+
+        if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) ) m_cpt_frz_cycles++;
+
+        ////////////////////////////////////////////////////////////////////////////
+        // This CLEANUP FSM controls the transmission of the cleanup transactions
+        // on the coherence network. It controls the following ressources:
+        // - r_cleanup_fsm
+        // - r_dcache_cleanup_req reset
+        // - r_icache_cleanup_req reset
+        // 
+        // This FSM handles cleanup requests from both the DCACHE FSM & ICACHE FSM
+        // 1 - Instruction Cleanup  : r_icache_cleanup_req 
+        // 2 - Data Cleanup         : r_dcache_cleanup_req 
+        // In case of simultaneous requests, the data request have highest priority.
+        // There is only one cleanup transaction at a given time (sequencial behavior)
+        // because the same FSM controls both command & response. 
+        // The the r_icache_cleanup_req & r_dcache_cleanup_req are reset only
+        // when the response packet is received.
+        // Error handling :
+        // As the coherence trafic is controled by hardware, errors are not reported
+        // to software : In case of errors, the simulation stops.
+        ////////////////////////////////////////////////////////////////////////////
+
+        switch (r_cleanup_fsm) {
+
+            case CLEANUP_CMD:
+            {    
+                if ( p_vci_ini_c.cmdack )
+                {
+                    if      (r_dcache_cleanup_req) 	r_cleanup_fsm = CLEANUP_DCACHE_RSP;
+                    else if (r_icache_cleanup_req) 	r_cleanup_fsm = CLEANUP_ICACHE_RSP;
+                }
+                break;
+            }
+            case CLEANUP_DCACHE_RSP:
+            {
+                if ( p_vci_ini_c.rspval )
+                {
+                    assert( p_vci_ini_c.reop && (p_vci_ini_c.rtrdid.read() == 0) &&
+                      "illegal response packet received for a cleanup transaction");
+                    assert( (p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL) && 
+                      "error signaled in a cleanup response" );
+                    
+                    r_cleanup_fsm = CLEANUP_CMD;
+                    r_dcache_cleanup_req = false;
+                }
+                break;
+            }
+            case CLEANUP_ICACHE_RSP:
+            {
+                if ( p_vci_ini_c.rspval )
+                {
+                    assert( p_vci_ini_c.reop && (p_vci_ini_c.rtrdid.read() == 1) &&
+                      "illegal response packet received for a cleanup transaction");
+                    assert( (p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL) && 
+                      "error signaled in a cleanup response" );
+                    
+                    r_cleanup_fsm = CLEANUP_CMD;
+                    r_icache_cleanup_req = false;
+                }
+                break;
+            }
+        } // end switch r_cleanup_fsm    
+        
+        ////////////////////////////////////////////////////////////////////////////
+        // The CMD FSM controls the transmission of read & write requests
+        // on the direct network. It controls the following ressources:
+        // - r_cmd_fsm
+        // - r_cmd_min
+        // - r_cmd_max
+        // - r_cmd_cpt
+        // - r_dcache_miss_req reset
+        // - r_dcache_unc_req reset
+        // - r_icache_miss_req reset
+        // - r_icache_unc_req reset
+        // - wbuf sent()
+        //
+        // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
+        // There is 5 request types, with the following priorities : 
+        // 1 - Data Read Miss       : r_dcache_miss_req (if no hit in the write buffer)
+        // 2 - Data Read Uncached   : r_dcache_unc_req (if no hit in the write buffer)
+        // 3 - Instruction Miss     : r_icache_miss_req (if no hit in the write buffer)
+        // 4 - Instruction Uncached : r_icache_unc_req (if no hit in the write buffer)
+        // 5 - Data Write           : r_wbuf.rok()      
+        // The read requests have highest priority, because the processor is blocked.
+        //
+        // VCI formats:
+        // According to the VCI advanced specification, all read requests packets 
+        // (read Uncached, Miss data, Miss instruction) are one word packets.
+        // For write burst packets, all words must be in the same cache line,
+        // and addresses must be contiguous (the BE field is 0 in case of "holes").
+        // The PLEN VCI field is always documented.
+        // - Read transactions  : index = 4*cached + 2*instruction  (even values)
+        //////////////////////////////////////////////////////////////////////////////
+
+        switch (r_cmd_fsm) {
+
+            case CMD_IDLE:
+                if ( r_dcache_miss_req & r_wbuf.miss( r_dcache_addr_save ) )
+                { 
+                    r_cmd_fsm = CMD_DATA_MISS;
+                    r_dcache_miss_req = false;
+                    m_cpt_dmiss_transaction++; 
+                } 
+                else if ( r_dcache_unc_req & r_wbuf.miss( r_dcache_addr_save ) )
+                { 
+                    r_cmd_fsm = CMD_DATA_UNC;
+                    r_dcache_unc_req = false;
+                    m_cpt_unc_transaction++; 
+                }
+                else if ( r_icache_miss_req & r_wbuf.miss( r_icache_addr_save ) )
+                { 
+                    r_cmd_fsm = CMD_INS_MISS; 
+                    r_icache_miss_req = false;
+                    m_cpt_imiss_transaction++;
+                } 
+                else if ( r_icache_unc_req & r_wbuf.miss( r_icache_addr_save ) )
+                { 
+                    r_cmd_fsm = CMD_INS_UNC; 
+                    r_icache_unc_req = false;
+                    m_cpt_imiss_transaction++;
+                }
+                else if ( r_wbuf.rok() ) 
+                { 
+                    r_cmd_fsm = CMD_DATA_WRITE;
+                    r_cmd_cpt = r_wbuf.getMin();
+                    r_cmd_min = r_wbuf.getMin();
+                    r_cmd_max = r_wbuf.getMax(); 
+                    m_cpt_write_transaction++; 
+                    m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1); 
+                } 
+                break;
+
+            case CMD_DATA_WRITE:
+                if ( p_vci_ini_d.cmdack.read() ) 
+                {
+                    r_cmd_cpt = r_cmd_cpt + 1;
+                    if (r_cmd_cpt == r_cmd_max) 
+                    {
+                        r_cmd_fsm = CMD_IDLE ;
+                        r_wbuf.sent() ;
+                    }
+                }
+                break;
+
+            case CMD_INS_MISS:
+            case CMD_INS_UNC:
+            case CMD_DATA_MISS:
+            case CMD_DATA_UNC:
+                if ( p_vci_ini_d.cmdack.read() )  r_cmd_fsm = CMD_IDLE;
+                break;
+        } // end  switch r_cmd_fsm
+
+        //////////////////////////////////////////////////////////////////////////
+        // The RSP FSM receive the response packets on the direct network.
+        // It controls the following ressources:
+        // - r_rsp_fsm:
+        // - r_icache_miss_buf[m_icache_words]
+        // - r_dcache_miss_buf[m_dcache_words]
+        // - r_icache_miss_req reset
+        // - r_icache_unc_req reset
+        // - r_dcache_miss_req reset
+        // - r_dcache_unc_req reset
+        // - r_icache_cleanup_req reset
+        // - r_dcache_cleanup_req reset
+        // - r_rsp_data_ok set
+        // - r_rsp_ins_ok set
+        // - r_rsp_data_error set
+        // - r_rsp_ins_error set
+        // - r_rsp_cpt
+        // 
+        // VCI formats:
+        // This component accepts only single word write response packets. 
+        //
+        // Error handling:
+        // This FSM analyzes the VCI error code and signals the  Write Bus Error. 
+        // In case of Read Data Error, the VCI_RSP FSM sets the r_rsp_data_error 
+        // flip_flop and the error is signaled by the DCACHE FSM.  
+        // In case of Instruction Error, the VCI_RSP FSM sets the r_rsp_ins_error 
+        // flip_flop and the error is signaled by the DCACHE FSM.  
+        //////////////////////////////////////////////////////////////////////////
+
+        switch (r_rsp_fsm) {
+
+        case RSP_IDLE:
+            if( p_vci_ini_d.rspval.read() )
+            {
+                r_rsp_cpt = 0;
+                if ( p_vci_ini_d.rtrdid.read()/m_wbuf_nlines != 0 )		r_rsp_fsm = RSP_DATA_WRITE;
+                else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_MISS ) r_rsp_fsm = RSP_DATA_MISS;
+                else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_UNC ) 	r_rsp_fsm = RSP_DATA_UNC;
+                else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_MISS ) 	r_rsp_fsm = RSP_INS_MISS;
+                else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_UNC ) 	r_rsp_fsm = RSP_INS_UNC;
+            }
+            break;
+
+        case RSP_DATA_WRITE:
+            if ( p_vci_ini_d.rspval.read() )
+            {
+                assert(p_vci_ini_d.reop.read() &&
+                   "illegal VCI response packet for a write transaction");
+                r_rsp_fsm = RSP_IDLE;
+                r_wbuf.completed( p_vci_ini_d.rtrdid.read() - m_wbuf_nlines );
+                if ( p_vci_ini_d.rerror.read() != vci_param::ERR_NORMAL ) m_iss.setWriteBerr();
+            }
+            break;
+
+        case RSP_INS_MISS:
+            if ( p_vci_ini_d.rspval.read() )
+            {  
+                assert( (r_rsp_cpt < m_icache_words) &&
+                        "The VCI response packet for instruction miss is too long" );
+                r_rsp_cpt = r_rsp_cpt + 1;
+                r_icache_miss_buf[r_rsp_cpt] = (data_t)p_vci_ini_d.rdata.read();
+                if ( p_vci_ini_d.reop.read() ) {
+                    assert( (r_rsp_cpt == m_icache_words - 1) &&
+                            "The VCI response packet for instruction miss is too short");
+                    r_rsp_ins_ok = true;
+                    r_rsp_fsm = RSP_IDLE;
+                }
+                if ( p_vci_ini_d.rerror.read() != vci_param::ERR_NORMAL ) r_rsp_ins_error = true;
+            }
+            break;
+
+        case RSP_INS_UNC:
+            if ( p_vci_ini_d.rspval.read() )
+            {
+                assert(p_vci_ini_d.reop.read() &&
+                   "illegal VCI response packet for uncached instruction");
+                r_icache_miss_buf[0] = (data_t)p_vci_ini_d.rdata.read();
+                r_rsp_ins_ok = true;
+                r_rsp_fsm = RSP_IDLE;
+                if ( p_vci_ini_d.rerror.read() != vci_param::ERR_NORMAL ) r_rsp_ins_error = true;
+            }
+            break;
+
+        case RSP_DATA_MISS:
+            if ( p_vci_ini_d.rspval.read() )
+            {
+                assert(r_rsp_cpt != m_dcache_words &&
+                   "illegal VCI response packet for data read miss");
+                r_rsp_cpt = r_rsp_cpt + 1;
+                r_dcache_miss_buf[r_rsp_cpt] = (data_t)p_vci_ini_d.rdata.read();
+                if ( p_vci_ini_d.reop.read() )
+                {
+                    assert(r_rsp_cpt == m_dcache_words - 1 &&
+                       "illegal VCI response packet for instruction miss");
+                    r_rsp_data_ok = true;
+                    r_rsp_fsm = RSP_IDLE;
+                }
+                if ( p_vci_ini_d.rerror.read() != vci_param::ERR_NORMAL ) r_rsp_data_error = true;
+            }
+            break;
+
+        case RSP_DATA_UNC:
+            if ( p_vci_ini_d.rspval.read() )
+            {
+                assert(p_vci_ini_d.reop.read() &&
+                   "illegal VCI response packet for uncached read data");
+                r_dcache_miss_buf[0] = (data_t)p_vci_ini_d.rdata.read();
+                r_rsp_data_ok = true;
+                r_rsp_fsm = RSP_IDLE;
+                if ( p_vci_ini_d.rerror.read() != vci_param::ERR_NORMAL ) r_rsp_data_error = true;
+            }
+            break;
+        } // end switch r_rsp_fsm
+
+    } // end transition()
+
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(void)::genMoore()
+    //////////////////////////////////////////////////////////////////////////////////
+    {
+        // Coherence network (initiator port)
+
+        switch ( r_cleanup_fsm.read() ) {
+
+            case CLEANUP_CMD:
+                p_vci_ini_c.rspack  = false;
+                p_vci_ini_c.cmdval  = r_icache_cleanup_req || r_dcache_cleanup_req;
+                if ( r_dcache_cleanup_req )
+                {
+                    p_vci_ini_c.address =  r_dcache_cleanup_line.read() * m_dcache_words * 4;
+                    p_vci_ini_c.trdid   = 0;
+                }
+                else
+                {
+                    p_vci_ini_c.address =  r_icache_cleanup_line.read() * (m_icache_words << 2); //* 4;
+                    p_vci_ini_c.trdid   = 1;
+                }
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0xF;
+                p_vci_ini_c.plen   = 4;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = m_srcid_c;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = true;
+                break;
+
+           case CLEANUP_DCACHE_RSP:
+                p_vci_ini_c.rspack  = true;
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.trdid  = 0; 
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+                break;
+
+           case CLEANUP_ICACHE_RSP:
+                p_vci_ini_c.rspack  = true;
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.trdid  = 0; 
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+                break;
+           } // end switch r_cleanup_fsm
+
+        // Direct network initiator response
+
+        p_vci_ini_d.rspack = ( r_rsp_fsm != RSP_IDLE );
+
+        // Direct network initiator command
+
+        switch ( r_cmd_fsm ) {
+
+            case CMD_IDLE:
+                p_vci_ini_d.cmdval  = false;
+                p_vci_ini_d.address = 0;
+                p_vci_ini_d.wdata   = 0;
+                p_vci_ini_d.be      = 0;
+                p_vci_ini_d.plen    = 0;
+                p_vci_ini_d.cmd     = vci_param::CMD_WRITE;
+                p_vci_ini_d.trdid   = 0;
+                p_vci_ini_d.pktid   = 0;
+                p_vci_ini_d.srcid   = 0;
+                p_vci_ini_d.cons    = false;
+                p_vci_ini_d.wrap    = false;
+                p_vci_ini_d.contig  = false;
+                p_vci_ini_d.clen    = 0;
+                p_vci_ini_d.cfixed  = false;
+                p_vci_ini_d.eop     = false;
+                break;
+
+            case CMD_DATA_WRITE:
+                p_vci_ini_d.cmdval  = true;
+                p_vci_ini_d.address = r_wbuf.getAddress(r_cmd_cpt)&~0x3;
+                p_vci_ini_d.wdata   = r_wbuf.getData(r_cmd_cpt);
+                p_vci_ini_d.be      = r_wbuf.getBe(r_cmd_cpt);
+                p_vci_ini_d.plen    = (r_cmd_max - r_cmd_min + 1)<<2;
+                p_vci_ini_d.cmd     = vci_param::CMD_WRITE;
+                p_vci_ini_d.pktid   = 0;
+                p_vci_ini_d.trdid   = r_wbuf.getIndex() + m_wbuf_nlines;
+                p_vci_ini_d.srcid   = m_srcid_d;
+                p_vci_ini_d.cons    = false;
+                p_vci_ini_d.wrap    = false;
+                p_vci_ini_d.contig  = true;
+                p_vci_ini_d.clen    = 0;
+                p_vci_ini_d.cfixed  = false;
+                p_vci_ini_d.eop     = (r_cmd_cpt == r_cmd_max);
+                break;
+
+            case CMD_DATA_UNC:
+                p_vci_ini_d.cmdval = true;
+                p_vci_ini_d.address = r_dcache_addr_save & ~0x3;
+                switch( r_dcache_type_save ) {
+                    case iss_t::DATA_READ:
+                        p_vci_ini_d.wdata = 0;
+                        p_vci_ini_d.be  = r_dcache_be_save.read();
+                        p_vci_ini_d.cmd = vci_param::CMD_READ;
+                        break;
+                    case iss_t::DATA_LL:
+                        p_vci_ini_d.wdata = 0;
+                        p_vci_ini_d.be  = 0xF;
+                        p_vci_ini_d.cmd = vci_param::CMD_LOCKED_READ;
+                        break;
+                    case iss_t::DATA_SC:
+                        p_vci_ini_d.wdata = r_dcache_wdata_save.read();
+                        p_vci_ini_d.be  = 0xF;
+                        p_vci_ini_d.cmd = vci_param::CMD_STORE_COND;
+                        break;
+                    default:
+                        assert("this should not happen");
+                }
+                p_vci_ini_d.plen = 4;
+                p_vci_ini_d.trdid  = TYPE_DATA_UNC;
+                p_vci_ini_d.pktid  = 0;
+                p_vci_ini_d.srcid  = m_srcid_d;
+                p_vci_ini_d.cons   = false;
+                p_vci_ini_d.wrap   = false;
+                p_vci_ini_d.contig = true;
+                p_vci_ini_d.clen   = 0;
+                p_vci_ini_d.cfixed = false;
+                p_vci_ini_d.eop    = true;
+                break;
+
+            case CMD_DATA_MISS:
+                p_vci_ini_d.cmdval = true;
+                p_vci_ini_d.address = r_dcache_addr_save.read() & (addr_t) m_dcache_yzmask;
+                p_vci_ini_d.be     = 0xF;
+                p_vci_ini_d.plen   = m_dcache_words << 2;
+                p_vci_ini_d.cmd    = vci_param::CMD_READ;
+                p_vci_ini_d.trdid  = TYPE_DATA_MISS;
+                p_vci_ini_d.pktid  = 0;
+                p_vci_ini_d.srcid  = m_srcid_d;
+                p_vci_ini_d.cons   = false;
+                p_vci_ini_d.wrap   = false;
+                p_vci_ini_d.contig = true;
+                p_vci_ini_d.clen   = 0;
+                p_vci_ini_d.cfixed = false;
+                p_vci_ini_d.eop    = true;
+                break;
+
+            case CMD_INS_MISS:
+                p_vci_ini_d.cmdval = true;
+                p_vci_ini_d.address = r_icache_addr_save & (addr_t) m_icache_yzmask;
+                p_vci_ini_d.be     = 0xF;
+                p_vci_ini_d.plen   = m_icache_words << 2;
+                p_vci_ini_d.cmd    = vci_param::CMD_READ;
+                p_vci_ini_d.trdid  = TYPE_INS_MISS;
+                p_vci_ini_d.pktid  = 0;
+                p_vci_ini_d.srcid  = m_srcid_d;
+                p_vci_ini_d.cons   = false;
+                p_vci_ini_d.wrap   = false;
+                p_vci_ini_d.contig = true;
+                p_vci_ini_d.clen   = 0;
+                p_vci_ini_d.cfixed = false;
+                p_vci_ini_d.eop    = true;
+                break;
+
+            case CMD_INS_UNC:
+                p_vci_ini_d.cmdval = true;
+                p_vci_ini_d.address = r_icache_addr_save.read() & ~0x3;
+                p_vci_ini_d.be     = 0xF;
+                p_vci_ini_d.plen   = 4;
+                p_vci_ini_d.cmd    = vci_param::CMD_READ;
+                p_vci_ini_d.trdid  = TYPE_INS_UNC;
+                p_vci_ini_d.pktid  = 0;
+                p_vci_ini_d.srcid  = m_srcid_d;
+                p_vci_ini_d.cons   = false;
+                p_vci_ini_d.wrap   = false;
+                p_vci_ini_d.contig = true;
+                p_vci_ini_d.clen   = 0;
+                p_vci_ini_d.cfixed = false;
+                p_vci_ini_d.eop    = true;
+                break;
+        } // end switch r_cmd_fsm
+
+        // coherence network : target port
+
+        switch ( r_tgt_fsm.read() ) {
+
+            case TGT_IDLE:
+            case TGT_UPDT_WORD:
+            case TGT_UPDT_DATA:
+                p_vci_tgt_c.cmdack  = true;
+                p_vci_tgt_c.rspval  = false;
+                break;
+
+            case TGT_RSP_BROADCAST:
+                p_vci_tgt_c.cmdack  = false;
+                p_vci_tgt_c.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() 
+                                       &&  ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
+                p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
+                p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
+                p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
+                p_vci_tgt_c.rdata   = 0;
+                p_vci_tgt_c.rerror  = 0;
+                p_vci_tgt_c.reop    = true;
+                break;
+
+            case TGT_RSP_ICACHE:
+                p_vci_tgt_c.cmdack  = false;
+                p_vci_tgt_c.rspval  = !r_tgt_icache_req.read() && r_tgt_icache_rsp.read();
+                p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
+                p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
+                p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
+                p_vci_tgt_c.rdata   = 0;
+                p_vci_tgt_c.rerror  = 0;
+                p_vci_tgt_c.reop    = true;
+                break;
+
+            case TGT_RSP_DCACHE:
+                p_vci_tgt_c.cmdack  = false;
+                p_vci_tgt_c.rspval  = !r_tgt_dcache_req.read() && r_tgt_dcache_rsp.read();
+                p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
+                p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
+                p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
+                p_vci_tgt_c.rdata   = 0;
+                p_vci_tgt_c.rerror  = 0;
+                p_vci_tgt_c.reop    = true;
+                break;
+
+            case TGT_REQ_BROADCAST:
+            case TGT_REQ_ICACHE:
+            case TGT_REQ_DCACHE:
+                p_vci_tgt_c.cmdack  = false;
+                p_vci_tgt_c.rspval  = false;
+                break;
+
+        } // end switch TGT_FSM
+    } // end genMoore()
+
+}} // end namespace
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
+
Index: trunk/modules/vci_cc_xcache_wrapper_v1/caba/metadata/vci_cc_xcache_wrapper_v1.sd
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v1/caba/metadata/vci_cc_xcache_wrapper_v1.sd	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper_v1/caba/metadata/vci_cc_xcache_wrapper_v1.sd	(revision 2)
@@ -0,0 +1,55 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_cc_xcache_wrapper_v1',
+	classname = 'soclib::caba::VciCcXCacheWrapperV1',
+	tmpl_parameters = [
+		parameter.Module('vci_param', default = 'caba:vci_param'),
+		parameter.Module('iss_t'),
+		],
+	header_files = [
+		'../source/include/vci_cc_xcache_wrapper_v1.h',
+		],
+	implementation_files = [
+		'../source/src/vci_cc_xcache_wrapper_v1.cpp',
+		],
+	uses = [
+		Uses('caba:base_module'),
+		Uses('common:mapping_table'),
+		Uses('common:iss2'),
+		Uses('caba:write_buffer'),
+		Uses('caba:generic_cache', addr_t = 'uint32_t'),
+		],
+	ports = [
+		Port('caba:vci_initiator', 'p_vci_ini_rw'),
+    Port('caba:vci_initiator', 'p_vci_ini_c'),
+		Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:bit_in', 'p_irq', parameter.Constant('n_irq')),
+		Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+		Port('caba:clock_in', 'p_clk', auto = 'clock'),
+		],
+	instance_parameters = [
+		parameter.Int('proc_id'),
+		parameter.Module('mtp', 'common:mapping_table'),
+		parameter.Module('mtc', 'common:mapping_table'),
+		parameter.IntTab('initiator_rw_index'),
+		parameter.IntTab('initiator_c_index'),
+		parameter.IntTab('target_index'),
+		parameter.Int('icache_ways'),
+		parameter.Int('icache_sets'),
+		parameter.Int('icache_words'),
+		parameter.Int('dcache_ways'),
+		parameter.Int('dcache_sets'),
+		parameter.Int('dcache_words'),
+		],
+	   extensions = [
+		'dsx:get_ident=initiator_index:p_vci_ini_rw',
+		'dsx:cpu=wrapper:iss_t',
+		'dsx:mapping_type=processor:proc_id',
+		],
+)
+
+
Index: trunk/modules/vci_cc_xcache_wrapper_v1/caba/source/include/vci_cc_xcache_wrapper_v1.h
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v1/caba/source/include/vci_cc_xcache_wrapper_v1.h	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper_v1/caba/source/include/vci_cc_xcache_wrapper_v1.h	(revision 2)
@@ -0,0 +1,296 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain
+ */
+ 
+#ifndef SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_V1_H
+#define SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_V1_H
+
+#include <inttypes.h>
+#include <systemc>
+#include "caba_base_module.h"
+#include "write_buffer.h"
+#include "generic_cache.h"
+#include "vci_initiator.h"
+#include "vci_target.h"
+#include "mapping_table.h"
+#include "static_assert.h"
+
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+////////////////////////////////////////////
+template<typename vci_param, typename iss_t>
+class VciCcXCacheWrapperV1
+///////////////////////////////////////////
+    : public soclib::caba::BaseModule
+{
+    typedef sc_dt::sc_uint<40> addr_40;
+    typedef uint32_t    data_t;
+    typedef uint32_t    tag_t;
+    typedef uint32_t    be_t;
+    typedef typename vci_param::fast_addr_t vci_addr_t;
+    enum dcache_fsm_state_e {
+        DCACHE_IDLE,
+        DCACHE_WRITE_UPDT,
+        DCACHE_WRITE_REQ,
+        DCACHE_MISS_WAIT,
+        DCACHE_MISS_UPDT,
+        DCACHE_UNC_WAIT,
+        DCACHE_INVAL,
+        DCACHE_ERROR,
+        DCACHE_CC_CHECK,
+        DCACHE_CC_INVAL,
+        DCACHE_CC_UPDT,
+        DCACHE_CC_CLEANUP,
+    };
+
+    enum icache_fsm_state_e {
+        ICACHE_IDLE,
+        ICACHE_MISS_WAIT,
+        ICACHE_MISS_UPDT,
+        ICACHE_UNC_WAIT,
+        ICACHE_ERROR,
+        ICACHE_CC_CHECK,
+        ICACHE_CC_INVAL,
+        ICACHE_CC_UPDT,
+        ICACHE_CC_CLEANUP 
+    };
+
+    enum cmd_fsm_state_e {
+        CMD_IDLE,
+        CMD_INS_MISS,
+        CMD_INS_UNC,
+        CMD_DATA_MISS,
+        CMD_DATA_UNC,
+        CMD_DATA_WRITE,
+        CMD_INS_CLEANUP,
+        CMD_DATA_CLEANUP,
+    };
+
+    enum rsp_fsm_state_e {
+        RSP_IDLE,
+        RSP_INS_MISS,
+        RSP_INS_UNC,
+        RSP_DATA_MISS,
+        RSP_DATA_UNC,
+        RSP_DATA_WRITE,
+        RSP_INS_CLEANUP,
+        RSP_DATA_CLEANUP,
+    };
+
+    enum tgt_fsm_state_e {
+        TGT_IDLE,
+        TGT_UPDT_WORD,
+        TGT_UPDT_DATA,
+        TGT_REQ_BROADCAST,
+        TGT_REQ_ICACHE,
+        TGT_REQ_DCACHE,
+        TGT_RSP_BROADCAST,
+        TGT_RSP_ICACHE,
+        TGT_RSP_DCACHE,
+    };
+
+public:
+
+    // PORTS
+    sc_in<bool>                             p_clk;
+    sc_in<bool>                             p_resetn;
+    sc_in<bool>                             p_irq[iss_t::n_irq];
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_rw;
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_c;
+    soclib::caba::VciTarget<vci_param>      p_vci_tgt;
+
+private:
+
+    // STRUCTURAL PARAMETERS
+    const soclib::common::AddressDecodingTable<vci_addr_t, bool>    m_cacheability_table;
+    const soclib::common::Segment                                   m_segment;
+    iss_t               m_iss;
+    const uint32_t      m_srcid_rw;   
+    const uint32_t      m_srcid_c;   
+    
+    const size_t        m_dcache_ways;
+    const size_t        m_dcache_words;
+    const size_t        m_dcache_yzmask;
+    const size_t        m_icache_ways;
+    const size_t        m_icache_words;
+    const size_t        m_icache_yzmask;
+
+    // REGISTERS
+    sc_signal<int>          r_dcache_fsm;
+    sc_signal<int>          r_dcache_fsm_save;
+    sc_signal<addr_40>      r_dcache_addr_save;
+    sc_signal<data_t>       r_dcache_wdata_save;
+    sc_signal<data_t>       r_dcache_rdata_save;
+    sc_signal<int>          r_dcache_type_save;
+    sc_signal<be_t>         r_dcache_be_save;
+    sc_signal<bool>         r_dcache_cached_save;
+    sc_signal<bool>         r_dcache_cleanup_req;
+    sc_signal<addr_40>      r_dcache_cleanup_line;
+    sc_signal<bool>         r_dcache_miss_req;
+    sc_signal<bool>         r_dcache_unc_req;
+    sc_signal<bool>         r_dcache_write_req;
+    sc_signal<bool>         r_dcache_inval_rsp;
+
+    sc_signal<int>          r_icache_fsm;
+    sc_signal<int>          r_icache_fsm_save;
+    sc_signal<addr_40>      r_icache_addr_save;
+    sc_signal<bool>         r_icache_miss_req;
+    sc_signal<bool>         r_icache_unc_req;
+    sc_signal<bool>         r_icache_cleanup_req;
+    sc_signal<addr_40>      r_icache_cleanup_line;
+    sc_signal<bool>         r_icache_inval_rsp;
+
+    sc_signal<int>          r_vci_cmd_fsm;
+    sc_signal<size_t>       r_vci_cmd_min;       
+    sc_signal<size_t>       r_vci_cmd_max;       
+    sc_signal<size_t>       r_vci_cmd_cpt;       
+      
+    sc_signal<int>          r_vci_rsp_fsm;
+    sc_signal<bool>         r_vci_rsp_ins_error;    
+    sc_signal<bool>         r_vci_rsp_data_error;    
+    sc_signal<size_t>       r_vci_rsp_cpt;  
+
+    data_t                  *r_icache_miss_buf;    
+    data_t                  *r_dcache_miss_buf;    
+    sc_signal<bool>         r_icache_buf_unc_valid;
+    sc_signal<bool>         r_dcache_buf_unc_valid;
+
+    data_t                  *r_tgt_buf;
+    be_t                    *r_tgt_be;
+
+    sc_signal<int>          r_vci_tgt_fsm;
+    sc_signal<addr_40>       r_tgt_addr;
+    sc_signal<size_t>       r_tgt_word;
+    sc_signal<bool>         r_tgt_update;
+    sc_signal<bool>         r_data_update; // 0 : update ins; 1 : update data
+    sc_signal<bool>         r_tgt_brdcast;
+    sc_signal<size_t>       r_tgt_srcid;
+    sc_signal<size_t>       r_tgt_pktid;
+    sc_signal<size_t>       r_tgt_trdid;
+    sc_signal<size_t>       r_tgt_plen;
+    sc_signal<bool>         r_tgt_icache_req;
+    sc_signal<bool>         r_tgt_dcache_req;
+    sc_signal<bool>         r_tgt_icache_rsp;
+    sc_signal<bool>         r_tgt_dcache_rsp;
+
+    WriteBuffer<addr_40>        r_wbuf;
+    GenericCache<vci_addr_t>    r_icache;
+    GenericCache<vci_addr_t>    r_dcache;
+
+    // Activity counters
+    uint32_t m_cpt_dcache_data_read;        // DCACHE DATA READ
+    uint32_t m_cpt_dcache_data_write;       // DCACHE DATA WRITE
+    uint32_t m_cpt_dcache_dir_read;         // DCACHE DIR READ
+    uint32_t m_cpt_dcache_dir_write;        // DCACHE DIR WRITE
+
+    uint32_t m_cpt_icache_data_read;        // ICACHE DATA READ
+    uint32_t m_cpt_icache_data_write;       // ICACHE DATA WRITE
+    uint32_t m_cpt_icache_dir_read;         // ICACHE DIR READ
+    uint32_t m_cpt_icache_dir_write;        // ICACHE DIR WRITE
+
+    uint32_t m_cpt_cc_update;               // number of coherence update packets 
+    uint32_t m_cpt_cc_inval;                // number of coherence inval packets
+
+    uint32_t m_cpt_frz_cycles;	            // number of cycles where the cpu is frozen
+    uint32_t m_cpt_total_cycles;	        // total number of cycles 
+
+    uint32_t m_cpt_read;                    // total number of read instructions
+    uint32_t m_cpt_write;                   // total number of write instructions
+    uint32_t m_cpt_data_miss;               // number of read miss
+    uint32_t m_cpt_ins_miss;                // number of instruction miss
+    uint32_t m_cpt_unc_read;                // number of read uncached
+    uint32_t m_cpt_write_cached;            // number of cached write
+
+    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
+    uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
+    uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
+    uint32_t m_cost_ins_miss_frz;           // number of frozen cycles related to ins miss
+
+    uint32_t m_cpt_imiss_transaction;       // number of VCI instruction miss transactions
+    uint32_t m_cpt_dmiss_transaction;       // number of VCI data miss transactions
+    uint32_t m_cpt_unc_transaction;         // number of VCI uncached read transactions
+    uint32_t m_cpt_write_transaction;       // number of VCI write transactions
+
+    uint32_t m_cost_imiss_transaction;      // cumulated duration for VCI IMISS transactions
+    uint32_t m_cost_dmiss_transaction;      // cumulated duration for VCI DMISS transactions
+    uint32_t m_cost_unc_transaction;        // cumulated duration for VCI UNC transactions
+    uint32_t m_cost_write_transaction;      // cumulated duration for VCI WRITE transactions
+    uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions
+
+protected:
+    SC_HAS_PROCESS(VciCcXCacheWrapperV1);
+
+public:
+
+    VciCcXCacheWrapperV1(
+                       sc_module_name insname,
+                       int proc_id,
+                       const soclib::common::MappingTable &mtp,
+                       const soclib::common::MappingTable &mtc,
+                       const soclib::common::IntTab &initiator_index_rw,
+                       const soclib::common::IntTab &initiator_index_c,
+                       const soclib::common::IntTab &target_index,
+                       size_t icache_ways,
+                       size_t icache_sets,
+                       size_t icache_words,
+                       size_t dcache_ways,
+                       size_t dcache_sets,
+                       size_t dcache_words );
+
+    ~VciCcXCacheWrapperV1();
+
+    void print_cpi();
+    void print_stats();
+
+private:
+
+    void transition();
+    void genMoore();
+
+    soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC);
+    soclib_static_assert((int)iss_t::SC_NOT_ATOMIC == (int)vci_param::STORE_COND_NOT_ATOMIC);
+};
+
+}}
+
+#endif /* SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_V1_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
Index: trunk/modules/vci_cc_xcache_wrapper_v1/caba/source/src/vci_cc_xcache_wrapper_v1.cpp
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v1/caba/source/src/vci_cc_xcache_wrapper_v1.cpp	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper_v1/caba/source/src/vci_cc_xcache_wrapper_v1.cpp	(revision 2)
@@ -0,0 +1,1938 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain 
+ *              eric.guthmuller@polytechnique.edu 
+ *              nipo
+ *              malek <abdelmalek.si-merabet@lip6.fr> 
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+// History
+// - 25/04/2008
+//   The existing vci_xcache component has been extended to include 
+//   a VCI target port to support a directory based coherence protocol.
+//   Two types of packets can be send by the L2 cache to the L1 cache
+//   * INVALIDATE packets : length = 1
+//   * UPDATE packets : length = n + 2   
+//   The CLEANUP packets are sent by the L1 cache to the L2 cache, 
+//   to signal a replaced cache line.
+// - 12/08/2008
+//   The vci_cc_xcache_wrapper component instanciates directly the processsor 
+//   iss, in order to supress the processor/cache interface.
+//   According to the VCI advanced specification, this component uses one 
+//   word VCI CMD packets for MISS transactions, and accept one word VCI RSP
+//   packets for Write burst  transactions.
+//   The write buffer has been modified to use the WriteBuffer object. 
+//   A VCI write burst is constructed when two conditions are satisfied :
+//   The processor make strictly successive write requests, and they are
+//   in the same cache line. The write buffer performs re-ordering, to
+//   respect the contiguous addresses VCI constraint. In case of several
+//   WRITE_WORD requests in the same word, only the last request is conserved.
+//   In case of several WRITE_HALF or WRITE_WORD requests in the same word,
+//   the requests are merged in the same word. In case of uncached write
+//   requests, each request is transmited as a single VCI transaction.
+//   Both the data & instruction caches can be flushed in one single cycle.
+// 08/12/2009
+//   adding update instruction (code X"C")  
+///////////////////////////////////////////////////////////////////////////////
+
+#include <cassert>
+#include "arithmetics.h"
+#include "../include/vci_cc_xcache_wrapper_v1.h"
+
+//#define DEBUG_CC_XCACHE_WRAPPER 1
+
+namespace soclib { 
+namespace caba {
+
+#if DEBUG_CC_XCACHE_WRAPPER
+    namespace {
+        const char *dcache_fsm_state_str[] = {
+            "DCACHE_IDLE",
+            "DCACHE_WRITE_UPDT",
+            "DCACHE_WRITE_REQ",
+            "DCACHE_MISS_WAIT",
+            "DCACHE_MISS_UPDT",
+            "DCACHE_UNC_WAIT",
+            "DCACHE_INVAL",
+            "DCACHE_ERROR",
+            "DCACHE_CC_CHECK",
+            "DCACHE_CC_INVAL",
+            "DCACHE_CC_UPDT",
+            "DCACHE_CC_NOP",
+            "DCACHE_CC_CLEANUP",
+        };
+        const char *icache_fsm_state_str[] = {
+            "ICACHE_IDLE",
+            "ICACHE_MISS_WAIT",
+            "ICACHE_MISS_UPDT",
+            "ICACHE_UNC_WAIT",
+            "ICACHE_ERROR",
+            "ICACHE_CC_CHECK",
+            "ICACHE_CC_INVAL",
+            "ICACHE_CC_UPDT",
+            "ICACHE_CC_CLEANUP", 
+        };
+        const char *cmd_fsm_state_str[] = {
+            "CMD_IDLE",
+            "CMD_INS_MISS",
+            "CMD_INS_UNC",
+            "CMD_DATA_MISS",
+            "CMD_DATA_UNC",
+            "CMD_DATA_WRITE",
+            "CMD_INS_CLEANUP",
+            "CMD_DATA_CLEANUP",
+        };
+        const char *rsp_fsm_state_str[] = {
+            "RSP_IDLE",
+            "RSP_INS_MISS",
+            "RSP_INS_UNC",
+            "RSP_DATA_MISS",
+            "RSP_DATA_UNC",
+            "RSP_DATA_WRITE",
+            "RSP_INS_CLEANUP",
+            "RSP_DATA_CLEANUP",
+        };
+        const char *tgt_fsm_state_str[] = {
+            "TGT_IDLE",
+            "TGT_UPDT_WORD",
+            "TGT_UPDT_DATA",
+            "TGT_REQ_BROADCAST",
+            "TGT_REQ_ICACHE",
+            "TGT_REQ_DCACHE",
+            "TGT_RSP_BROADCAST",
+            "TGT_RSP_ICACHE",
+            "TGT_RSP_DCACHE",
+        };
+    }
+#endif
+
+#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXCacheWrapperV1<vci_param, iss_t>
+
+    using soclib::common::uint32_log2;
+
+    /////////////////////////////////
+    tmpl(/**/)::VciCcXCacheWrapperV1(
+            /////////////////////////////////
+            sc_module_name name,
+            int proc_id,
+            const soclib::common::MappingTable &mtp,
+            const soclib::common::MappingTable &mtc,
+            const soclib::common::IntTab &initiator_index_rw,
+            const soclib::common::IntTab &initiator_index_c,
+            const soclib::common::IntTab &target_index,
+            size_t icache_ways,
+            size_t icache_sets,
+            size_t icache_words,
+            size_t dcache_ways,
+            size_t dcache_sets,
+            size_t dcache_words )
+        : 
+            soclib::caba::BaseModule(name),
+
+            p_clk("clk"),
+            p_resetn("resetn"),
+            p_vci_ini_rw("vci_ini_rw"),
+            p_vci_ini_c("vci_ini_c"),
+            p_vci_tgt("vci_tgt"),
+
+            m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()),
+            m_segment(mtc.getSegment(target_index)),
+            m_iss(this->name(), proc_id),
+            m_srcid_rw(mtp.indexForId(initiator_index_rw)),
+            m_srcid_c(mtc.indexForId(initiator_index_c)),
+
+            m_dcache_ways(dcache_ways),
+            m_dcache_words(dcache_words),
+            m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
+            m_icache_ways(icache_ways),
+            m_icache_words(icache_words),
+            m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
+
+            r_dcache_fsm("r_dcache_fsm"),
+            r_dcache_fsm_save("r_dcache_fsm_save"),
+            r_dcache_addr_save("r_dcache_addr_save"),
+            r_dcache_wdata_save("r_dcache_wdata_save"),
+            r_dcache_rdata_save("r_dcache_rdata_save"),
+            r_dcache_type_save("r_dcache_type_save"),
+            r_dcache_be_save("r_dcache_be_save"),
+            r_dcache_cached_save("r_dcache_cached_save"),
+            r_dcache_cleanup_req("r_dcache_cleanup_req"),
+            r_dcache_cleanup_line("r_dcache_cleanup_line"),
+            r_dcache_miss_req("r_dcache_miss_req"),
+            r_dcache_unc_req("r_dcache_unc_req"),
+            r_dcache_write_req("r_dcache_write_req"),
+
+            r_icache_fsm("r_icache_fsm"),
+            r_icache_fsm_save("r_icache_fsm_save"),
+            r_icache_addr_save("r_icache_addr_save"),
+            r_icache_miss_req("r_icache_miss_req"),
+            r_icache_cleanup_req("r_icache_cleanup_req"),
+            r_icache_cleanup_line("r_icache_cleanup_line"),
+
+            r_vci_cmd_fsm("r_vci_cmd_fsm"),
+            r_vci_cmd_min("r_vci_cmd_min"),
+            r_vci_cmd_max("r_vci_cmd_max"),
+            r_vci_cmd_cpt("r_vci_cmd_cpt"),
+
+            r_vci_rsp_fsm("r_vci_rsp_fsm"),
+            r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
+            r_vci_rsp_data_error("r_vci_rsp_data_error"),
+            r_vci_rsp_cpt("r_vci_rsp_cpt"),
+
+            r_icache_buf_unc_valid("r_icache_buf_unc_valid"),
+            r_dcache_buf_unc_valid("r_dcache_buf_unc_valid"),
+
+            r_vci_tgt_fsm("r_vci_tgt_fsm"),
+            r_tgt_addr("r_tgt_addr"),
+            r_tgt_word("r_tgt_word"),
+            r_tgt_update("r_tgt_update"),
+            r_data_update("r_data_update"),
+            r_tgt_srcid("r_tgt_srcid"),
+            r_tgt_pktid("r_tgt_pktid"),
+            r_tgt_trdid("r_tgt_trdid"),
+            r_tgt_icache_req("r_tgt_icache_req"),
+            r_tgt_dcache_req("r_tgt_dcache_req"),
+
+            r_wbuf("r_wbuf", dcache_words ),
+            r_icache("icache", icache_ways, icache_sets, icache_words),
+            r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
+
+            {
+                r_icache_miss_buf = new data_t[icache_words];
+                r_dcache_miss_buf = new data_t[dcache_words];
+                r_tgt_buf         = new data_t[dcache_words];
+                r_tgt_be          = new be_t[dcache_words];
+
+                SC_METHOD(transition);
+                dont_initialize();
+                sensitive << p_clk.pos();
+
+                SC_METHOD(genMoore);
+                dont_initialize();
+                sensitive << p_clk.neg();
+
+                typename iss_t::CacheInfo cache_info;
+                cache_info.has_mmu = false;
+                cache_info.icache_line_size = icache_words*sizeof(data_t);
+                cache_info.icache_assoc = icache_ways;
+                cache_info.icache_n_lines = icache_sets;
+                cache_info.dcache_line_size = dcache_words*sizeof(data_t);
+                cache_info.dcache_assoc = dcache_ways;
+                cache_info.dcache_n_lines = dcache_sets;
+                m_iss.setCacheInfo(cache_info);
+
+            } // end constructor
+
+    ///////////////////////////////////
+    tmpl(/**/)::~VciCcXCacheWrapperV1()
+        ///////////////////////////////////
+    {
+        delete [] r_icache_miss_buf;
+        delete [] r_dcache_miss_buf;
+        delete [] r_tgt_be;
+        delete [] r_tgt_buf;
+    }
+
+    ////////////////////////
+    tmpl(void)::print_cpi()
+        ////////////////////////
+    {
+        std::cout << "CPU " << m_srcid_rw << " : CPI = " 
+            << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
+    }
+    ////////////////////////
+    tmpl(void)::print_stats()
+        ////////////////////////
+    {
+        float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
+        std::cout << "------------------------------------" << std:: dec << std::endl;
+        std::cout << "CPU " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
+        std::cout << "- CPI                = " << (float)m_cpt_total_cycles/run_cycles << std::endl ;
+        std::cout << "- READ RATE          = " << (float)m_cpt_read/run_cycles << std::endl ;
+        std::cout << "- WRITE RATE         = " << (float)m_cpt_write/run_cycles << std::endl;
+        std::cout << "- UNCACHED READ RATE = " << (float)m_cpt_unc_read/m_cpt_read << std::endl ;
+        std::cout << "- CACHED WRITE RATE  = " << (float)m_cpt_write_cached/m_cpt_write << std::endl ;
+        std::cout << "- IMISS_RATE         = " << (float)m_cpt_ins_miss/run_cycles << std::endl;
+        std::cout << "- DMISS RATE         = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl ;
+        std::cout << "- INS MISS COST      = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl;
+        std::cout << "- IMISS TRANSACTION  = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl;
+        std::cout << "- DMISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl;
+        std::cout << "- DMISS TRANSACTION  = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl;
+        std::cout << "- UNC COST           = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl;
+        std::cout << "- UNC TRANSACTION    = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl;
+        std::cout << "- WRITE COST         = " << (float)m_cost_write_frz/m_cpt_write << std::endl;
+        std::cout << "- WRITE TRANSACTION  = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl;
+        std::cout << "- WRITE LENGTH       = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl;
+    }
+
+    //////////////////////////
+    tmpl(void)::transition()
+        //////////////////////////
+    {
+        if ( ! p_resetn.read() ) {
+
+            m_iss.reset();
+
+            // FSM states
+            r_dcache_fsm = DCACHE_IDLE;
+            r_icache_fsm = ICACHE_IDLE;
+            r_vci_cmd_fsm = CMD_IDLE;
+            r_vci_rsp_fsm = RSP_IDLE;
+            r_vci_tgt_fsm = TGT_IDLE;
+
+            // write buffer & caches
+            r_wbuf.reset();
+            r_icache.reset();
+            r_dcache.reset();
+
+            // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI  FSMs
+            r_icache_miss_req    = false;
+            r_icache_unc_req     = false;
+            r_icache_cleanup_req = false;
+            r_dcache_miss_req    = false;
+            r_dcache_unc_req     = false;
+            r_dcache_write_req   = false;
+            r_dcache_cleanup_req = false;
+
+            // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
+            r_tgt_icache_req     = false;
+            r_tgt_dcache_req     = false;
+
+            // internal messages in DCACHE et ICACHE FSMs
+            r_icache_inval_rsp   = false;
+            r_dcache_inval_rsp   = false;
+
+            // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs
+            r_dcache_buf_unc_valid = false;
+            r_icache_buf_unc_valid = false;
+            r_vci_rsp_data_error   = false;
+            r_vci_rsp_ins_error    = false;
+
+            // activity counters
+            m_cpt_dcache_data_read  = 0;
+            m_cpt_dcache_data_write = 0;
+            m_cpt_dcache_dir_read  = 0;
+            m_cpt_dcache_dir_write = 0;
+            m_cpt_icache_data_read  = 0;
+            m_cpt_icache_data_write = 0;
+            m_cpt_icache_dir_read  = 0;
+            m_cpt_icache_dir_write = 0;
+
+            m_cpt_cc_update = 0;
+            m_cpt_cc_inval = 0;
+
+            m_cpt_frz_cycles = 0;
+            m_cpt_total_cycles = 0;
+
+            m_cpt_read = 0;
+            m_cpt_write = 0;
+            m_cpt_data_miss = 0;
+            m_cpt_ins_miss = 0;
+            m_cpt_unc_read = 0;
+            m_cpt_write_cached = 0;
+
+            m_cost_write_frz = 0;
+            m_cost_data_miss_frz = 0;
+            m_cost_unc_read_frz = 0;
+            m_cost_ins_miss_frz = 0;
+
+            m_cpt_imiss_transaction = 0;
+            m_cpt_dmiss_transaction = 0;
+            m_cpt_unc_transaction = 0;
+            m_cpt_write_transaction = 0;
+
+            m_cost_imiss_transaction = 0;
+            m_cost_dmiss_transaction = 0;
+            m_cost_unc_transaction = 0;
+            m_cost_write_transaction = 0;
+            m_length_write_transaction = 0;
+
+            return;
+        }
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << "--------------------------------------------" << std::endl;
+        std::cout << std::dec << "CC_XCACHE_WRAPPER " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
+        std::cout             << " tgt fsm    = " << tgt_fsm_state_str[r_vci_tgt_fsm] << std::endl
+            << " dcache fsm = " << dcache_fsm_state_str[r_dcache_fsm] << std::endl
+            << " icache fsm = " << icache_fsm_state_str[r_icache_fsm] << std::endl
+            << " cmd fsm    = " << cmd_fsm_state_str[r_vci_cmd_fsm] << std::endl
+            << " rsp fsm    = " << rsp_fsm_state_str[r_vci_rsp_fsm] << std::endl;
+#endif
+
+        m_cpt_total_cycles++;
+
+        /////////////////////////////////////////////////////////////////////
+        // The TGT_FSM controls the following ressources:
+        // - r_vci_tgt_fsm
+        // - r_tgt_buf[nwords]
+        // - r_tgt_be[nwords]
+        // - r_tgt_update
+        // - r_data_update
+        // - r_tgt_word
+        // - r_tgt_addr
+        // - r_tgt_srcid
+        // - r_tgt_trdid
+        // - r_tgt_pktid
+        // All VCI commands must be CMD_WRITE.
+        // If the VCI address offset is null, the command is an invalidate 
+        // request. It is an update request otherwise.
+        // The VCI_TGT FSM stores the external request arguments in the
+        // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 
+        // & r_tgt_dcache_req flip-flops to signal the external request to 
+        // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
+        // of the update or invalidate request in the RSP state.
+        // -  for an invalidate request the VCI packet length is 1 word.
+        // The WDATA field contains the line index (i.e. the Z & Y fields).
+        // -  for an update request the VCI packet length is (n+2) words.
+        // The WDATA field of the first VCI word contains the line number.
+        // The WDATA field of the second VCI word contains the word index.
+        // The WDATA field of the n following words contains the values.
+        // -  for both invalidate & update requests, the VCI response
+        // is one single word.
+        // In case of errors in the VCI command packet, the simulation
+        // is stopped with an error message.
+        /////////////////////////////////////////////////////////////////////
+
+        switch(r_vci_tgt_fsm) {
+
+            case TGT_IDLE:
+                if ( p_vci_tgt.cmdval.read() ) 
+                {
+                    addr_40 address = p_vci_tgt.address.read();
+
+                    if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the received VCI command from " << std::dec << p_vci_tgt.srcid.read() << " is not a write" << std::endl;
+                        exit(0);
+                    }
+
+                    // multi-update or multi-invalidate for data type
+                    if ( (address != 0x3) && (! m_segment.contains(address)) ) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "out of segment VCI command received for a multi-updt or multi-inval request" << std::endl;
+                        exit(0);
+                    }
+
+                    r_tgt_addr = (((addr_40) ((p_vci_tgt.be.read() & 0x3) << 32)) | 
+                                 ((addr_40) (p_vci_tgt.wdata.read()))) * m_dcache_words * 4;      
+                    r_tgt_srcid = p_vci_tgt.srcid.read();
+                    r_tgt_trdid = p_vci_tgt.trdid.read();
+                    r_tgt_pktid = p_vci_tgt.pktid.read();
+                    r_tgt_plen  = p_vci_tgt.plen.read();
+                    
+                    if ( address == 0x3 )   // broadcast invalidate for data or instruction type
+                    {
+                        if ( ! p_vci_tgt.eop.read() ) 
+                        {
+                            std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                            std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
+                            exit(0);
+                        }
+                        r_tgt_update = false; 
+                        r_tgt_brdcast= true;
+                        r_vci_tgt_fsm = TGT_REQ_BROADCAST;
+                        m_cpt_cc_inval++ ;
+                    }
+                    else                    // multi-update or multi-invalidate for data type
+                    { 
+                        uint32_t cell = address - m_segment.baseAddress(); // addr_40
+                        r_tgt_brdcast = false;
+                        if (cell == 0) 
+                        {                               // invalidate 
+                            if ( ! p_vci_tgt.eop.read() ) 
+                            {
+                                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                                exit(0);
+                            }
+                            r_tgt_update = false; 
+                            r_vci_tgt_fsm = TGT_REQ_DCACHE;
+                            m_cpt_cc_inval++ ;
+                        } 
+                        else if (cell == 4)                  // update data
+                        {                                
+                            if ( p_vci_tgt.eop.read() ) 
+                            {
+                                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                                exit(0);
+                            }
+                            r_data_update  = true;
+                            r_tgt_update   = true; 
+                            r_vci_tgt_fsm  = TGT_UPDT_WORD;
+                            m_cpt_cc_update++ ;
+                        } 
+                        else if (cell == 8)                  // invalidate instruction
+                        {                         
+                            if ( ! p_vci_tgt.eop.read() ) 
+                            {
+                                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                                exit(0);
+                            }
+                            r_tgt_update = false; 
+                            r_vci_tgt_fsm = TGT_REQ_ICACHE;
+                            m_cpt_cc_inval++ ;
+                        } 
+                        else if (cell == 12)                  // update ins
+                        {                                
+                            if ( p_vci_tgt.eop.read() ) 
+                            {
+                                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                                exit(0);
+                            }
+                            r_data_update = false;
+                            r_tgt_update  = true; 
+                            r_vci_tgt_fsm = TGT_UPDT_WORD;
+                            m_cpt_cc_update++ ;
+                        } 
+
+                    } // end if address
+                } // end if cmdval
+                break;
+
+            case TGT_UPDT_WORD:
+                if (p_vci_tgt.cmdval.read()) 
+                {
+                    if ( p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                        exit(0);
+                    }
+                    for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_be[i] = 0;
+                    r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
+                    r_vci_tgt_fsm = TGT_UPDT_DATA;
+                }
+                break;
+
+            case TGT_UPDT_DATA:
+                if (p_vci_tgt.cmdval.read()) 
+                {
+                    size_t word = r_tgt_word.read();
+                    if ( word >= m_dcache_words ) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the received MULTI-UPDATE command length is wrong" << std::endl;
+                        exit(0);
+                    }
+                    r_tgt_buf[word] = p_vci_tgt.wdata.read();
+                    r_tgt_be[word] = p_vci_tgt.be.read();
+                    r_tgt_word = word + 1;
+                    if (p_vci_tgt.eop.read()) {
+                        if (r_data_update.read())  r_vci_tgt_fsm = TGT_REQ_DCACHE;
+                        else r_vci_tgt_fsm = TGT_REQ_ICACHE;
+                    }
+                }
+                break;
+
+            case TGT_REQ_BROADCAST:
+                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+                {
+                    r_vci_tgt_fsm = TGT_RSP_BROADCAST; 
+                    r_tgt_icache_req = true;
+                    r_tgt_dcache_req = true;
+                }
+                break;
+                ////////////////////
+            case TGT_REQ_ICACHE:
+                {
+                    if ( !r_tgt_icache_req.read() ) 
+                    {
+                        r_vci_tgt_fsm = TGT_RSP_ICACHE; 
+                        r_tgt_icache_req = true;
+                    }
+                    break;
+                }
+
+            case TGT_REQ_DCACHE:
+                if ( !r_tgt_dcache_req.read() ) 
+                {
+                    r_vci_tgt_fsm = TGT_RSP_DCACHE; 
+                    r_tgt_dcache_req = true;
+                }
+                break;
+
+            case TGT_RSP_BROADCAST:
+                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+                {
+                    // one response
+                    if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
+                    {
+                        if ( p_vci_tgt.rspack.read() )
+                        {
+                            r_vci_tgt_fsm = TGT_IDLE; 
+                            r_tgt_icache_rsp = false;
+                            r_tgt_dcache_rsp = false;
+                        }
+                    }
+
+                    // if data and instruction have the inval line, need two responses  
+                    if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
+                    {
+                        if ( p_vci_tgt.rspack.read() )
+                        {
+                            r_tgt_icache_rsp = false; // only reset one for respond the second time 
+                        }
+                    }
+
+                    // if there is no need for a response
+                    if ( !r_tgt_icache_rsp && !r_tgt_dcache_rsp )
+                    {
+                        r_vci_tgt_fsm = TGT_IDLE;
+                    }
+
+                }
+                break;
+                ////////////////////
+            case TGT_RSP_ICACHE:
+                {
+                    if ( (p_vci_tgt.rspack.read() || !r_tgt_icache_rsp.read()) && !r_tgt_icache_req.read() ) 
+                    {
+                        r_vci_tgt_fsm = TGT_IDLE;
+                        r_tgt_icache_rsp = false; 
+                    }
+                    break;
+                }
+
+            case TGT_RSP_DCACHE:
+                {
+                    if ( (p_vci_tgt.rspack.read() || !r_tgt_dcache_rsp.read()) && !r_tgt_dcache_req.read() ) 
+                    {
+                        r_vci_tgt_fsm = TGT_IDLE;
+                        r_tgt_dcache_rsp = false; 
+                    }
+                    break;
+                }
+        } // end switch TGT_FSM
+
+        /////////////////////////////////////////////////////////////////////
+        // The ICACHE FSM controls the following ressources:
+        // - r_icache_fsm
+        // - r_icache_fsm_save
+        // - r_icache instruction cache access
+        // - r_icache_addr_save
+        // - r_icache_miss_req set
+        // - r_icache_unc_req set
+        // - r_icache_buf_unc_valid set
+        // - r_vci_rsp_ins_error reset
+        // - r_tgt_icache_req reset
+        // - ireq & irsp structures for communication with the processor
+        //
+        // 1/ External requests (update or invalidate) have highest priority.
+        //    They are taken into account in the IDLE and WAIT states.
+        //    As external hit should be extremly rare on the ICACHE,
+        //    all external requests are handled as invalidate...
+        //    In case of external request the ICACHE FSM goes to the CC_CHECK
+        //    state to test the external hit, and returns in the
+        //    pre-empted state after completion.
+        // 2/ Processor requests are taken into account only in the IDLE state.
+        //    In case of MISS, or in case of uncached instruction, the FSM 
+        //    writes the missing address line in the  r_icache_addr_save register 
+        //    and sets the r_icache_miss_req or the r_icache_unc_req flip-flops.
+        //    These request flip-flops are reset by the VCI_RSP FSM
+        //    when the VCI transaction is completed and the r_icache_buf_unc_valid
+        //    is set in case of uncached access.
+        //    In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 
+        //    flip-flop. It is reset by the ICACHE FSM.
+        ///////////////////////////////////////////////////////////////////////
+
+        typename iss_t::InstructionRequest  ireq = ISS_IREQ_INITIALIZER;
+        typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
+
+        typename iss_t::DataRequest  dreq = ISS_DREQ_INITIALIZER;
+        typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
+
+        m_iss.getRequests( ireq, dreq );
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << " Instruction Request: " << ireq << std::endl;
+#endif
+
+        switch(r_icache_fsm) {
+            /////////////////
+            case ICACHE_IDLE:
+                {
+                    if ( r_tgt_icache_req ) {   // external request
+                        if ( ireq.valid ) m_cost_ins_miss_frz++;
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm;
+                        break;
+                    } 
+                    if ( ireq.valid ) {
+                        data_t  icache_ins = 0;
+                        bool    icache_hit = false;
+                        bool    icache_cached = m_cacheability_table[(vci_addr_t)ireq.addr];
+                        // icache_hit & icache_ins evaluation
+                        if ( icache_cached ) {
+                            icache_hit = r_icache.read((vci_addr_t) ireq.addr, &icache_ins);
+                        } else {
+                            icache_hit = ( r_icache_buf_unc_valid && ((addr_40) ireq.addr == (addr_40)r_icache_addr_save) );
+                            icache_ins = r_icache_miss_buf[0];
+                        }
+                        if ( ! icache_hit ) {
+                            m_cpt_ins_miss++;
+                            m_cost_ins_miss_frz++;
+                            r_icache_addr_save = (addr_40) ireq.addr;
+                            if ( icache_cached ) {
+                                r_icache_fsm = ICACHE_MISS_WAIT;
+                                r_icache_miss_req = true;
+                            } else {
+                                r_icache_fsm = ICACHE_UNC_WAIT;
+                                r_icache_unc_req = true;
+                            }
+                        } else {
+                            r_icache_buf_unc_valid = false;
+                        }
+                        m_cpt_icache_dir_read += m_icache_ways;
+                        m_cpt_icache_data_read += m_icache_ways;
+                        irsp.valid          = icache_hit;
+                        irsp.instruction    = icache_ins;
+                    }
+                    break;
+                }
+                //////////////////////
+            case ICACHE_MISS_WAIT:
+                {
+                    m_cost_ins_miss_frz++;
+                    if ( r_tgt_icache_req ) {   // external request
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm;
+                        break;
+                    } 
+                    if ( !r_icache_miss_req && !r_icache_inval_rsp ) { // Miss read response and no invalidation
+                        if ( r_vci_rsp_ins_error ) {
+                            r_icache_fsm = ICACHE_ERROR;
+                        } else {
+                            r_icache_fsm = ICACHE_MISS_UPDT;
+                        }
+                    }
+                    if ( !r_icache_miss_req && r_icache_inval_rsp ) { // Miss read response and invalidation
+                        if ( r_vci_rsp_ins_error ) {
+                            r_icache_inval_rsp = false;
+                            r_icache_fsm = ICACHE_ERROR;
+                        } else {
+                            r_icache_inval_rsp = false;
+                            r_icache_fsm = ICACHE_CC_CLEANUP;
+                        }
+                    }
+                    break;
+                }
+                /////////////////////
+            case ICACHE_UNC_WAIT:
+                {
+                    m_cost_ins_miss_frz++;
+                    if ( r_tgt_icache_req ) {   // external request
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm;
+                        break;
+                    } 
+                    if ( !r_icache_unc_req ) {
+                        if ( r_vci_rsp_ins_error ) {
+                            r_icache_fsm = ICACHE_ERROR;
+                        } else {
+                            r_icache_fsm = ICACHE_IDLE;
+                            r_icache_buf_unc_valid = true;
+                        }
+                    }
+                    break;
+                }
+                //////////////////
+            case ICACHE_ERROR:
+                {
+                    r_icache_fsm = ICACHE_IDLE;
+                    r_vci_rsp_ins_error = false;
+                    irsp.error          = true;
+                    irsp.valid          = true;
+                    break;
+                }
+                //////////////////////
+            case ICACHE_MISS_UPDT: 
+                {
+                    if ( r_tgt_icache_req ) {   // external request
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm;
+                        break;
+                    } 
+                    if(!r_icache_cleanup_req.read() && !r_icache_inval_rsp){
+                        vci_addr_t ad   = 0;
+                        ad              = (vci_addr_t) r_icache_addr_save.read();
+                        data_t*   buf   = r_icache_miss_buf;
+                        vci_addr_t victim_index = 0;
+                        m_cpt_icache_dir_write++;
+                        m_cpt_icache_data_write++;
+                        if ( ireq.valid ) m_cost_ins_miss_frz++;
+
+                        r_icache_cleanup_req  = r_icache.update(ad, buf, &victim_index);
+                        r_icache_cleanup_line = (addr_40) victim_index;
+
+                        r_icache_fsm        = ICACHE_IDLE;
+                        break;
+                    }
+                    if(r_icache_inval_rsp){
+                        if ( ireq.valid ) m_cost_ins_miss_frz++;
+                        r_icache_inval_rsp  = false;
+                        r_icache_fsm = ICACHE_CC_CLEANUP;
+                        break;
+                    }
+                    if ( ireq.valid ) m_cost_ins_miss_frz++;
+                }
+                ////////////////////
+            case ICACHE_CC_CLEANUP:
+                {
+                    // external cache invalidate request
+                    if ( r_tgt_icache_req )     
+                    {
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm;
+                        break;
+                    }
+                    // cleanup
+                    if(!r_icache_cleanup_req){
+                        r_icache_cleanup_req = true;
+                        r_icache_cleanup_line = r_icache_addr_save.read() >> (uint32_log2(m_icache_words) + 2);   
+                        r_icache_fsm = ICACHE_IDLE;
+                    }
+                    break;
+                }
+            case ICACHE_CC_CHECK:   // read directory in case of invalidate or update request
+                {
+
+                    m_cpt_icache_dir_read += m_icache_ways;
+                    m_cpt_icache_data_read += m_icache_ways;
+                    addr_40  ad           = r_tgt_addr;
+                    data_t  icache_rdata = 0;
+
+                    if(( ( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT ) ) && 
+                            ( (r_icache_addr_save.read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) {
+                        r_icache_inval_rsp = true;
+                        r_tgt_icache_req = false;
+                        if(r_tgt_update){    // Also send a cleanup and answer
+                            r_tgt_icache_rsp     = true;
+                        } else {            // Also send a cleanup but don't answer
+                            r_tgt_icache_rsp     = false;
+                        }
+                        r_icache_fsm = r_icache_fsm_save;
+                    } else {
+                        bool    icache_hit   = r_icache.read(ad, &icache_rdata);
+                        if ( icache_hit && r_tgt_update ) {
+                            r_icache_fsm = ICACHE_CC_UPDT;
+                            // complete the line buffer in case of update
+                            for ( size_t word = 0 ; word < m_icache_words ; word++ ) {
+                                data_t mask = vci_param::be2mask(r_tgt_be[word]);
+                                addr_40  ad = addr_40 (r_tgt_addr.read() + word*4); //(addr_40)word;
+                                r_icache.read(ad, &icache_rdata);
+                                r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & icache_rdata);
+                            }
+                        } else if ( icache_hit && !r_tgt_update ) {
+                            r_icache_fsm = ICACHE_CC_INVAL;
+                        } else { // instruction not found (can happen)
+                            r_tgt_icache_req = false;
+                            if(r_tgt_update){
+                                r_tgt_icache_rsp = true;
+                            } else {
+                                r_tgt_icache_rsp = false;
+                            }
+                            r_icache_fsm = r_icache_fsm_save;
+                        }
+                    }
+                    break;
+                }
+                ///////////////////
+            case ICACHE_CC_UPDT:    // update directory and data cache        
+                {
+                    m_cpt_icache_dir_write++;
+                    m_cpt_icache_data_write++;
+                    addr_40  ad     = r_tgt_addr;
+                    data_t* buf     = r_tgt_buf;
+                    for(size_t i=0; i<m_icache_words; i++){
+                        if(r_tgt_be[i]) r_icache.write( ad + i*4, buf[i]);
+                    }
+                    r_tgt_icache_req = false;
+                    r_tgt_icache_rsp = true;
+                    r_icache_fsm = r_icache_fsm_save;
+                    break;
+                }
+
+                /////////////////////
+            case ICACHE_CC_INVAL:   // invalidate a cache line
+                {
+                    addr_40  ad      = r_tgt_addr;
+                    r_tgt_icache_rsp = r_icache.inval(ad);
+                    r_tgt_icache_req = false;
+                    r_icache_fsm = r_icache_fsm_save;
+                    break;
+                }
+
+        } // end switch r_icache_fsm
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << " Instruction Response: " << irsp << std::endl;
+#endif
+
+        //////////////////////////////////////////////////////////////////////://///////////
+        // The DCACHE FSM controls the following ressources:
+        // - r_dcache_fsm
+        // - r_dcache_fsm_save
+        // - r_dcache (data cache access)
+        // - r_dcache_addr_save
+        // - r_dcache_wdata_save
+        // - r_dcache_rdata_save
+        // - r_dcache_type_save
+        // - r_dcache_be_save
+        // - r_dcache_cached_save
+        // - r_dcache_miss_req set
+        // - r_dcache_unc_req set
+        // - r_dcache_write_req set
+        // - r_dcache_cleanup_req set
+        // - r_vci_rsp_data_error reset
+        // - r_tgt_dcache_req reset
+        // - r_wbuf write
+        // - dreq & drsp structures for communication with the processor
+        //
+        // 1/ EXTERNAL REQUEST : 
+        //    There is an external request when the tgt_dcache req flip-flop is set,
+        //    requesting a line invalidation or a line update. 
+        //    External requests are taken into account in the states  IDLE, WRITE_REQ,  
+        //    UNC_WAIT, MISS_WAIT, and have the highest priority :
+        //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
+        //    goes to the CC_CHECK state to execute the requested action, and returns to the
+        //    pre-empted state.
+        //  2/ PROCESSOR REQUEST : 
+        //   In order to support VCI write burst, the processor requests are taken into account
+        //   in the WRITE_REQ state as well as in the IDLE state.
+        //   - In the IDLE state, the processor request cannot be satisfied if
+        //   there is a cached read miss, or an uncached read.
+        //   - In the WRITE_REQ state, the request cannot be satisfied if
+        //   there is a cached read miss, or an uncached read,
+        //   or when the write buffer is full.
+        //   - In all other states, the processor request is not satisfied.
+        //
+        //   The cache access takes into account the cacheability_table.
+        //   In case of processor request, there is five conditions to exit the IDLE state:
+        //   - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal), 
+        //     then to the MISS_UPDT state, and finally to the IDLE state.
+        //   - UNCACHED READ  => to the UNC_WAIT state (waiting the r_miss_ok signal), 
+        //     and to the IDLE state.
+        //   - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state.
+        //   - WRITE MISS => directly to the WRITE_REQ state to access the write buffer.
+        //   - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state.
+        //
+        // Error handling :  Read Bus Errors are synchronous events, but
+        // Write Bus Errors are asynchronous events (processor is not frozen).
+        // - If a Read Bus Error is detected, the VCI_RSP FSM sets the
+        //   r_vci_rsp_data_error flip-flop, and the synchronous error is signaled
+        //   by the DCACHE FSM.
+        // - If a Write Bus Error is detected, the VCI_RSP FSM  signals
+        //   the asynchronous error using the setWriteBerr() method.
+        ///////////////////////////////////////////////////////////////////////////////////
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << " Data Request: " << dreq << std::endl;
+#endif
+
+        //if( (m_cpt_total_cycles % 10000) ==0 ) std::cout << std::dec << "Proc " << m_srcid << " Data Request: " << dreq << std::endl;
+
+        switch ( r_dcache_fsm ) {
+
+            /////////////////////
+            case DCACHE_WRITE_REQ:
+                { 
+                    if ( r_tgt_dcache_req ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }
+                    // try to post the write request in the write buffer
+                    if ( !r_dcache_write_req ) {    // no previous write transaction     
+                        if ( r_wbuf.wok(r_dcache_addr_save) ) {   // write request in the same cache line
+                            r_wbuf.write(r_dcache_addr_save, r_dcache_be_save, r_dcache_wdata_save);
+                            // close the write packet if uncached
+                            if ( !r_dcache_cached_save ){
+                                r_dcache_write_req = true ;
+                            }
+                        } else {    
+                            // close the write packet if write request not in the same cache line
+                            r_dcache_write_req = true;  
+                            if(!m_srcid_rw) {
+                            }
+                            m_cost_write_frz++;
+                            break;  // posting request not possible : stay in DCACHE_WRITEREQ state
+                        }
+                    } else {    //  previous write transaction not completed
+                        m_cost_write_frz++;
+                        break;  // posting request not possible : stay in DCACHE_WRITEREQ state  
+                    }
+
+                    // close the write packet if the next processor request is not a write 
+                    if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE) ) {
+                        r_dcache_write_req = true ;
+                    }
+
+                    // The next state and the processor request parameters are computed 
+                    // as in the DCACHE_IDLE state (see below ...)
+                }
+                /////////////////
+            case DCACHE_IDLE:
+                {
+                    if ( r_tgt_dcache_req ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    } 
+
+                    if ( dreq.valid ) {              
+                        bool        dcache_hit     = false;
+                        data_t      dcache_rdata   = 0;
+                        bool        dcache_cached;
+                        m_cpt_dcache_data_read += m_dcache_ways;
+                        m_cpt_dcache_dir_read += m_dcache_ways;
+
+                        // dcache_cached evaluation
+                        switch (dreq.type) {
+                            case iss_t::DATA_LL:
+                            case iss_t::DATA_SC:
+                            case iss_t::XTN_READ:
+                            case iss_t::XTN_WRITE:
+                                dcache_cached = false;
+                                break;
+                            default:
+                                dcache_cached = m_cacheability_table[(vci_addr_t)dreq.addr];
+                        }
+
+                        // dcache_hit & dcache_rdata evaluation
+                        if ( dcache_cached ) {
+                            dcache_hit = r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
+                        } else {
+                            dcache_hit = ( r_dcache_buf_unc_valid.read() && ((addr_40) dreq.addr == (addr_40)r_dcache_addr_save) );
+                            dcache_rdata = r_dcache_miss_buf[0];
+                        }
+
+                        switch( dreq.type ) {
+                            case iss_t::DATA_READ:
+                            case iss_t::DATA_LL:
+                            case iss_t::DATA_SC:
+                                m_cpt_read++;
+                                if ( dcache_hit ) {
+                                    r_dcache_fsm = DCACHE_IDLE;
+                                    drsp.valid = true;
+                                    drsp.rdata = dcache_rdata;
+                                    r_dcache_buf_unc_valid = false;
+                                } else {
+                                    if ( dcache_cached ) {
+                                        m_cpt_data_miss++;
+                                        m_cost_data_miss_frz++;
+                                        r_dcache_miss_req = true;
+                                        r_dcache_fsm = DCACHE_MISS_WAIT;
+                                    } else {
+                                        m_cpt_unc_read++;
+                                        m_cost_unc_read_frz++;
+                                        r_dcache_unc_req = true;
+                                        r_dcache_fsm = DCACHE_UNC_WAIT;
+                                    }
+                                }
+                                break;
+                            case iss_t::XTN_READ:
+                            case iss_t::XTN_WRITE:
+                                // only DCACHE INVALIDATE request are supported
+                                if ( dreq.addr/4 == iss_t::XTN_DCACHE_INVAL ){
+                                    r_dcache_fsm = DCACHE_INVAL;
+                                } else {
+                                    r_dcache_fsm = DCACHE_IDLE;
+                                }
+                                drsp.valid = true;
+                                drsp.rdata = 0;
+                                break;
+                            case iss_t::DATA_WRITE:
+                                m_cpt_write++;
+                                if ( dcache_hit && dcache_cached ) {
+                                    r_dcache_fsm = DCACHE_WRITE_UPDT;
+                                    m_cpt_write_cached++;
+                                } else {
+                                    r_dcache_fsm = DCACHE_WRITE_REQ;
+                                }
+                                drsp.valid = true;
+                                drsp.rdata = 0;
+                                break;
+                        } // end switch dreq.type
+
+                        r_dcache_addr_save      = (addr_40) dreq.addr;
+                        r_dcache_type_save      = dreq.type;
+                        r_dcache_wdata_save     = dreq.wdata;
+                        r_dcache_be_save        = dreq.be;
+                        r_dcache_rdata_save     = dcache_rdata;
+                        r_dcache_cached_save    = dcache_cached;
+
+                    } else {    // end if dreq.valid
+                        r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    // processor request are not accepted in the WRITE_REQUEST state
+                    // when the write buffer is not writeable
+                    if ( (r_dcache_fsm == DCACHE_WRITE_REQ) &&
+                            (r_dcache_write_req || !r_wbuf.wok(r_dcache_addr_save)) ) {
+                        drsp.valid = false;
+                        drsp.rdata = 0;
+                    }
+                    break;
+                }
+                ///////////////////////
+            case DCACHE_WRITE_UPDT:
+                {
+                    m_cpt_dcache_data_write++;
+                    data_t mask = vci_param::be2mask(r_dcache_be_save);
+                    data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
+                    vci_addr_t ad = r_dcache_addr_save.read();
+                    r_dcache.write(ad, wdata);
+                    r_dcache_fsm = DCACHE_WRITE_REQ;
+                    break;
+                }
+                //////////////////////
+            case DCACHE_MISS_WAIT:
+                {
+
+                    if ( dreq.valid ) m_cost_data_miss_frz++;
+                    if ( r_tgt_dcache_req.read() ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }
+                    if ( !r_dcache_miss_req && !r_dcache_inval_rsp ) { // Miss read response and no invalidation
+                        if ( r_vci_rsp_data_error ) {
+                            r_dcache_fsm = DCACHE_ERROR;
+                        } else {
+                            r_dcache_fsm = DCACHE_MISS_UPDT;
+                        }
+                        break;
+                    }
+                    if ( !r_dcache_miss_req && r_dcache_inval_rsp ) { // Miss read response and invalidation
+                        if ( r_vci_rsp_data_error ) {
+                            r_dcache_inval_rsp  = false;
+                            r_dcache_fsm = DCACHE_ERROR;
+                        } else {
+                            r_dcache_inval_rsp  = false;
+                            r_dcache_fsm = DCACHE_CC_CLEANUP;
+                        }
+                        break;
+                    }
+                    break;
+                }
+                //////////////////////
+            case DCACHE_MISS_UPDT:
+
+                {
+                        if ( r_tgt_dcache_req.read() ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }
+                    if( !r_dcache_cleanup_req.read() && !r_dcache_inval_rsp ){
+                        vci_addr_t  ad  = 0;
+                        ad = (vci_addr_t) r_dcache_addr_save.read();
+                        data_t* buf = new data_t[m_dcache_words];
+                        for(size_t i=0; i<m_dcache_words; i++) {
+                            buf[i] = r_dcache_miss_buf[i];
+                        }
+                        vci_addr_t  victim_index = 0;
+                        if ( dreq.valid ) m_cost_data_miss_frz++;
+                        m_cpt_dcache_data_write++;
+                        m_cpt_dcache_dir_write++;
+
+                        r_dcache_cleanup_req = r_dcache.update(ad, buf, &victim_index);
+                        r_dcache_cleanup_line = (addr_40) victim_index;
+
+                        r_dcache_fsm = DCACHE_IDLE;
+                        delete [] buf;
+                        break;
+                    }
+                    if( r_dcache_inval_rsp ){
+                        r_dcache_inval_rsp  = false;
+                        r_dcache_fsm = DCACHE_CC_CLEANUP;
+                        break;
+                    }
+                    break;
+                }
+                ////////////////////
+            case DCACHE_UNC_WAIT:
+                {
+                    if ( dreq.valid ) m_cost_unc_read_frz++;
+                    if ( r_tgt_dcache_req ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    } 
+                    if ( !r_dcache_unc_req ) {
+                        if ( r_vci_rsp_data_error ) {
+                            r_dcache_fsm = DCACHE_ERROR;
+                        } else {
+                            r_dcache_fsm = DCACHE_IDLE;
+                            // If request was a DATA_SC we need to invalidate the corresponding cache line,
+                            // so that subsequent access to this line are read from RAM
+                            if (dreq.type == iss_t::DATA_SC) {
+                                r_dcache_fsm = DCACHE_INVAL;
+                            }
+                            r_dcache_buf_unc_valid = true;
+                        }
+                    }
+                    break;
+                }
+                //////////////////
+            case DCACHE_ERROR:
+                {
+                    r_dcache_fsm = DCACHE_IDLE;
+                    r_vci_rsp_data_error = false;
+                    drsp.error = true;
+                    drsp.valid = true;
+                    break;
+                }
+                /////////////////    
+            case DCACHE_INVAL:
+                {
+                    if ( r_tgt_dcache_req.read() ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }
+                    if( !r_dcache_cleanup_req.read() ){
+                        m_cpt_dcache_dir_read += m_dcache_ways;
+                        vci_addr_t  ad  = r_dcache_addr_save.read();
+                        r_dcache_cleanup_req = r_dcache.inval(ad);
+                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> (uint32_log2(m_dcache_words)+2);
+
+                        r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+                }
+                /////////////////////
+            case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
+                {
+
+                    m_cpt_dcache_dir_read += m_dcache_ways;
+                    m_cpt_dcache_data_read += m_dcache_ways;
+                    addr_40  ad           = r_tgt_addr;
+                    data_t  dcache_rdata = 0;
+
+                    if(( ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) && 
+                            ( (r_dcache_addr_save.read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) {
+                        r_dcache_inval_rsp = true;
+                        r_tgt_dcache_req = false;
+                        if(r_tgt_update){    // Also send a cleanup and answer
+                            r_tgt_dcache_rsp     = true;
+                        } else {            // Also send a cleanup but don't answer
+                            r_tgt_dcache_rsp     = false;
+                        }
+                        r_dcache_fsm = r_dcache_fsm_save;
+                    } else {
+                        bool    dcache_hit   = r_dcache.read(ad, &dcache_rdata);
+                        if ( dcache_hit && r_tgt_update ) {
+                            r_dcache_fsm = DCACHE_CC_UPDT;
+                            // complete the line buffer in case of update
+                            for ( size_t word = 0 ; word < m_dcache_words ; word++ ) {
+                                addr_40  ad = addr_40 (r_tgt_addr.read() + word*4); //(addr_40)word;
+                                data_t mask = vci_param::be2mask(r_tgt_be[word]);
+                                r_dcache.read(ad, &dcache_rdata);
+                                r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & dcache_rdata);
+                            }
+                        } else if ( dcache_hit && !r_tgt_update ) {
+                            r_dcache_fsm = DCACHE_CC_INVAL;
+                        } else { // data not found (can happen) 
+                            if(r_tgt_update){
+                                r_tgt_dcache_rsp = true;
+                            } else {
+                                r_tgt_dcache_rsp = false;
+                            }
+                            r_tgt_dcache_req = false;
+                            r_dcache_fsm = r_dcache_fsm_save;
+                        }
+                    }
+                    break;
+                }
+                ///////////////////
+            case DCACHE_CC_UPDT:    // update directory and data cache        
+                {
+                    m_cpt_dcache_dir_write++;
+                    m_cpt_dcache_data_write++;
+                    addr_40  ad      = r_tgt_addr;
+                    data_t* buf     = r_tgt_buf;
+                    for(size_t i=0; i<m_dcache_words; i++){
+                        if(r_tgt_be[i]) r_dcache.write( ad + i*4, buf[i]);
+                    }
+                    r_tgt_dcache_req = false;
+                    r_tgt_dcache_rsp = true;
+                    r_dcache_fsm = r_dcache_fsm_save;
+                    break;
+                }
+                /////////////////////
+            case DCACHE_CC_INVAL:   // invalidate a cache line
+                {
+                    addr_40  ad      = r_tgt_addr;
+                    r_tgt_dcache_rsp = r_dcache.inval(ad);
+                    r_tgt_dcache_req = false;
+                    r_dcache_fsm = r_dcache_fsm_save;
+                    break;
+                }
+             ///////////////////
+            case DCACHE_CC_CLEANUP:   
+                {
+                    // external cache invalidate request
+                    if ( r_tgt_dcache_req )   
+                    {
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }        
+                    // cleanup
+                    if(!r_dcache_cleanup_req){
+                        r_dcache_cleanup_req = true;
+                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> (uint32_log2(m_dcache_words) + 2);
+                        r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+                }    
+
+        } // end switch r_dcache_fsm
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << " Data Response: " << drsp << std::endl;
+#endif
+
+        /////////// execute one iss cycle /////////////////////////////////////////////
+        {
+            uint32_t it = 0;
+            for (size_t i=0; i<(size_t)iss_t::n_irq; i++) 
+                if(p_irq[i].read()) it |= (1<<i);
+            m_iss.executeNCycles(1, irsp, drsp, it);
+        }
+
+        if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) ) m_cpt_frz_cycles++;
+
+
+        ////////////////////////////////////////////////////////////////////////////
+        // The VCI_CMD FSM controls the following ressources:
+        // - r_vci_cmd_fsm
+        // - r_vci_cmd_min
+        // - r_vci_cmd_max
+        // - r_vci_cmd_cpt
+        // - wbuf reset
+        //
+        // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
+        // There is 7 request types, with the following priorities : 
+        // 1 - Instruction Miss     : r_icache_miss_req
+        // 2 - Data Write           : r_dcache_write_req
+        // 3 - Data Read Miss       : r_dcache_miss_req 
+        // 4 - Data Read Uncached   : r_dcache_unc_req 
+        // 5 - Instruction Cleanup  : r_icache_cleanup_req 
+        // 6 - Data Cleanup         : r_dcache_cleanup_req 
+        // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM 
+        // and RSP_FSM exit simultaneously the IDLE state.
+        //
+        // VCI formats:
+        // According to the VCI advanced specification, all read requests packets 
+        // (read Uncached, Miss data, Miss instruction) are one word packets.
+        // For write burst packets, all words must be in the same cache line,
+        // and addresses must be contiguous (the BE field is 0 in case of "holes").
+        //////////////////////////////////////////////////////////////////////////////
+
+        switch (r_vci_cmd_fsm) {
+
+            case CMD_IDLE:
+                if (r_vci_rsp_fsm != RSP_IDLE) break;
+
+                r_vci_cmd_cpt = 0;
+                if ( r_icache_cleanup_req ) { 
+                    r_vci_cmd_fsm = CMD_INS_CLEANUP; 
+                } else if ( r_dcache_cleanup_req ) { 
+                    r_vci_cmd_fsm = CMD_DATA_CLEANUP;
+                } else if ( r_icache_miss_req ) { 
+                    r_vci_cmd_fsm = CMD_INS_MISS; 
+                    m_cpt_imiss_transaction++;
+                } else if ( r_icache_unc_req ) { 
+                    r_vci_cmd_fsm = CMD_INS_UNC; 
+                    m_cpt_imiss_transaction++;
+                } else if ( r_dcache_write_req ) { 
+                    r_vci_cmd_fsm = CMD_DATA_WRITE;
+                    r_vci_cmd_cpt = r_wbuf.getMin();
+                    r_vci_cmd_min = r_wbuf.getMin();
+                    r_vci_cmd_max = r_wbuf.getMax(); 
+                    m_cpt_write_transaction++; 
+                    m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1); 
+                } else if ( r_dcache_miss_req ) { 
+                    r_vci_cmd_fsm = CMD_DATA_MISS;
+                    m_cpt_dmiss_transaction++; 
+                } else if ( r_dcache_unc_req ) { 
+                    r_vci_cmd_fsm = CMD_DATA_UNC;
+                    m_cpt_unc_transaction++; 
+                }
+                break;
+
+            case CMD_DATA_WRITE:
+                if ( p_vci_ini_rw.cmdack.read() ) {
+                    r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
+                    if (r_vci_cmd_cpt == r_vci_cmd_max) {
+                        r_vci_cmd_fsm = CMD_IDLE ;
+                        r_wbuf.reset() ;
+                    }
+                }
+                break;
+
+            case CMD_INS_MISS:
+            case CMD_INS_UNC:
+            case CMD_DATA_MISS:
+            case CMD_DATA_UNC:
+                if ( p_vci_ini_rw.cmdack.read() ) {
+                    r_vci_cmd_fsm = CMD_IDLE;
+                }
+                break;
+            case CMD_INS_CLEANUP:
+            case CMD_DATA_CLEANUP:
+                if ( p_vci_ini_c.cmdack.read() ) {
+                    r_vci_cmd_fsm = CMD_IDLE;
+                }
+                break;
+
+        } // end  switch r_vci_cmd_fsm
+
+        //////////////////////////////////////////////////////////////////////////
+        // The VCI_RSP FSM controls the following ressources:
+        // - r_vci_rsp_fsm:
+        // - r_icache_miss_buf[m_icache_words]
+        // - r_dcache_miss_buf[m_dcache_words]
+        // - r_icache_miss_req reset
+        // - r_icache_unc_req reset
+        // - r_dcache_miss_req reset
+        // - r_icache_cleanup_req reset
+        // - r_dcache_cleanup_req reset
+        // - r_vci_rsp_data_error set
+        // - r_vci_rsp_ins_error set
+        // - r_vci_rsp_cpt
+        // In order to have only one active VCI transaction, this VCI_RSP_FSM 
+        // is synchronized with the VCI_CMD FSM, and both FSMs exit the
+        // IDLE state simultaneously.
+        // 
+        // VCI formats:
+        // This component accepts single word or multi-word response packets for
+        // write response packets. 
+        //
+        // Error handling:
+        // This FSM analyzes the VCI error code and signals directly the
+        // Write Bus Error. 
+        // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error 
+        // flip_flop and the error is signaled by the DCACHE FSM.  
+        // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 
+        // flip_flop and the error is signaled by the DCACHE FSM.  
+        // In case of Cleanup Error, the simulation stops with an error message...
+        //////////////////////////////////////////////////////////////////////////
+
+        switch (r_vci_rsp_fsm) {
+
+            case RSP_IDLE:
+                if(p_vci_ini_rw.rspval.read()||
+                        p_vci_ini_c.rspval.read())
+                {
+                    std::cout << "CC_XCache " << m_srcid_rw << " Unexpected response" << std::endl;
+                }
+                assert( ! p_vci_ini_rw.rspval.read() && ! p_vci_ini_c.rspval.read() && "Unexpected response" );
+                if (r_vci_cmd_fsm != CMD_IDLE) break;
+
+                r_vci_rsp_cpt = 0;
+                if      ( r_icache_cleanup_req )    r_vci_rsp_fsm = RSP_INS_CLEANUP;
+                else if ( r_dcache_cleanup_req )    r_vci_rsp_fsm = RSP_DATA_CLEANUP;
+                else if ( r_icache_miss_req )       r_vci_rsp_fsm = RSP_INS_MISS;
+                else if ( r_icache_unc_req )        r_vci_rsp_fsm = RSP_INS_UNC;
+                else if ( r_dcache_write_req )      r_vci_rsp_fsm = RSP_DATA_WRITE;
+                else if ( r_dcache_miss_req )       r_vci_rsp_fsm = RSP_DATA_MISS;
+                else if ( r_dcache_unc_req )        r_vci_rsp_fsm = RSP_DATA_UNC;
+                break;
+
+            case RSP_INS_MISS:
+                m_cost_imiss_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                assert( (r_vci_rsp_cpt < m_icache_words) &&
+                        "The VCI response packet for instruction miss is too long" );
+                r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+                r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+
+                if ( p_vci_ini_rw.reop.read() ) {
+                    assert( (r_vci_rsp_cpt == m_icache_words - 1) &&
+                            "The VCI response packet for instruction miss is too short");
+                    r_icache_miss_req = false;
+                    r_vci_rsp_fsm = RSP_IDLE;
+                }
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+                break;
+
+            case RSP_INS_UNC:
+                m_cost_imiss_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                assert(p_vci_ini_rw.reop.read() &&
+                        "illegal VCI response packet for uncached instruction");
+                r_icache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+                r_vci_rsp_fsm = RSP_IDLE;
+                r_icache_unc_req = false;
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+                break;
+
+            case RSP_DATA_MISS:
+                m_cost_dmiss_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                assert(r_vci_rsp_cpt != m_dcache_words &&
+                        "illegal VCI response packet for data read miss");
+                r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+                r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+                if ( p_vci_ini_rw.reop.read() ) {
+                    assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                            "illegal VCI response packet for data read miss");
+                    r_dcache_miss_req = false;
+                    r_vci_rsp_fsm = RSP_IDLE;
+                }
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                break;
+
+            case RSP_DATA_WRITE:
+                m_cost_write_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                if ( p_vci_ini_rw.reop.read() ) {
+                    r_vci_rsp_fsm = RSP_IDLE;
+                    r_dcache_write_req = false;
+                }
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) m_iss.setWriteBerr();
+                break;
+
+            case RSP_DATA_UNC:
+                m_cost_unc_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                assert(p_vci_ini_rw.reop.read() &&
+                        "illegal VCI response packet for data read uncached");
+                r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+                r_vci_rsp_fsm = RSP_IDLE;
+                r_dcache_unc_req = false;
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                break;
+
+            case RSP_INS_CLEANUP:
+            case RSP_DATA_CLEANUP:
+                if ( ! p_vci_ini_c.rspval.read() )
+                    break;
+                assert( p_vci_ini_c.reop.read() &&
+                        "illegal VCI response packet for icache cleanup");
+                assert( (p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL) &&
+                        "error in response packet for icache cleanup");
+                if ( r_vci_rsp_fsm == RSP_INS_CLEANUP ) r_icache_cleanup_req = false;
+                else                                    r_dcache_cleanup_req = false;
+                r_vci_rsp_fsm = RSP_IDLE;
+                break;
+
+        } // end switch r_vci_rsp_fsm
+
+    } // end transition()
+
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(void)::genMoore()
+        //////////////////////////////////////////////////////////////////////////////////
+    {
+        // VCI initiator response
+
+        p_vci_ini_rw.rspack = true;
+        p_vci_ini_c.rspack = true;
+
+        // VCI initiator command
+
+        switch (r_vci_cmd_fsm.read() ) {
+
+            case CMD_IDLE:
+                p_vci_ini_rw.cmdval  = false;
+                p_vci_ini_rw.address = 0;
+                p_vci_ini_rw.wdata   = 0;
+                p_vci_ini_rw.be      = 0;
+                p_vci_ini_rw.plen    = 0;
+                p_vci_ini_rw.cmd     = vci_param::CMD_NOP;
+                p_vci_ini_rw.trdid   = 0;
+                p_vci_ini_rw.pktid   = 0;
+                p_vci_ini_rw.srcid   = 0;
+                p_vci_ini_rw.cons    = false;
+                p_vci_ini_rw.wrap    = false;
+                p_vci_ini_rw.contig  = false;
+                p_vci_ini_rw.clen    = 0;
+                p_vci_ini_rw.cfixed  = false;
+                p_vci_ini_rw.eop     = false;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_DATA_UNC:
+                p_vci_ini_rw.cmdval = true;
+                p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
+                switch( r_dcache_type_save ) {
+                    case iss_t::DATA_READ:
+                        p_vci_ini_rw.wdata = 0;
+                        p_vci_ini_rw.be  = r_dcache_be_save.read();
+                        p_vci_ini_rw.cmd = vci_param::CMD_READ;
+                        break;
+                    case iss_t::DATA_LL:
+                        p_vci_ini_rw.wdata = 0;
+                        p_vci_ini_rw.be  = 0xF;
+                        p_vci_ini_rw.cmd = vci_param::CMD_LOCKED_READ;
+                        break;
+                    case iss_t::DATA_SC:
+                        p_vci_ini_rw.wdata = r_dcache_wdata_save.read();
+                        p_vci_ini_rw.be  = 0xF;
+                        p_vci_ini_rw.cmd = vci_param::CMD_STORE_COND;
+                        break;
+                    default:
+                        assert("this should not happen");
+                }
+                p_vci_ini_rw.plen = 4;
+                p_vci_ini_rw.trdid  = 0;   // data cache uncached read
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = m_srcid_rw;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = true;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop    = true;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_DATA_WRITE:
+                p_vci_ini_rw.cmdval  = true;
+                p_vci_ini_rw.address = r_wbuf.getAddress(r_vci_cmd_cpt)&~0x3;
+                p_vci_ini_rw.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
+                p_vci_ini_rw.be      = r_wbuf.getBe(r_vci_cmd_cpt);
+                p_vci_ini_rw.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
+                p_vci_ini_rw.cmd     = vci_param::CMD_WRITE;
+                p_vci_ini_rw.trdid   = 0;  // data cache write
+                p_vci_ini_rw.pktid   = 0;
+                p_vci_ini_rw.srcid   = m_srcid_rw;
+                p_vci_ini_rw.cons    = false;
+                p_vci_ini_rw.wrap    = false;
+                p_vci_ini_rw.contig  = true;
+                p_vci_ini_rw.clen    = 0;
+                p_vci_ini_rw.cfixed  = false;
+                p_vci_ini_rw.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_DATA_MISS:
+                p_vci_ini_rw.cmdval = true;
+                p_vci_ini_rw.address = r_dcache_addr_save.read() & (addr_40) m_dcache_yzmask;
+                p_vci_ini_rw.be     = 0xF;
+                p_vci_ini_rw.plen   = m_dcache_words << 2;
+                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
+                p_vci_ini_rw.trdid  = 1;   // data cache cached read
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = m_srcid_rw;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = true;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop = true;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_INS_MISS:
+                p_vci_ini_rw.cmdval = true;
+                p_vci_ini_rw.address = r_icache_addr_save.read() & (addr_40) m_icache_yzmask;
+                p_vci_ini_rw.be     = 0xF;
+                p_vci_ini_rw.plen   = m_icache_words << 2;
+                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
+                p_vci_ini_rw.trdid  = 3;   // ins cache cached read
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = m_srcid_rw;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = true;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop = true;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_INS_UNC:
+                p_vci_ini_rw.cmdval = true;
+                p_vci_ini_rw.address = r_icache_addr_save.read() & ~0x3;
+                p_vci_ini_rw.be     = 0xF;
+                p_vci_ini_rw.plen   = 4;
+                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
+                p_vci_ini_rw.trdid  = 2;   // ins cache uncached read
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = m_srcid_rw;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = true;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop = true;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+
+                break;
+
+            case CMD_INS_CLEANUP:
+                p_vci_ini_rw.cmdval = false;
+                p_vci_ini_rw.address = 0;
+                p_vci_ini_rw.wdata  = 0;
+                p_vci_ini_rw.be     = 0;
+                p_vci_ini_rw.plen   = 0;
+                p_vci_ini_rw.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_rw.trdid  = 0;
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = 0;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = false;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop    = false;
+
+                p_vci_ini_c.cmdval  = true;
+                p_vci_ini_c.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 4;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.trdid  = 1; // cleanup instruction
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = m_srcid_c;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = true;
+
+                break;
+
+
+            case CMD_DATA_CLEANUP:
+                p_vci_ini_rw.cmdval = false;
+                p_vci_ini_rw.address = 0;
+                p_vci_ini_rw.wdata  = 0;
+                p_vci_ini_rw.be     = 0;
+                p_vci_ini_rw.plen   = 0;
+                p_vci_ini_rw.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_rw.trdid  = 0;
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = 0;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = false;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop    = false;
+
+                p_vci_ini_c.cmdval  = true;
+                p_vci_ini_c.address = r_dcache_cleanup_line.read() * (m_dcache_words<<2);
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 4;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.trdid  = 0; // cleanup data
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = m_srcid_c;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = true;
+
+                break;
+
+        } // end switch r_vci_cmd_fsm
+
+        // VCI_TGT
+
+        switch ( r_vci_tgt_fsm.read() ) {
+
+            case TGT_IDLE:
+            case TGT_UPDT_WORD:
+            case TGT_UPDT_DATA:
+                p_vci_tgt.cmdack  = true;
+                p_vci_tgt.rspval  = false;
+                break;
+
+            case TGT_RSP_BROADCAST:
+                p_vci_tgt.cmdack  = false;
+                p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
+                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+                p_vci_tgt.rpktid  = r_tgt_pktid.read();
+                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+                p_vci_tgt.rdata   = 0;
+                p_vci_tgt.rerror  = 0;
+                p_vci_tgt.reop    = true;
+                break;
+
+            case TGT_RSP_ICACHE:
+                p_vci_tgt.cmdack  = false;
+                p_vci_tgt.rspval  = !r_tgt_icache_req.read() && r_tgt_icache_rsp.read();
+                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+                p_vci_tgt.rpktid  = r_tgt_pktid.read();
+                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+                p_vci_tgt.rdata   = 0;
+                p_vci_tgt.rerror  = 0;
+                p_vci_tgt.reop    = true;
+                break;
+
+            case TGT_RSP_DCACHE:
+                p_vci_tgt.cmdack  = false;
+                p_vci_tgt.rspval  = !r_tgt_dcache_req.read() && r_tgt_dcache_rsp.read();
+                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+                p_vci_tgt.rpktid  = r_tgt_pktid.read();
+                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+                p_vci_tgt.rdata   = 0;
+                p_vci_tgt.rerror  = 0;
+                p_vci_tgt.reop    = true;
+                break;
+
+            case TGT_REQ_BROADCAST:
+            case TGT_REQ_ICACHE:
+            case TGT_REQ_DCACHE:
+                p_vci_tgt.cmdack  = false;
+                p_vci_tgt.rspval  = false;
+                break;
+
+        } // end switch TGT_FSM
+    } // end genMoore()
+
+}} // end namespace
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
+
Index: trunk/modules/vci_cc_xcache_wrapper_v4/caba/metadata/vci_cc_xcache_wrapper_v4.sd
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v4/caba/metadata/vci_cc_xcache_wrapper_v4.sd	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper_v4/caba/metadata/vci_cc_xcache_wrapper_v4.sd	(revision 2)
@@ -0,0 +1,55 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_cc_xcache_wrapper_v4',
+	classname = 'soclib::caba::VciCcXCacheWrapperV4',
+	tmpl_parameters = [
+		parameter.Module('vci_param', default = 'caba:vci_param'),
+		parameter.Module('iss_t'),
+		],
+	header_files = [
+		'../source/include/vci_cc_xcache_wrapper_v4.h',
+		],
+	implementation_files = [
+		'../source/src/vci_cc_xcache_wrapper_v4.cpp',
+		],
+	uses = [
+		Uses('caba:base_module'),
+		Uses('common:mapping_table'),
+		Uses('common:iss2'),
+		Uses('caba:write_buffer'),
+		Uses('caba:generic_cache', addr_t = 'uint32_t'),
+		],
+	ports = [
+		Port('caba:vci_initiator', 'p_vci_ini_rw'),
+    Port('caba:vci_initiator', 'p_vci_ini_c'),
+		Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:bit_in', 'p_irq', parameter.Constant('n_irq')),
+		Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+		Port('caba:clock_in', 'p_clk', auto = 'clock'),
+		],
+	instance_parameters = [
+		parameter.Int('proc_id'),
+		parameter.Module('mtp', 'common:mapping_table'),
+		parameter.Module('mtc', 'common:mapping_table'),
+		parameter.IntTab('initiator_rw_index'),
+		parameter.IntTab('initiator_c_index'),
+		parameter.IntTab('target_index'),
+		parameter.Int('icache_ways'),
+		parameter.Int('icache_sets'),
+		parameter.Int('icache_words'),
+		parameter.Int('dcache_ways'),
+		parameter.Int('dcache_sets'),
+		parameter.Int('dcache_words'),
+		],
+	   extensions = [
+		'dsx:get_ident=initiator_index:p_vci_ini_rw',
+		'dsx:cpu=wrapper:iss_t',
+		'dsx:mapping_type=processor:proc_id',
+		],
+)
+
+
Index: trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h	(revision 2)
@@ -0,0 +1,302 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain
+ */
+ 
+#ifndef SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_V4_H
+#define SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_V4_H
+
+#include <inttypes.h>
+#include <systemc>
+#include "caba_base_module.h"
+#include "write_buffer.h"
+#include "generic_cache.h"
+#include "vci_initiator.h"
+#include "vci_target.h"
+#include "mapping_table.h"
+#include "static_assert.h"
+
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+////////////////////////////////////////////
+template<typename vci_param, typename iss_t>
+class VciCcXCacheWrapperV4
+///////////////////////////////////////////
+    : public soclib::caba::BaseModule
+{
+    typedef sc_dt::sc_uint<40> addr_40;
+    typedef uint32_t    data_t;
+    typedef uint32_t    tag_t;
+    typedef uint32_t    be_t;
+    typedef typename vci_param::fast_addr_t vci_addr_t;
+    enum dcache_fsm_state_e {
+        DCACHE_IDLE,
+        DCACHE_WRITE_UPDT,
+        DCACHE_WRITE_REQ,
+        DCACHE_MISS_WAIT,
+        DCACHE_MISS_UPDT,
+        DCACHE_UNC_WAIT,
+        DCACHE_SC_WAIT,
+        DCACHE_INVAL,
+        DCACHE_ERROR,
+        DCACHE_CC_CHECK,
+        DCACHE_CC_INVAL,
+        DCACHE_CC_UPDT,
+        DCACHE_CC_CLEANUP,
+    };
+
+    enum icache_fsm_state_e {
+        ICACHE_IDLE,
+        ICACHE_MISS_WAIT,
+        ICACHE_MISS_UPDT,
+        ICACHE_UNC_WAIT,
+        ICACHE_ERROR,
+        ICACHE_CC_CLEANUP, 
+        ICACHE_CC_CHECK,
+        ICACHE_CC_INVAL,
+        ICACHE_CC_UPDT,
+    };
+
+    enum cmd_fsm_state_e {
+        CMD_IDLE,
+        CMD_INS_MISS,
+        CMD_INS_UNC,
+        CMD_DATA_MISS,
+        CMD_DATA_UNC,
+        CMD_DATA_WRITE,
+        CMD_DATA_SC,
+        CMD_INS_CLEANUP,
+        CMD_DATA_CLEANUP,
+    };
+
+    enum rsp_fsm_state_e {
+        RSP_IDLE,
+        RSP_INS_MISS,
+        RSP_INS_UNC,
+        RSP_DATA_MISS,
+        RSP_DATA_UNC,
+        RSP_DATA_WRITE,
+        RSP_DATA_SC,
+        RSP_INS_CLEANUP,
+        RSP_DATA_CLEANUP,
+    };
+
+    enum tgt_fsm_state_e {
+        TGT_IDLE,
+        TGT_UPDT_WORD,
+        TGT_UPDT_DATA,
+        TGT_REQ_BROADCAST,
+        TGT_REQ_ICACHE,
+        TGT_REQ_DCACHE,
+        TGT_RSP_BROADCAST,
+        TGT_RSP_ICACHE,
+        TGT_RSP_DCACHE,
+    };
+
+public:
+
+    // PORTS
+    sc_in<bool>                             p_clk;
+    sc_in<bool>                             p_resetn;
+    sc_in<bool>                             p_irq[iss_t::n_irq];
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_rw;
+    soclib::caba::VciInitiator<vci_param>   p_vci_ini_c;
+    soclib::caba::VciTarget<vci_param>      p_vci_tgt;
+
+private:
+
+    // STRUCTURAL PARAMETERS
+    const soclib::common::AddressDecodingTable<vci_addr_t, bool>    m_cacheability_table;
+    const soclib::common::Segment                                   m_segment;
+    iss_t               m_iss;
+    const uint32_t      m_srcid_rw;   
+    const uint32_t      m_srcid_c;   
+    
+    const size_t        m_dcache_ways;
+    const size_t        m_dcache_words;
+    const size_t        m_dcache_yzmask;
+    const size_t        m_icache_ways;
+    const size_t        m_icache_words;
+    const size_t        m_icache_yzmask;
+
+    // REGISTERS
+    sc_signal<int>          r_dcache_fsm;
+    sc_signal<int>          r_dcache_fsm_save;
+    sc_signal<addr_40>      r_dcache_addr_save;
+    sc_signal<data_t>       r_dcache_wdata_save;
+    sc_signal<data_t>       r_dcache_rdata_save;
+    sc_signal<uint64_t>     r_dcache_ll_data;
+    sc_signal<addr_40>      r_dcache_ll_addr;
+    sc_signal<bool>         r_dcache_ll_valid;
+    sc_signal<int>          r_dcache_type_save;
+    sc_signal<be_t>         r_dcache_be_save;
+    sc_signal<bool>         r_dcache_cached_save;
+    sc_signal<bool>         r_dcache_cleanup_req;
+    sc_signal<addr_40>      r_dcache_cleanup_line;
+    sc_signal<bool>         r_dcache_miss_req;
+    sc_signal<bool>         r_dcache_unc_req;
+    sc_signal<bool>         r_dcache_sc_req;
+    sc_signal<bool>         r_dcache_write_req;
+    sc_signal<bool>         r_dcache_inval_rsp;
+
+    sc_signal<int>          r_icache_fsm;
+    sc_signal<int>          r_icache_fsm_save;
+    sc_signal<addr_40>      r_icache_addr_save;
+    sc_signal<bool>         r_icache_miss_req;
+    sc_signal<bool>         r_icache_unc_req;
+    sc_signal<bool>         r_icache_cleanup_req;
+    sc_signal<addr_40>      r_icache_cleanup_line;
+    sc_signal<bool>         r_icache_inval_rsp;
+
+    sc_signal<int>          r_vci_cmd_fsm;
+    sc_signal<size_t>       r_vci_cmd_min;       
+    sc_signal<size_t>       r_vci_cmd_max;       
+    sc_signal<size_t>       r_vci_cmd_cpt;       
+      
+    sc_signal<int>          r_vci_rsp_fsm;
+    sc_signal<bool>         r_vci_rsp_ins_error;    
+    sc_signal<bool>         r_vci_rsp_data_error;    
+    sc_signal<size_t>       r_vci_rsp_cpt;  
+
+    data_t                  *r_icache_miss_buf;    
+    data_t                  *r_dcache_miss_buf;    
+    sc_signal<bool>         r_icache_buf_unc_valid;
+
+    data_t                  *r_tgt_buf;
+    be_t                    *r_tgt_be;
+
+    sc_signal<int>          r_vci_tgt_fsm;
+    sc_signal<addr_40>       r_tgt_addr;
+    sc_signal<size_t>       r_tgt_word;
+    sc_signal<bool>         r_tgt_update;
+    sc_signal<bool>         r_tgt_update_data;
+    sc_signal<bool>         r_tgt_brdcast;
+    sc_signal<size_t>       r_tgt_srcid;
+    sc_signal<size_t>       r_tgt_pktid;
+    sc_signal<size_t>       r_tgt_trdid;
+    sc_signal<size_t>       r_tgt_plen;
+    sc_signal<bool>         r_tgt_icache_req;
+    sc_signal<bool>         r_tgt_dcache_req;
+    sc_signal<bool>         r_tgt_icache_rsp;
+    sc_signal<bool>         r_tgt_dcache_rsp;
+
+    WriteBuffer<addr_40>        r_wbuf;
+    GenericCache<vci_addr_t>    r_icache;
+    GenericCache<vci_addr_t>    r_dcache;
+
+    // Activity counters
+    uint32_t m_cpt_dcache_data_read;        // DCACHE DATA READ
+    uint32_t m_cpt_dcache_data_write;       // DCACHE DATA WRITE
+    uint32_t m_cpt_dcache_dir_read;         // DCACHE DIR READ
+    uint32_t m_cpt_dcache_dir_write;        // DCACHE DIR WRITE
+
+    uint32_t m_cpt_icache_data_read;        // ICACHE DATA READ
+    uint32_t m_cpt_icache_data_write;       // ICACHE DATA WRITE
+    uint32_t m_cpt_icache_dir_read;         // ICACHE DIR READ
+    uint32_t m_cpt_icache_dir_write;        // ICACHE DIR WRITE
+
+    uint32_t m_cpt_cc_update;               // number of coherence update packets 
+    uint32_t m_cpt_cc_inval;                // number of coherence inval packets
+
+    uint32_t m_cpt_frz_cycles;	            // number of cycles where the cpu is frozen
+    uint32_t m_cpt_total_cycles;	        // total number of cycles 
+
+    uint32_t m_cpt_read;                    // total number of read instructions
+    uint32_t m_cpt_write;                   // total number of write instructions
+    uint32_t m_cpt_data_miss;               // number of read miss
+    uint32_t m_cpt_ins_miss;                // number of instruction miss
+    uint32_t m_cpt_unc_read;                // number of read uncached
+    uint32_t m_cpt_write_cached;            // number of cached write
+
+    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
+    uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
+    uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
+    uint32_t m_cost_ins_miss_frz;           // number of frozen cycles related to ins miss
+
+    uint32_t m_cpt_imiss_transaction;       // number of VCI instruction miss transactions
+    uint32_t m_cpt_dmiss_transaction;       // number of VCI data miss transactions
+    uint32_t m_cpt_unc_transaction;         // number of VCI uncached read transactions
+    uint32_t m_cpt_write_transaction;       // number of VCI write transactions
+
+    uint32_t m_cost_imiss_transaction;      // cumulated duration for VCI IMISS transactions
+    uint32_t m_cost_dmiss_transaction;      // cumulated duration for VCI DMISS transactions
+    uint32_t m_cost_unc_transaction;        // cumulated duration for VCI UNC transactions
+    uint32_t m_cost_write_transaction;      // cumulated duration for VCI WRITE transactions
+    uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions
+
+protected:
+    SC_HAS_PROCESS(VciCcXCacheWrapperV4);
+
+public:
+
+    VciCcXCacheWrapperV4(
+                       sc_module_name insname,
+                       int proc_id,
+                       const soclib::common::MappingTable &mtp,
+                       const soclib::common::MappingTable &mtc,
+                       const soclib::common::IntTab &initiator_index_rw,
+                       const soclib::common::IntTab &initiator_index_c,
+                       const soclib::common::IntTab &target_index,
+                       size_t icache_ways,
+                       size_t icache_sets,
+                       size_t icache_words,
+                       size_t dcache_ways,
+                       size_t dcache_sets,
+                       size_t dcache_words );
+
+    ~VciCcXCacheWrapperV4();
+
+    void print_cpi();
+    void print_stats();
+
+private:
+
+    void transition();
+    void genMoore();
+
+    soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC);
+    soclib_static_assert((int)iss_t::SC_NOT_ATOMIC == (int)vci_param::STORE_COND_NOT_ATOMIC);
+};
+
+}}
+
+#endif /* SOCLIB_CABA_VCI_CC_XCACHE_WRAPPER_V4_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
Index: trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp
===================================================================
--- trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp	(revision 2)
+++ trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp	(revision 2)
@@ -0,0 +1,2062 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, SoC
+ *         Alain Greiner <alain.greiner@lip6.fr>, 2008
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu nipo
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+// History
+// - 25/04/2008
+//   The existing vci_xcache component has been extended to include 
+//   a VCI target port to support a directory based coherence protocol.
+//   Two types of packets can be send by the L2 cache to the L1 cache
+//   * INVALIDATE packets : length = 1
+//   * UPDATE packets : length = n + 2   
+//   The CLEANUP packets are sent by the L1 cache to the L2 cache, 
+//   to signal a replaced cache line.
+// - 12/08/2008
+//   The vci_cc_xcache_wrapper component instanciates directly the processsor 
+//   iss, in order to supress the processor/cache interface.
+//   According to the VCI advanced specification, this component uses one 
+//   word VCI CMD packets for MISS transactions, and accept one word VCI RSP
+//   packets for Write burst  transactions.
+//   The write buffer has been modified to use the WriteBuffer object. 
+//   A VCI write burst is constructed when two conditions are satisfied :
+//   The processor make strictly successive write requests, and they are
+//   in the same cache line. The write buffer performs re-ordering, to
+//   respect the contiguous addresses VCI constraint. In case of several
+//   WRITE_WORD requests in the same word, only the last request is conserved.
+//   In case of several WRITE_HALF or WRITE_WORD requests in the same word,
+//   the requests are merged in the same word. In case of uncached write
+//   requests, each request is transmited as a single VCI transaction.
+//   Both the data & instruction caches can be flushed in one single cycle.
+///////////////////////////////////////////////////////////////////////////////
+
+#include <cassert>
+#include "arithmetics.h"
+#include "../include/vci_cc_xcache_wrapper_v4.h"
+
+//#define DEBUG_CC_XCACHE_WRAPPER 1
+
+namespace soclib { 
+namespace caba {
+
+#if DEBUG_CC_XCACHE_WRAPPER
+    namespace {
+        const char *dcache_fsm_state_str[] = {
+            "DCACHE_IDLE",
+            "DCACHE_WRITE_UPDT",
+            "DCACHE_WRITE_REQ",
+            "DCACHE_MISS_WAIT",
+            "DCACHE_MISS_UPDT",
+            "DCACHE_UNC_WAIT",
+            "DCACHE_SC_WAIT",
+            "DCACHE_INVAL",
+            "DCACHE_ERROR",
+            "DCACHE_CC_CHECK",
+            "DCACHE_CC_INVAL",
+            "DCACHE_CC_UPDT",
+            "DCACHE_CC_CLEANUP",
+        };
+        const char *icache_fsm_state_str[] = {
+            "ICACHE_IDLE",
+            "ICACHE_MISS_WAIT",
+            "ICACHE_MISS_UPDT",
+            "ICACHE_UNC_WAIT",
+            "ICACHE_ERROR",
+            "ICACHE_CC_CLEANUP",
+            "ICACHE_CC_CHECK",
+            "ICACHE_CC_INVAL",
+            "ICACHE_CC_UPDT",
+        };
+        const char *cmd_fsm_state_str[] = {
+            "CMD_IDLE",
+            "CMD_INS_MISS",
+            "CMD_INS_UNC",
+            "CMD_DATA_MISS",
+            "CMD_DATA_UNC",
+            "CMD_DATA_WRITE",
+            "CMD_DATA_SC",
+            "CMD_INS_CLEANUP",
+            "CMD_DATA_CLEANUP",
+        };
+        const char *rsp_fsm_state_str[] = {
+            "RSP_IDLE",
+            "RSP_INS_MISS",
+            "RSP_INS_UNC",
+            "RSP_DATA_MISS",
+            "RSP_DATA_UNC",
+            "RSP_DATA_WRITE",
+            "RSP_DATA_SC",
+            "RSP_INS_CLEANUP",
+            "RSP_DATA_CLEANUP",
+        };
+        const char *tgt_fsm_state_str[] = {
+            "TGT_IDLE",
+            "TGT_UPDT_WORD",
+            "TGT_UPDT_DATA",
+            "TGT_REQ_BROADCAST",
+            "TGT_REQ_ICACHE",
+            "TGT_REQ_DCACHE",
+            "TGT_RSP_BROADCAST",
+            "TGT_RSP_ICACHE",
+            "TGT_RSP_DCACHE",
+        };
+    }
+#endif
+
+#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXCacheWrapperV4<vci_param, iss_t>
+
+    using soclib::common::uint32_log2;
+
+    /////////////////////////////////
+    tmpl(/**/)::VciCcXCacheWrapperV4(
+            /////////////////////////////////
+            sc_module_name name,
+            int proc_id,
+            const soclib::common::MappingTable &mtp,
+            const soclib::common::MappingTable &mtc,
+            const soclib::common::IntTab &initiator_index_rw,
+            const soclib::common::IntTab &initiator_index_c,
+            const soclib::common::IntTab &target_index,
+            size_t icache_ways,
+            size_t icache_sets,
+            size_t icache_words,
+            size_t dcache_ways,
+            size_t dcache_sets,
+            size_t dcache_words )
+        : 
+            soclib::caba::BaseModule(name),
+
+            p_clk("clk"),
+            p_resetn("resetn"),
+            p_vci_ini_rw("vci_ini_rw"),
+            p_vci_ini_c("vci_ini_c"),
+            p_vci_tgt("vci_tgt"),
+
+            m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()),
+            m_segment(mtc.getSegment(target_index)),
+            m_iss(this->name(), proc_id),
+            m_srcid_rw(mtp.indexForId(initiator_index_rw)),
+            m_srcid_c(mtc.indexForId(initiator_index_c)),
+
+            m_dcache_ways(dcache_ways),
+            m_dcache_words(dcache_words),
+            m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
+            m_icache_ways(icache_ways),
+            m_icache_words(icache_words),
+            m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
+
+            r_dcache_fsm("r_dcache_fsm"),
+            r_dcache_fsm_save("r_dcache_fsm_save"),
+            r_dcache_addr_save("r_dcache_addr_save"),
+            r_dcache_wdata_save("r_dcache_wdata_save"),
+            r_dcache_rdata_save("r_dcache_rdata_save"),
+            r_dcache_ll_data("r_dcache_ll_data"),
+            r_dcache_ll_addr("r_dcache_ll_addr"),
+            r_dcache_ll_valid("r_dcache_ll_valid"),
+            r_dcache_type_save("r_dcache_type_save"),
+            r_dcache_be_save("r_dcache_be_save"),
+            r_dcache_cached_save("r_dcache_cached_save"),
+            r_dcache_cleanup_req("r_dcache_cleanup_req"),
+            r_dcache_cleanup_line("r_dcache_cleanup_line"),
+            r_dcache_miss_req("r_dcache_miss_req"),
+            r_dcache_unc_req("r_dcache_unc_req"),
+            r_dcache_write_req("r_dcache_write_req"),
+
+            r_icache_fsm("r_icache_fsm"),
+            r_icache_fsm_save("r_icache_fsm_save"),
+            r_icache_addr_save("r_icache_addr_save"),
+            r_icache_miss_req("r_icache_miss_req"),
+            r_icache_cleanup_req("r_icache_cleanup_req"),
+            r_icache_cleanup_line("r_icache_cleanup_line"),
+
+            r_vci_cmd_fsm("r_vci_cmd_fsm"),
+            r_vci_cmd_min("r_vci_cmd_min"),
+            r_vci_cmd_max("r_vci_cmd_max"),
+            r_vci_cmd_cpt("r_vci_cmd_cpt"),
+
+            r_vci_rsp_fsm("r_vci_rsp_fsm"),
+            r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
+            r_vci_rsp_data_error("r_vci_rsp_data_error"),
+            r_vci_rsp_cpt("r_vci_rsp_cpt"),
+
+            r_icache_buf_unc_valid("r_icache_buf_unc_valid"),
+
+            r_vci_tgt_fsm("r_vci_tgt_fsm"),
+            r_tgt_addr("r_tgt_addr"),
+            r_tgt_word("r_tgt_word"),
+            r_tgt_update("r_tgt_update"),
+            r_tgt_srcid("r_tgt_srcid"),
+            r_tgt_pktid("r_tgt_pktid"),
+            r_tgt_trdid("r_tgt_trdid"),
+            r_tgt_icache_req("r_tgt_icache_req"),
+            r_tgt_dcache_req("r_tgt_dcache_req"),
+
+            r_wbuf("r_wbuf", dcache_words ),
+            r_icache("icache", icache_ways, icache_sets, icache_words),
+            r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
+
+            {
+                r_icache_miss_buf = new data_t[icache_words];
+                r_dcache_miss_buf = new data_t[dcache_words];
+                r_tgt_buf         = new data_t[dcache_words];
+                r_tgt_be          = new be_t[dcache_words];
+
+                SC_METHOD(transition);
+                dont_initialize();
+                sensitive << p_clk.pos();
+
+                SC_METHOD(genMoore);
+                dont_initialize();
+                sensitive << p_clk.neg();
+
+
+                typename iss_t::CacheInfo cache_info;
+                cache_info.has_mmu = false;
+                cache_info.icache_line_size = icache_words*sizeof(data_t);
+                cache_info.icache_assoc = icache_ways;
+                cache_info.icache_n_lines = icache_sets;
+                cache_info.dcache_line_size = dcache_words*sizeof(data_t);
+                cache_info.dcache_assoc = dcache_ways;
+                cache_info.dcache_n_lines = dcache_sets;
+                m_iss.setCacheInfo(cache_info);
+            } // end constructor
+
+    ///////////////////////////////////
+    tmpl(/**/)::~VciCcXCacheWrapperV4()
+        ///////////////////////////////////
+    {
+        delete [] r_icache_miss_buf;
+        delete [] r_dcache_miss_buf;
+        delete [] r_tgt_be;
+        delete [] r_tgt_buf;
+    }
+
+    ////////////////////////
+    tmpl(void)::print_cpi()
+        ////////////////////////
+    {
+        std::cout << "CPU " << m_srcid_rw << " : CPI = " 
+            << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
+    }
+    ////////////////////////
+    tmpl(void)::print_stats()
+        ////////////////////////
+    {
+        float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
+        std::cout << "------------------------------------" << std:: dec << std::endl;
+        std::cout << "CPU " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
+        std::cout << "- CPI                = " << (float)m_cpt_total_cycles/run_cycles << std::endl ;
+        std::cout << "- READ RATE          = " << (float)m_cpt_read/run_cycles << std::endl ;
+        std::cout << "- WRITE RATE         = " << (float)m_cpt_write/run_cycles << std::endl;
+        std::cout << "- UNCACHED READ RATE = " << (float)m_cpt_unc_read/m_cpt_read << std::endl ;
+        std::cout << "- CACHED WRITE RATE  = " << (float)m_cpt_write_cached/m_cpt_write << std::endl ;
+        std::cout << "- IMISS_RATE         = " << (float)m_cpt_ins_miss/run_cycles << std::endl;
+        std::cout << "- DMISS RATE         = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl ;
+        std::cout << "- INS MISS COST      = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl;
+        std::cout << "- IMISS TRANSACTION  = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl;
+        std::cout << "- DMISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl;
+        std::cout << "- DMISS TRANSACTION  = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl;
+        std::cout << "- UNC COST           = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl;
+        std::cout << "- UNC TRANSACTION    = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl;
+        std::cout << "- WRITE COST         = " << (float)m_cost_write_frz/m_cpt_write << std::endl;
+        std::cout << "- WRITE TRANSACTION  = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl;
+        std::cout << "- WRITE LENGTH       = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl;
+    }
+
+    //////////////////////////
+    tmpl(void)::transition()
+        //////////////////////////
+    {
+        if ( ! p_resetn.read() ) {
+
+            m_iss.reset();
+
+            // FSM states
+            r_dcache_fsm = DCACHE_IDLE;
+            r_icache_fsm = ICACHE_IDLE;
+            r_vci_cmd_fsm = CMD_IDLE;
+            r_vci_rsp_fsm = RSP_IDLE;
+            r_vci_tgt_fsm = TGT_IDLE;
+
+            // write buffer & caches
+            r_wbuf.reset();
+            r_icache.reset();
+            r_dcache.reset();
+
+            // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI  FSMs
+            r_icache_miss_req    = false;
+            r_icache_unc_req     = false;
+            r_icache_cleanup_req = false;
+            r_dcache_miss_req    = false;
+            r_dcache_unc_req     = false;
+            r_dcache_sc_req      = false;
+            r_dcache_write_req   = false;
+            r_dcache_cleanup_req = false;
+
+            // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
+            r_tgt_icache_req     = false;
+            r_tgt_dcache_req     = false;
+
+            // internal messages in DCACHE et ICACHE FSMs
+            r_icache_inval_rsp   = false;
+            r_dcache_inval_rsp   = false;
+
+            // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs
+            r_dcache_ll_valid      = false;
+            r_icache_buf_unc_valid = false;
+            r_vci_rsp_data_error   = false;
+            r_vci_rsp_ins_error    = false;
+
+            // activity counters
+            m_cpt_dcache_data_read  = 0;
+            m_cpt_dcache_data_write = 0;
+            m_cpt_dcache_dir_read  = 0;
+            m_cpt_dcache_dir_write = 0;
+            m_cpt_icache_data_read  = 0;
+            m_cpt_icache_data_write = 0;
+            m_cpt_icache_dir_read  = 0;
+            m_cpt_icache_dir_write = 0;
+
+            m_cpt_cc_update = 0;
+            m_cpt_cc_inval = 0;
+
+            m_cpt_frz_cycles = 0;
+            m_cpt_total_cycles = 0;
+
+            m_cpt_read = 0;
+            m_cpt_write = 0;
+            m_cpt_data_miss = 0;
+            m_cpt_ins_miss = 0;
+            m_cpt_unc_read = 0;
+            m_cpt_write_cached = 0;
+
+            m_cost_write_frz = 0;
+            m_cost_data_miss_frz = 0;
+            m_cost_unc_read_frz = 0;
+            m_cost_ins_miss_frz = 0;
+
+            m_cpt_imiss_transaction = 0;
+            m_cpt_dmiss_transaction = 0;
+            m_cpt_unc_transaction = 0;
+            m_cpt_write_transaction = 0;
+
+            m_cost_imiss_transaction = 0;
+            m_cost_dmiss_transaction = 0;
+            m_cost_unc_transaction = 0;
+            m_cost_write_transaction = 0;
+            m_length_write_transaction = 0;
+
+            return;
+        }
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << "--------------------------------------------" << std::endl;
+        std::cout << std::dec << "CC_XCACHE_WRAPPER " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
+        std::cout             << " tgt fsm    = " << tgt_fsm_state_str[r_vci_tgt_fsm] << std::endl
+            << " dcache fsm = " << dcache_fsm_state_str[r_dcache_fsm] << std::endl
+            << " icache fsm = " << icache_fsm_state_str[r_icache_fsm] << std::endl
+            << " cmd fsm    = " << cmd_fsm_state_str[r_vci_cmd_fsm] << std::endl
+            << " rsp fsm    = " << rsp_fsm_state_str[r_vci_rsp_fsm] << std::endl;
+#endif
+
+        m_cpt_total_cycles++;
+
+        /////////////////////////////////////////////////////////////////////
+        // The TGT_FSM controls the following ressources:
+        // - r_vci_tgt_fsm
+        // - r_tgt_buf[nwords]
+        // - r_tgt_be[nwords]
+        // - r_tgt_update
+        // - r_tgt_word
+        // - r_tgt_addr
+        // - r_tgt_srcid
+        // - r_tgt_trdid
+        // - r_tgt_pktid
+        // All VCI commands must be CMD_WRITE.
+        // If the VCI address offset is null, the command is an invalidate 
+        // request. It is an update request otherwise.
+        // The VCI_TGT FSM stores the external request arguments in the
+        // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 
+        // & r_tgt_dcache_req flip-flops to signal the external request to 
+        // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
+        // of the update or invalidate request in the RSP state.
+        // -  for an invalidate request the VCI packet length is 1 word.
+        // The WDATA field contains the line index (i.e. the Z & Y fields).
+        // -  for an update request the VCI packet length is (n+2) words.
+        // The WDATA field of the first VCI word contains the line number.
+        // The WDATA field of the second VCI word contains the word index.
+        // The WDATA field of the n following words contains the values.
+        // -  for both invalidate & update requests, the VCI response
+        // is one single word.
+        // In case of errors in the VCI command packet, the simulation
+        // is stopped with an error message.
+        /////////////////////////////////////////////////////////////////////
+
+        switch(r_vci_tgt_fsm) {
+
+            case TGT_IDLE:
+                if ( p_vci_tgt.cmdval.read() ) 
+                {
+                    addr_40 address = p_vci_tgt.address.read();
+
+                    if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the received VCI command from " << std::dec << p_vci_tgt.srcid.read() << " is not a write" << std::endl;
+                        exit(0);
+                    }
+
+                    // multi-update or multi-invalidate for data type
+                    if ( (address != 0x3) && (! m_segment.contains(address)) ) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "out of segment VCI command received for a multi-updt or multi-inval request" << std::endl;
+                        exit(0);
+                    }
+
+                    r_tgt_addr = (((addr_40) ((p_vci_tgt.be.read() & 0x3) << 32)) | 
+                                 ((addr_40) (p_vci_tgt.wdata.read()))) * m_dcache_words * 4;      
+                    r_tgt_srcid = p_vci_tgt.srcid.read();
+                    r_tgt_trdid = p_vci_tgt.trdid.read();
+                    r_tgt_pktid = p_vci_tgt.pktid.read();
+                    r_tgt_plen  = p_vci_tgt.plen.read();
+                    
+                    if ( address == 0x3 )   // broadcast invalidate for data or instruction type
+                    {
+                        if ( ! p_vci_tgt.eop.read() ) 
+                        {
+                            std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                            std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
+                            exit(0);
+                        }
+                        r_tgt_update = false; 
+                        r_tgt_brdcast= true;
+                        r_vci_tgt_fsm = TGT_REQ_BROADCAST;
+                        m_cpt_cc_inval++ ;
+                    }
+                    else                    // multi-update or multi-invalidate for data type
+                    { 
+                        uint32_t cell = address - m_segment.baseAddress(); // addr_40
+                        r_tgt_brdcast = false;
+                        if (cell == 0) 
+                        {                                       // invalidate data
+                            if ( ! p_vci_tgt.eop.read() ) 
+                            {
+                                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                                exit(0);
+                            }
+                            r_tgt_update = false; 
+                            r_vci_tgt_fsm = TGT_REQ_DCACHE;
+                            m_cpt_cc_inval++ ;
+                        } 
+                        else if (cell == 4)                     // invalidate instruction
+                        {                         
+                            if ( ! p_vci_tgt.eop.read() ) 
+                            {
+                                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
+                                exit(0);
+                            }
+                            r_tgt_update = false; 
+                            r_vci_tgt_fsm = TGT_REQ_ICACHE;
+                            m_cpt_cc_inval++ ;
+                        } 
+                        else if ( (cell == 8) || (cell==12) )    // update data or instruction
+                        {                                
+                            if ( p_vci_tgt.eop.read() ) 
+                            {
+                                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
+                                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                                exit(0);
+                            }
+                            if(cell == 8)
+                                r_tgt_update_data = true;
+                            else
+                                r_tgt_update_data = false;
+                            r_tgt_update = true; 
+                            r_vci_tgt_fsm = TGT_UPDT_WORD;
+                            m_cpt_cc_update++ ;
+                        } 
+
+                    } // end if address
+                } // end if cmdval
+                break;
+
+            case TGT_UPDT_WORD:
+                if (p_vci_tgt.cmdval.read()) 
+                {
+                    if ( p_vci_tgt.eop.read() ) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
+                        exit(0);
+                    }
+                    for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_be[i] = 0;
+                    r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
+#ifdef COHERENCE_DEBUG
+                    std::cout << "PROC " << m_srcid_rw << " update, line : " << std::hex << r_tgt_addr.read() << " word : " << p_vci_tgt.wdata.read() << std::dec << std::endl;
+#endif
+                    r_vci_tgt_fsm = TGT_UPDT_DATA;
+                }
+                break;
+
+            case TGT_UPDT_DATA:
+                if (p_vci_tgt.cmdval.read()) 
+                {
+                    size_t word = r_tgt_word.read();
+                    if ( word >= m_dcache_words ) 
+                    {
+                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
+                        std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
+                        exit(0);
+                    }
+#ifdef COHERENCE_DEBUG
+                    std::cout << "PROC " << m_srcid_rw << " update, data : " << p_vci_tgt.wdata.read() << " be : " << std::hex << p_vci_tgt.be.read() << std::dec << std::endl;
+#endif
+                    r_tgt_buf[word] = p_vci_tgt.wdata.read();
+                    r_tgt_be[word] = p_vci_tgt.be.read();
+                    r_tgt_word = word + 1;
+                    if (p_vci_tgt.eop.read()){
+                      if(r_tgt_update_data.read()){
+                        r_vci_tgt_fsm = TGT_REQ_DCACHE;
+                      } else {
+                        r_vci_tgt_fsm = TGT_REQ_ICACHE;
+                      }
+                    }
+                }
+                break;
+
+            case TGT_REQ_BROADCAST:
+                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+                {
+                    r_vci_tgt_fsm = TGT_RSP_BROADCAST; 
+                    r_tgt_icache_req = true;
+                    r_tgt_dcache_req = true;
+                }
+                break;
+                ////////////////////
+            case TGT_REQ_ICACHE:
+                {
+                    if ( !r_tgt_icache_req.read() ) 
+                    {
+                        r_vci_tgt_fsm = TGT_RSP_ICACHE; 
+                        r_tgt_icache_req = true;
+                    }
+                    break;
+                }
+
+            case TGT_REQ_DCACHE:
+                if ( !r_tgt_dcache_req.read() ) 
+                {
+                    r_vci_tgt_fsm = TGT_RSP_DCACHE; 
+                    r_tgt_dcache_req = true;
+                }
+                break;
+
+            case TGT_RSP_BROADCAST:
+                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() ) 
+                {
+                    // one response
+                    if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
+                    {
+                        if ( p_vci_tgt.rspack.read() )
+                        {
+                            r_vci_tgt_fsm = TGT_IDLE; 
+                            r_tgt_icache_rsp = false;
+                            r_tgt_dcache_rsp = false;
+                        }
+                    }
+
+                    // if data and instruction have the inval line, need two responses  
+                    if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
+                    {
+                        if ( p_vci_tgt.rspack.read() )
+                        {
+                            r_tgt_icache_rsp = false; // only reset one for respond the second time 
+                        }
+                    }
+
+                    // if there is no need for a response
+                    if ( !r_tgt_icache_rsp && !r_tgt_dcache_rsp )
+                    {
+                        r_vci_tgt_fsm = TGT_IDLE;
+                    }
+
+                }
+                break;
+                ////////////////////
+            case TGT_RSP_ICACHE:
+                {
+                    if ( (p_vci_tgt.rspack.read() || !r_tgt_icache_rsp.read()) && !r_tgt_icache_req.read() ) 
+                    {
+                        r_vci_tgt_fsm = TGT_IDLE;
+                        r_tgt_icache_rsp = false; 
+                    }
+                    break;
+                }
+
+            case TGT_RSP_DCACHE:
+                {
+                    if ( (p_vci_tgt.rspack.read() || !r_tgt_dcache_rsp.read()) && !r_tgt_dcache_req.read() ) 
+                    {
+                        r_vci_tgt_fsm = TGT_IDLE;
+                        r_tgt_dcache_rsp = false; 
+                    }
+                    break;
+                }
+        } // end switch TGT_FSM
+
+        /////////////////////////////////////////////////////////////////////
+        // The ICACHE FSM controls the following ressources:
+        // - r_icache_fsm
+        // - r_icache_fsm_save
+        // - r_icache instruction cache access
+        // - r_icache_addr_save
+        // - r_icache_miss_req set
+        // - r_icache_unc_req set
+        // - r_icache_buf_unc_valid set
+        // - r_vci_rsp_ins_error reset
+        // - r_tgt_icache_req reset
+        // - ireq & irsp structures for communication with the processor
+        //
+        // 1/ External requests (update or invalidate) have highest priority.
+        //    They are taken into account in the IDLE and WAIT states.
+        //    As external hit should be extremly rare on the ICACHE,
+        //    all external requests are handled as invalidate...
+        //    In case of external request the ICACHE FSM goes to the CC_CHECK
+        //    state to test the external hit, and returns in the
+        //    pre-empted state after completion.
+        // 2/ Processor requests are taken into account only in the IDLE state.
+        //    In case of MISS, or in case of uncached instruction, the FSM 
+        //    writes the missing address line in the  r_icache_addr_save register 
+        //    and sets the r_icache_miss_req or the r_icache_unc_req flip-flops.
+        //    These request flip-flops are reset by the VCI_RSP FSM
+        //    when the VCI transaction is completed and the r_icache_buf_unc_valid
+        //    is set in case of uncached access.
+        //    In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 
+        //    flip-flop. It is reset by the ICACHE FSM.
+        ///////////////////////////////////////////////////////////////////////
+
+        typename iss_t::InstructionRequest  ireq = ISS_IREQ_INITIALIZER;
+        typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
+
+        typename iss_t::DataRequest  dreq = ISS_DREQ_INITIALIZER;
+        typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
+
+        m_iss.getRequests( ireq, dreq );
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << " Instruction Request: " << ireq << std::endl;
+#endif
+
+        switch(r_icache_fsm) {
+            /////////////////
+            case ICACHE_IDLE:
+                {
+                    if ( r_tgt_icache_req ) {   // external request
+                        if ( ireq.valid ) m_cost_ins_miss_frz++;
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm.read();
+                        break;
+                    } 
+                    if ( ireq.valid ) {
+                        data_t  icache_ins = 0;
+                        bool    icache_hit = false;
+                        bool    icache_cached = m_cacheability_table[(vci_addr_t)ireq.addr];
+                        // icache_hit & icache_ins evaluation
+                        if ( icache_cached ) {
+                            icache_hit = r_icache.read((vci_addr_t) ireq.addr, &icache_ins);
+                        } else {
+                            icache_hit = ( r_icache_buf_unc_valid && ((addr_40) ireq.addr == (addr_40)r_icache_addr_save) );
+                            icache_ins = r_icache_miss_buf[0];
+                        }
+                        if ( ! icache_hit ) {
+                            m_cpt_ins_miss++;
+                            m_cost_ins_miss_frz++;
+                            r_icache_addr_save = (addr_40) ireq.addr;
+                            if ( icache_cached ) {
+                                r_icache_fsm = ICACHE_MISS_WAIT;
+                                r_icache_miss_req = true;
+                            } else {
+                                r_icache_fsm = ICACHE_UNC_WAIT;
+                                r_icache_unc_req = true;
+                            }
+                        } else {
+                            r_icache_buf_unc_valid = false;
+                        }
+                        m_cpt_icache_dir_read += m_icache_ways;
+                        m_cpt_icache_data_read += m_icache_ways;
+                        irsp.valid          = icache_hit;
+                        irsp.instruction    = icache_ins;
+                    }
+                    break;
+                }
+                //////////////////////
+            case ICACHE_MISS_WAIT:
+                {
+                    m_cost_ins_miss_frz++;
+                    if ( r_tgt_icache_req ) {   // external request
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm.read();
+                        break;
+                    } 
+                    if ( !r_icache_miss_req && !r_icache_inval_rsp ) { // Miss read response and no invalidation
+                        if ( r_vci_rsp_ins_error ) {
+                            r_icache_fsm = ICACHE_ERROR;
+                        } else {
+                            r_icache_fsm = ICACHE_MISS_UPDT;
+                        }
+                    }
+                    if ( !r_icache_miss_req && r_icache_inval_rsp ) { // Miss read response and invalidation
+                        if ( r_vci_rsp_ins_error ) {
+                            r_icache_inval_rsp = false;
+                            r_icache_fsm = ICACHE_ERROR;
+                        } else {
+                            r_icache_inval_rsp = false;
+                            r_icache_fsm = ICACHE_CC_CLEANUP;
+                        }
+                    }
+                    break;
+                }
+                /////////////////////
+            case ICACHE_UNC_WAIT:
+                {
+                    m_cost_ins_miss_frz++;
+                    if ( r_tgt_icache_req ) {   // external request
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm.read();
+                        break;
+                    } 
+                    if ( !r_icache_unc_req ) {
+                        if ( r_vci_rsp_ins_error ) {
+                            r_icache_fsm = ICACHE_ERROR;
+                        } else {
+                            r_icache_fsm = ICACHE_IDLE;
+                            r_icache_buf_unc_valid = true;
+                        }
+                    }
+                    break;
+                }
+                //////////////////
+            case ICACHE_ERROR:
+                {
+                    r_icache_fsm = ICACHE_IDLE;
+                    r_vci_rsp_ins_error = false;
+                    irsp.error          = true;
+                    irsp.valid          = true;
+                    break;
+                }
+                //////////////////////
+            case ICACHE_MISS_UPDT: 
+                {
+                    if ( r_tgt_icache_req ) {   // external request
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm.read();
+                        break;
+                    } 
+                    if(!r_icache_cleanup_req.read() && !r_icache_inval_rsp){
+                        vci_addr_t ad   = 0;
+                        ad              = (vci_addr_t) r_icache_addr_save.read();
+                        data_t*   buf   = r_icache_miss_buf;
+                        vci_addr_t victim_index = 0;
+                        m_cpt_icache_dir_write++;
+                        m_cpt_icache_data_write++;
+                        if ( ireq.valid ) m_cost_ins_miss_frz++;
+
+                        r_icache_cleanup_req  = r_icache.update(ad, buf, &victim_index);
+                        r_icache_cleanup_line = (addr_40) victim_index;
+
+                        r_icache_fsm        = ICACHE_IDLE;
+                        break;
+                    }
+                    if(r_icache_inval_rsp){
+                        if ( ireq.valid ) m_cost_ins_miss_frz++;
+                        r_icache_inval_rsp  = false;
+                        r_icache_fsm = ICACHE_CC_CLEANUP;
+                        break;
+                    }
+                    if ( ireq.valid ) m_cost_ins_miss_frz++;
+                }
+                ////////////////////
+            case ICACHE_CC_CLEANUP:
+                {
+                    // external cache invalidate request
+                    if ( r_tgt_icache_req )     
+                    {
+                        r_icache_fsm = ICACHE_CC_CHECK;
+                        r_icache_fsm_save = r_icache_fsm.read();
+                        break;
+                    }
+                    // cleanup
+                    if(!r_icache_cleanup_req){
+                        r_icache_cleanup_req = true;
+                        r_icache_cleanup_line = r_icache_addr_save.read() >> (uint32_log2(m_icache_words) + 2);   
+                        r_icache_fsm = ICACHE_IDLE;
+                    }
+                    break;
+                }
+                /////////////////////
+            case ICACHE_CC_CHECK:   // read directory in case of invalidate or update request
+                {
+
+                    m_cpt_icache_dir_read += m_icache_ways;
+                    m_cpt_icache_data_read += m_icache_ways;
+                    addr_40  ad           = r_tgt_addr;
+                    data_t  icache_rdata = 0;
+
+                    if(( ( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT ) ) && 
+                            ( (r_icache_addr_save.read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) {
+                        r_icache_inval_rsp = true;
+                        r_tgt_icache_req = false;
+                        if(r_tgt_update){    // Also send a cleanup and answer
+                            r_tgt_icache_rsp     = true;
+                        } else {            // Also send a cleanup but don't answer
+                            r_tgt_icache_rsp     = false;
+                        }
+                        r_icache_fsm = r_icache_fsm_save;
+                    } else {
+                        bool    icache_hit   = r_icache.read(ad, &icache_rdata);
+                        if ( icache_hit && r_tgt_update ) {
+                            r_icache_fsm = ICACHE_CC_UPDT;
+                            // complete the line buffer in case of update
+                            for(size_t i=0; i<m_dcache_words; i++){
+                                data_t rdata = 0;
+                                r_dcache.read(ad + i*4,&rdata);
+                                data_t mask = vci_param::be2mask(r_tgt_be[i]);
+                                r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata);
+                            }
+                        } else if ( icache_hit && !r_tgt_update ) {
+                            r_icache_fsm = ICACHE_CC_INVAL;
+                        } else { // instruction not found (can happen)
+                            r_tgt_icache_req = false;
+                            if(r_tgt_update){
+                                r_tgt_icache_rsp = true;
+                            } else {
+                                r_tgt_icache_rsp = false;
+                            }
+                            r_icache_fsm = r_icache_fsm_save;
+                        }
+                    }
+                    break;
+                }
+                /////////////////////
+            case ICACHE_CC_INVAL:  
+                {                       
+                    addr_40    ad  = r_tgt_addr;
+                    if ( ireq.valid ) m_cost_ins_miss_frz++;
+                    m_cpt_icache_dir_read += m_icache_ways;
+                    r_tgt_icache_rsp = true;
+                    r_icache.inval(ad);
+                    r_tgt_icache_req = false;
+                    r_icache_fsm = r_icache_fsm_save;
+                    break;
+                }    
+                /////////////////////
+            case ICACHE_CC_UPDT:
+                {                       
+                    m_cpt_icache_dir_write++;
+                    m_cpt_icache_data_write++;
+                    addr_40    ad  = r_tgt_addr.read();
+                    data_t* buf    = r_tgt_buf;
+                    for(size_t i=0; i<m_icache_words;i++){
+                        if(r_tgt_be[i]) r_icache.write( ad + i*4, buf[i]);
+                    }
+                    r_tgt_icache_req = false;
+                    r_tgt_icache_rsp = true;
+                    r_icache_fsm     = r_icache_fsm_save.read();
+                    break;
+                }    
+
+        } // end switch r_icache_fsm
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << " Instruction Response: " << irsp << std::endl;
+#endif
+
+        //////////////////////////////////////////////////////////////////////://///////////
+        // The DCACHE FSM controls the following ressources:
+        // - r_dcache_fsm
+        // - r_dcache_fsm_save
+        // - r_dcache (data cache access)
+        // - r_dcache_addr_save
+        // - r_dcache_wdata_save
+        // - r_dcache_rdata_save
+        // - r_dcache_type_save
+        // - r_dcache_be_save
+        // - r_dcache_cached_save
+        // - r_dcache_miss_req set
+        // - r_dcache_unc_req set
+        // - r_dcache_write_req set
+        // - r_dcache_cleanup_req set
+        // - r_vci_rsp_data_error reset
+        // - r_tgt_dcache_req reset
+        // - r_wbuf write
+        // - dreq & drsp structures for communication with the processor
+        //
+        // 1/ EXTERNAL REQUEST : 
+        //    There is an external request when the tgt_dcache req flip-flop is set,
+        //    requesting a line invalidation or a line update. 
+        //    External requests are taken into account in the states  IDLE, WRITE_REQ,  
+        //    UNC_WAIT, MISS_WAIT, and have the highest priority :
+        //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
+        //    goes to the CC_CHECK state to execute the requested action, and returns to the
+        //    pre-empted state.
+        //  2/ PROCESSOR REQUEST : 
+        //   In order to support VCI write burst, the processor requests are taken into account
+        //   in the WRITE_REQ state as well as in the IDLE state.
+        //   - In the IDLE state, the processor request cannot be satisfied if
+        //   there is a cached read miss, or an uncached read.
+        //   - In the WRITE_REQ state, the request cannot be satisfied if
+        //   there is a cached read miss, or an uncached read,
+        //   or when the write buffer is full.
+        //   - In all other states, the processor request is not satisfied.
+        //
+        //   The cache access takes into account the cacheability_table.
+        //   In case of processor request, there is five conditions to exit the IDLE state:
+        //   - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal), 
+        //     then to the MISS_UPDT state, and finally to the IDLE state.
+        //   - UNCACHED READ  => to the UNC_WAIT state (waiting the r_miss_ok signal), 
+        //     and to the IDLE state.
+        //   - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state.
+        //   - WRITE MISS => directly to the WRITE_REQ state to access the write buffer.
+        //   - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state.
+        //
+        // Error handling :  Read Bus Errors are synchronous events, but
+        // Write Bus Errors are asynchronous events (processor is not frozen).
+        // - If a Read Bus Error is detected, the VCI_RSP FSM sets the
+        //   r_vci_rsp_data_error flip-flop, and the synchronous error is signaled
+        //   by the DCACHE FSM.
+        // - If a Write Bus Error is detected, the VCI_RSP FSM  signals
+        //   the asynchronous error using the setWriteBerr() method.
+        ///////////////////////////////////////////////////////////////////////////////////
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << " Data Request: " << dreq << std::endl;
+#endif
+
+        //if( (m_cpt_total_cycles % 10000) ==0 ) std::cout << std::dec << "Proc " << m_srcid << " Data Request: " << dreq << std::endl;
+
+        switch ( r_dcache_fsm ) {
+
+            /////////////////////
+            case DCACHE_WRITE_REQ:
+                { 
+                    if ( r_tgt_dcache_req ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }
+                    // try to post the write request in the write buffer
+                    if ( !r_dcache_write_req ) {    // no previous write transaction     
+                        if ( r_wbuf.wok(r_dcache_addr_save) ) {   // write request in the same cache line
+                            r_wbuf.write(r_dcache_addr_save, r_dcache_be_save, r_dcache_wdata_save);
+                            // close the write packet if uncached
+                            if ( !r_dcache_cached_save ){
+                                r_dcache_write_req = true ;
+                            }
+                        } else {    
+                            // close the write packet if write request not in the same cache line
+                            r_dcache_write_req = true;  
+                            if(!m_srcid_rw) {
+                            }
+                            m_cost_write_frz++;
+                            break;  // posting request not possible : stay in DCACHE_WRITEREQ state
+                        }
+                    } else {    //  previous write transaction not completed
+                        m_cost_write_frz++;
+                        break;  // posting request not possible : stay in DCACHE_WRITEREQ state  
+                    }
+
+                    // close the write packet if the next processor request is not a write 
+                    if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE) ) {
+                        r_dcache_write_req = true ;
+                    }
+
+                    // The next state and the processor request parameters are computed 
+                    // as in the DCACHE_IDLE state (see below ...)
+                }
+                /////////////////
+            case DCACHE_IDLE:
+                {
+                    if ( r_tgt_dcache_req ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    } 
+
+                    if ( dreq.valid ) {              
+                        bool        dcache_hit     = false;
+                        data_t      dcache_rdata   = 0;
+                        bool        dcache_cached;
+                        m_cpt_dcache_data_read += m_dcache_ways;
+                        m_cpt_dcache_dir_read += m_dcache_ways;
+
+                        // dcache_cached evaluation
+                        switch (dreq.type) {
+                            case iss_t::DATA_SC:
+                            case iss_t::XTN_READ:
+                            case iss_t::XTN_WRITE:
+                                dcache_cached = false;
+                                break;
+                            default:
+                                dcache_cached = m_cacheability_table[(vci_addr_t)dreq.addr];
+                        }
+
+                        // dcache_hit & dcache_rdata evaluation
+                        if ( dcache_cached ) {
+                            dcache_hit = r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
+                        } else {
+                            dcache_hit = false;
+                        }
+
+                        switch( dreq.type ) {
+                            case iss_t::DATA_READ:
+                            case iss_t::DATA_LL:
+                                m_cpt_read++;
+                                if ( dcache_hit ) {
+                                    r_dcache_fsm = DCACHE_IDLE;
+                                    drsp.valid = true;
+                                    drsp.rdata = dcache_rdata;
+                                    if(dreq.type == iss_t::DATA_LL){
+                                        r_dcache_ll_valid = true;
+                                        r_dcache_ll_data = dcache_rdata;
+                                        r_dcache_ll_addr = (vci_addr_t) dreq.addr;
+#ifdef COHERENCE_DEBUG
+                                        std::cout << "Value returned for LL at address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
+                                        r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
+                                        std::cout << "Value stored at this  address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
+#endif
+                                    }
+                                } else {
+                                    if ( dcache_cached ) {
+                                        m_cpt_data_miss++;
+                                        m_cost_data_miss_frz++;
+                                        r_dcache_miss_req = true;
+                                        r_dcache_fsm = DCACHE_MISS_WAIT;
+                                    } else {
+                                        m_cpt_unc_read++;
+                                        m_cost_unc_read_frz++;
+                                        r_dcache_unc_req = true;
+                                        r_dcache_fsm = DCACHE_UNC_WAIT;
+                                    }
+                                }
+                                break;
+                            case iss_t::DATA_SC:
+                            {
+                                m_cpt_unc_read++;
+                                m_cost_unc_read_frz++;
+                                if(r_dcache_ll_valid.read() && (r_dcache_ll_addr.read() == (vci_addr_t)dreq.addr)){
+                                    r_dcache_sc_req = true;
+                                    r_dcache_fsm = DCACHE_SC_WAIT;
+                                } else {
+                                    drsp.valid = true;
+                                    drsp.rdata = 1; // SC rsp NOK
+                                    r_dcache_ll_valid = false;
+                                }
+                                break;
+                            }
+                            case iss_t::XTN_READ:
+                            case iss_t::XTN_WRITE:
+                                    // only DCACHE INVALIDATE request are supported
+                                    if ( dreq.addr/4 == iss_t::XTN_DCACHE_INVAL ){
+                                        r_dcache_fsm = DCACHE_INVAL;
+                                    } else {
+                                        r_dcache_fsm = DCACHE_IDLE;
+                                    }
+                                    drsp.valid = true;
+                                    drsp.rdata = 0;
+                                    break;
+                            case iss_t::DATA_WRITE:
+                                    m_cpt_write++;
+                                    if ( dcache_hit && dcache_cached ) {
+                                        r_dcache_fsm = DCACHE_WRITE_UPDT;
+                                        m_cpt_write_cached++;
+                                    } else {
+                                        r_dcache_fsm = DCACHE_WRITE_REQ;
+                                    }
+                                    drsp.valid = true;
+                                    drsp.rdata = 0;
+                                    break;
+                        } // end switch dreq.type
+
+                        r_dcache_addr_save      = (addr_40) dreq.addr;
+                        r_dcache_type_save      = dreq.type;
+                        r_dcache_wdata_save     = dreq.wdata;
+                        r_dcache_be_save        = dreq.be;
+                        r_dcache_rdata_save     = dcache_rdata;
+                        r_dcache_cached_save    = dcache_cached;
+
+                    } else {    // end if dreq.valid
+                        r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    // processor request are not accepted in the WRITE_REQUEST state
+                    // when the write buffer is not writeable
+                    if ( (r_dcache_fsm == DCACHE_WRITE_REQ) &&
+                            (r_dcache_write_req || !r_wbuf.wok(r_dcache_addr_save)) ) {
+                        drsp.valid = false;
+                        drsp.rdata = 0;
+                    }
+                    break;
+                }
+                ///////////////////////
+            case DCACHE_WRITE_UPDT:
+                {
+                    m_cpt_dcache_data_write++;
+                    data_t mask = vci_param::be2mask(r_dcache_be_save);
+                    data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
+                    vci_addr_t ad = r_dcache_addr_save.read();
+                    r_dcache.write(ad, wdata);
+                    r_dcache_fsm = DCACHE_WRITE_REQ;
+                    break;
+                }
+                //////////////////////
+            case DCACHE_MISS_WAIT:
+                {
+
+                    if ( dreq.valid ) m_cost_data_miss_frz++;
+                    if ( r_tgt_dcache_req.read() ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }
+                    if ( !r_dcache_miss_req && !r_dcache_inval_rsp ) { // Miss read response and no invalidation
+                        if ( r_vci_rsp_data_error ) {
+                            r_dcache_fsm = DCACHE_ERROR;
+                        } else {
+                            r_dcache_fsm = DCACHE_MISS_UPDT;
+                        }
+                        break;
+                    }
+                    if ( !r_dcache_miss_req && r_dcache_inval_rsp ) { // Miss read response and invalidation
+                        if ( r_vci_rsp_data_error ) {
+                            r_dcache_inval_rsp  = false;
+                            r_dcache_fsm = DCACHE_ERROR;
+                        } else {
+                            r_dcache_inval_rsp  = false;
+                            r_dcache_fsm = DCACHE_CC_CLEANUP;
+                        }
+                        break;
+                    }
+                    break;
+                }
+                //////////////////////
+            case DCACHE_MISS_UPDT:
+
+                {
+                        if ( r_tgt_dcache_req.read() ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }
+                    if( !r_dcache_cleanup_req.read() && !r_dcache_inval_rsp ){
+                        vci_addr_t  ad  = 0;
+                        ad = (vci_addr_t) r_dcache_addr_save.read();
+                        data_t* buf = new data_t[m_dcache_words];
+                        for(size_t i=0; i<m_dcache_words; i++) {
+                            buf[i] = r_dcache_miss_buf[i];
+                        }
+                        vci_addr_t  victim_index = 0;
+                        if ( dreq.valid ) m_cost_data_miss_frz++;
+                        m_cpt_dcache_data_write++;
+                        m_cpt_dcache_dir_write++;
+
+                        r_dcache_cleanup_req = r_dcache.update(ad, buf, &victim_index);
+                        r_dcache_cleanup_line = (addr_40) victim_index;
+
+                        r_dcache_fsm = DCACHE_IDLE;
+                        delete [] buf;
+                        break;
+                    }
+                    if( r_dcache_inval_rsp ){
+                        r_dcache_inval_rsp  = false;
+                        r_dcache_fsm = DCACHE_CC_CLEANUP;
+                        break;
+                    }
+                    break;
+                }
+                ////////////////////
+            case DCACHE_UNC_WAIT:
+                {
+                    if ( dreq.valid ) m_cost_unc_read_frz++;
+                    if ( r_tgt_dcache_req ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    } 
+                    if ( !r_dcache_unc_req ) {
+                        if ( r_vci_rsp_data_error ) {
+                            r_dcache_fsm = DCACHE_ERROR;
+                        } else {
+                            if(dreq.type == iss_t::DATA_LL){
+                                r_dcache_ll_valid = true;
+                                r_dcache_ll_data = r_dcache_miss_buf[0];
+                                r_dcache_ll_addr = (vci_addr_t) dreq.addr;
+                            }
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = r_dcache_miss_buf[0];
+                        }
+                    }
+                    break;
+                }
+                ////////////////////
+            case DCACHE_SC_WAIT:
+                {
+                    if ( dreq.valid ) m_cost_unc_read_frz++;
+                    if ( r_tgt_dcache_req ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    } 
+                    if ( !r_dcache_sc_req ) {
+                        if ( r_vci_rsp_data_error ) {
+                            r_dcache_fsm = DCACHE_ERROR;
+                        } else {
+                            r_dcache_fsm = DCACHE_IDLE;
+                            drsp.valid = true;
+                            drsp.rdata = r_dcache_miss_buf[0];
+                            r_dcache_ll_valid = false;
+                        }
+                    }
+                    break;
+                }
+
+                //////////////////
+            case DCACHE_ERROR:
+                {
+                    r_dcache_fsm = DCACHE_IDLE;
+                    r_vci_rsp_data_error = false;
+                    drsp.error = true;
+                    drsp.valid = true;
+                    break;
+                }
+                /////////////////    
+            case DCACHE_INVAL:
+                {
+                    if ( r_tgt_dcache_req.read() ) {   // external request
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }
+                    if( !r_dcache_cleanup_req.read() ){
+                        m_cpt_dcache_dir_read += m_dcache_ways;
+                        vci_addr_t  ad  = r_dcache_addr_save.read();
+                        r_dcache_cleanup_req = r_dcache.inval(ad);
+                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> (uint32_log2(m_dcache_words)+2);
+
+                        r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+                }
+                /////////////////////
+            case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
+                {
+
+                    m_cpt_dcache_dir_read += m_dcache_ways;
+                    m_cpt_dcache_data_read += m_dcache_ways;
+                    addr_40  ad           = r_tgt_addr;
+                    data_t  dcache_rdata = 0;
+
+                    if(( ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) && 
+                            ( (r_dcache_addr_save.read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) {
+                        r_dcache_inval_rsp = true;
+                        r_tgt_dcache_req = false;
+                        if(r_tgt_update){    // Also send a cleanup and answer
+                            r_tgt_dcache_rsp     = true;
+                        } else {            // Also send a cleanup but don't answer
+                            r_tgt_dcache_rsp     = false;
+                        }
+                        r_dcache_fsm = r_dcache_fsm_save;
+                    } else {
+                        bool    dcache_hit   = r_dcache.read(ad, &dcache_rdata);
+#ifdef COHERENCE_DEBUG
+                        std::cout << "PROC " << m_srcid_rw << " DCACHE_CC_CHECK, hit ? : " << dcache_hit << std::endl;
+#endif
+                        if ( dcache_hit && r_tgt_update ) {
+                            // complete the line buffer in case of update
+                            for(size_t i=0; i<m_dcache_words; i++){
+                                data_t rdata = 0;
+                                r_dcache.read(ad + i*4,&rdata);
+                                data_t mask = vci_param::be2mask(r_tgt_be[i]);
+                                r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata);
+                            }
+                            r_dcache_fsm = DCACHE_CC_UPDT;
+                        } else if ( dcache_hit && !r_tgt_update ) {
+                            r_dcache_fsm = DCACHE_CC_INVAL;
+                        } else {
+                            if(r_tgt_update){
+                                r_tgt_dcache_rsp = true;
+                            } else {
+                                r_tgt_dcache_rsp = false;
+                            }
+                            r_tgt_dcache_req = false;
+                            r_dcache_fsm = r_dcache_fsm_save;
+                        }
+                    }
+                    break;
+                }
+                ///////////////////
+            case DCACHE_CC_UPDT:    // update directory and data cache        
+                {
+                    m_cpt_dcache_dir_write++;
+                    m_cpt_dcache_data_write++;
+                    addr_40  ad      = r_tgt_addr;
+                    data_t* buf     = r_tgt_buf;
+#ifdef COHERENCE_DEBUG
+                    std::cout << "PROC " << m_srcid_rw << " DCACHE_CC_UPDT, update : " << std::endl;
+#endif
+                    for(size_t i=0; i<m_dcache_words; i++){
+                        if(r_tgt_be[i]) {
+                            r_dcache.write( ad + i*4, buf[i]);
+#ifdef COHERENCE_DEBUG
+                            std::cout << " address " << std::hex << ad+i*4 << " data " << std::dec << buf[i] << std::endl;
+                            data_t rdata = 0xAAAAAAAA;
+                            r_dcache.read(ad + i*4,&rdata);
+                            std::cout << "data written " << rdata << std::endl; 
+#endif
+                        }
+                    }
+                    r_tgt_dcache_req = false;
+                    r_tgt_dcache_rsp = true;
+                    r_dcache_fsm = r_dcache_fsm_save;
+                    break;
+                }
+                /////////////////////
+            case DCACHE_CC_INVAL:   // invalidate a cache line
+                {
+                    addr_40  ad      = r_tgt_addr;
+                    r_tgt_dcache_rsp = true;
+                    r_dcache.inval(ad);
+                    r_tgt_dcache_req = false;
+                    r_dcache_fsm = r_dcache_fsm_save;
+                    break;
+                }
+                ///////////////////
+            case DCACHE_CC_CLEANUP:   
+                {
+                    // external cache invalidate request
+                    if ( r_tgt_dcache_req )   
+                    {
+                        r_dcache_fsm = DCACHE_CC_CHECK;
+                        r_dcache_fsm_save = r_dcache_fsm;
+                        break;
+                    }        
+                    // cleanup
+                    if(!r_dcache_cleanup_req){
+                        r_dcache_cleanup_req = true;
+                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> (uint32_log2(m_dcache_words) + 2);
+                        r_dcache_fsm = DCACHE_IDLE;
+                    }
+                    break;
+                }    
+
+        } // end switch r_dcache_fsm
+
+#if DEBUG_CC_XCACHE_WRAPPER
+        std::cout << " Data Response: " << drsp << std::endl;
+#endif
+
+        /////////// execute one iss cycle /////////////////////////////////////////////
+        {
+            uint32_t it = 0;
+            for (size_t i=0; i<(size_t)iss_t::n_irq; i++) 
+                if(p_irq[i].read()) it |= (1<<i);
+            m_iss.executeNCycles(1, irsp, drsp, it);
+        }
+
+        if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) ) m_cpt_frz_cycles++;
+
+
+        ////////////////////////////////////////////////////////////////////////////
+        // The VCI_CMD FSM controls the following ressources:
+        // - r_vci_cmd_fsm
+        // - r_vci_cmd_min
+        // - r_vci_cmd_max
+        // - r_vci_cmd_cpt
+        // - wbuf reset
+        //
+        // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
+        // There is 7 request types, with the following priorities : 
+        // 1 - Instruction Miss     : r_icache_miss_req
+        // 2 - Data Write           : r_dcache_write_req
+        // 3 - Data Read Miss       : r_dcache_miss_req 
+        // 4 - Data Read Uncached   : r_dcache_unc_req 
+        // 5 - Instruction Cleanup  : r_icache_cleanup_req 
+        // 6 - Data Cleanup         : r_dcache_cleanup_req 
+        // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM 
+        // and RSP_FSM exit simultaneously the IDLE state.
+        //
+        // VCI formats:
+        // According to the VCI advanced specification, all read requests packets 
+        // (read Uncached, Miss data, Miss instruction) are one word packets.
+        // For write burst packets, all words must be in the same cache line,
+        // and addresses must be contiguous (the BE field is 0 in case of "holes").
+        //////////////////////////////////////////////////////////////////////////////
+
+        switch (r_vci_cmd_fsm) {
+
+            case CMD_IDLE:
+                if (r_vci_rsp_fsm != RSP_IDLE) break;
+
+                r_vci_cmd_cpt = 0;
+                if ( r_icache_cleanup_req ) { 
+                    r_vci_cmd_fsm = CMD_INS_CLEANUP; 
+                } else if ( r_dcache_cleanup_req ) { 
+                    r_vci_cmd_fsm = CMD_DATA_CLEANUP;
+                } else if ( r_icache_miss_req ) { 
+                    r_vci_cmd_fsm = CMD_INS_MISS; 
+                    m_cpt_imiss_transaction++;
+                } else if ( r_icache_unc_req ) { 
+                    r_vci_cmd_fsm = CMD_INS_UNC; 
+                    m_cpt_imiss_transaction++;
+                } else if ( r_dcache_write_req ) { 
+                    r_vci_cmd_fsm = CMD_DATA_WRITE;
+                    r_vci_cmd_cpt = r_wbuf.getMin();
+                    r_vci_cmd_min = r_wbuf.getMin();
+                    r_vci_cmd_max = r_wbuf.getMax(); 
+                    m_cpt_write_transaction++; 
+                    m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1); 
+                } else if ( r_dcache_miss_req ) { 
+                    r_vci_cmd_fsm = CMD_DATA_MISS;
+                    m_cpt_dmiss_transaction++; 
+                } else if ( r_dcache_unc_req ) { 
+                    r_vci_cmd_fsm = CMD_DATA_UNC;
+                    m_cpt_unc_transaction++; 
+                } else if ( r_dcache_sc_req ) { 
+                    r_vci_cmd_fsm = CMD_DATA_SC;
+                    r_vci_cmd_max = 1; 
+                    m_cpt_unc_transaction++; 
+                }
+                break;
+
+            case CMD_DATA_WRITE:
+                if ( p_vci_ini_rw.cmdack.read() ) {
+                    r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
+                    if (r_vci_cmd_cpt == r_vci_cmd_max) {
+                        r_vci_cmd_fsm = CMD_IDLE ;
+                        r_wbuf.reset() ;
+                    }
+                }
+                break;
+
+            case CMD_DATA_SC:
+                if ( p_vci_ini_rw.cmdack.read() ) {
+                    r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
+                    if (r_vci_cmd_cpt == r_vci_cmd_max) {
+                        r_vci_cmd_fsm = CMD_IDLE ;
+                    }
+                }
+                break;
+            case CMD_INS_MISS:
+            case CMD_INS_UNC:
+            case CMD_DATA_MISS:
+            case CMD_DATA_UNC:
+                if ( p_vci_ini_rw.cmdack.read() ) {
+                    r_vci_cmd_fsm = CMD_IDLE;
+                }
+                break;
+            case CMD_INS_CLEANUP:
+            case CMD_DATA_CLEANUP:
+                if ( p_vci_ini_c.cmdack.read() ) {
+                    r_vci_cmd_fsm = CMD_IDLE;
+                }
+                break;
+
+        } // end  switch r_vci_cmd_fsm
+
+        //////////////////////////////////////////////////////////////////////////
+        // The VCI_RSP FSM controls the following ressources:
+        // - r_vci_rsp_fsm:
+        // - r_icache_miss_buf[m_icache_words]
+        // - r_dcache_miss_buf[m_dcache_words]
+        // - r_icache_miss_req reset
+        // - r_icache_unc_req reset
+        // - r_dcache_miss_req reset
+        // - r_icache_cleanup_req reset
+        // - r_dcache_cleanup_req reset
+        // - r_vci_rsp_data_error set
+        // - r_vci_rsp_ins_error set
+        // - r_vci_rsp_cpt
+        // In order to have only one active VCI transaction, this VCI_RSP_FSM 
+        // is synchronized with the VCI_CMD FSM, and both FSMs exit the
+        // IDLE state simultaneously.
+        // 
+        // VCI formats:
+        // This component accepts single word or multi-word response packets for
+        // write response packets. 
+        //
+        // Error handling:
+        // This FSM analyzes the VCI error code and signals directly the
+        // Write Bus Error. 
+        // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error 
+        // flip_flop and the error is signaled by the DCACHE FSM.  
+        // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 
+        // flip_flop and the error is signaled by the DCACHE FSM.  
+        // In case of Cleanup Error, the simulation stops with an error message...
+        //////////////////////////////////////////////////////////////////////////
+
+        switch (r_vci_rsp_fsm) {
+
+            case RSP_IDLE:
+                if(p_vci_ini_rw.rspval.read()||
+                        p_vci_ini_c.rspval.read())
+                {
+                    std::cout << "CC_XCache " << m_srcid_rw << " Unexpected response" << std::endl;
+                }
+                assert( ! p_vci_ini_rw.rspval.read() && ! p_vci_ini_c.rspval.read() && "Unexpected response" );
+                if (r_vci_cmd_fsm != CMD_IDLE) break;
+
+                r_vci_rsp_cpt = 0;
+                if      ( r_icache_cleanup_req )    r_vci_rsp_fsm = RSP_INS_CLEANUP;
+                else if ( r_dcache_cleanup_req )    r_vci_rsp_fsm = RSP_DATA_CLEANUP;
+                else if ( r_icache_miss_req )       r_vci_rsp_fsm = RSP_INS_MISS;
+                else if ( r_icache_unc_req )        r_vci_rsp_fsm = RSP_INS_UNC;
+                else if ( r_dcache_write_req )      r_vci_rsp_fsm = RSP_DATA_WRITE;
+                else if ( r_dcache_miss_req )       r_vci_rsp_fsm = RSP_DATA_MISS;
+                else if ( r_dcache_unc_req )        r_vci_rsp_fsm = RSP_DATA_UNC;
+                else if ( r_dcache_sc_req )         r_vci_rsp_fsm = RSP_DATA_SC;
+                break;
+
+            case RSP_INS_MISS:
+                m_cost_imiss_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                assert( (r_vci_rsp_cpt < m_icache_words) &&
+                        "The VCI response packet for instruction miss is too long" );
+                r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+                r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+
+                if ( p_vci_ini_rw.reop.read() ) {
+                    assert( (r_vci_rsp_cpt == m_icache_words - 1) &&
+                            "The VCI response packet for instruction miss is too short");
+                    r_icache_miss_req = false;
+                    r_vci_rsp_fsm = RSP_IDLE;
+                }
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+                break;
+
+            case RSP_INS_UNC:
+                m_cost_imiss_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                assert(p_vci_ini_rw.reop.read() &&
+                        "illegal VCI response packet for uncached instruction");
+                r_icache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+                r_vci_rsp_fsm = RSP_IDLE;
+                r_icache_unc_req = false;
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
+                break;
+
+            case RSP_DATA_MISS:
+                m_cost_dmiss_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                assert(r_vci_rsp_cpt != m_dcache_words &&
+                        "illegal VCI response packet for data read miss");
+                r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
+                r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
+                if ( p_vci_ini_rw.reop.read() ) {
+                    assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
+                            "illegal VCI response packet for data read miss");
+                    r_dcache_miss_req = false;
+                    r_vci_rsp_fsm = RSP_IDLE;
+                }
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                break;
+
+            case RSP_DATA_WRITE:
+                m_cost_write_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                if ( p_vci_ini_rw.reop.read() ) {
+                    r_vci_rsp_fsm = RSP_IDLE;
+                    r_dcache_write_req = false;
+                }
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) m_iss.setWriteBerr();
+                break;
+
+            case RSP_DATA_UNC:
+                m_cost_unc_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                assert(p_vci_ini_rw.reop.read() &&
+                        "illegal VCI response packet for data read uncached");
+                r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+                r_vci_rsp_fsm = RSP_IDLE;
+                r_dcache_unc_req = false;
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                break;
+
+            case RSP_DATA_SC:
+                m_cost_unc_transaction++;
+                if ( ! p_vci_ini_rw.rspval.read() )
+                    break;
+                assert(p_vci_ini_rw.reop.read() &&
+                        "illegal VCI response packet for data SC");
+                r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
+                r_vci_rsp_fsm = RSP_IDLE;
+                r_dcache_sc_req = false;
+                if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
+                break;
+
+            case RSP_INS_CLEANUP:
+            case RSP_DATA_CLEANUP:
+                if ( ! p_vci_ini_c.rspval.read() )
+                    break;
+                assert( p_vci_ini_c.reop.read() &&
+                        "illegal VCI response packet for icache cleanup");
+                assert( (p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL) &&
+                        "error in response packet for icache cleanup");
+                if ( r_vci_rsp_fsm == RSP_INS_CLEANUP ) r_icache_cleanup_req = false;
+                else                                    r_dcache_cleanup_req = false;
+                r_vci_rsp_fsm = RSP_IDLE;
+                break;
+
+        } // end switch r_vci_rsp_fsm
+
+    } // end transition()
+
+    //////////////////////////////////////////////////////////////////////////////////
+    tmpl(void)::genMoore()
+        //////////////////////////////////////////////////////////////////////////////////
+    {
+        // VCI initiator response
+
+        p_vci_ini_rw.rspack = true;
+        p_vci_ini_c.rspack = true;
+
+        // VCI initiator command
+
+        switch (r_vci_cmd_fsm.read() ) {
+
+            case CMD_IDLE:
+                p_vci_ini_rw.cmdval  = false;
+                p_vci_ini_rw.address = 0;
+                p_vci_ini_rw.wdata   = 0;
+                p_vci_ini_rw.be      = 0;
+                p_vci_ini_rw.plen    = 0;
+                p_vci_ini_rw.cmd     = vci_param::CMD_NOP;
+                p_vci_ini_rw.trdid   = 0;
+                p_vci_ini_rw.pktid   = 0;
+                p_vci_ini_rw.srcid   = 0;
+                p_vci_ini_rw.cons    = false;
+                p_vci_ini_rw.wrap    = false;
+                p_vci_ini_rw.contig  = false;
+                p_vci_ini_rw.clen    = 0;
+                p_vci_ini_rw.cfixed  = false;
+                p_vci_ini_rw.eop     = false;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_DATA_UNC:
+                p_vci_ini_rw.cmdval = true;
+                p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
+                switch( r_dcache_type_save ) {
+                    case iss_t::DATA_READ:
+                        p_vci_ini_rw.wdata = 0;
+                        p_vci_ini_rw.be  = r_dcache_be_save.read();
+                        p_vci_ini_rw.cmd = vci_param::CMD_READ;
+                        break;
+                    case iss_t::DATA_LL:
+                        p_vci_ini_rw.wdata = 0;
+                        p_vci_ini_rw.be  = 0xF;
+                        p_vci_ini_rw.cmd = vci_param::CMD_LOCKED_READ;
+                        break;
+                    default:
+                        assert("this should not happen");
+                }
+                p_vci_ini_rw.plen = 4;
+                p_vci_ini_rw.trdid  = 0;   // data cache uncached read
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = m_srcid_rw;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = true;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop    = true;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_DATA_SC:
+                p_vci_ini_rw.cmdval = true;
+                p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
+                if(r_vci_cmd_max.read() == 3){
+                    assert(false && "Not handled yet");
+                } else { // r_vci_cmd_cpt == 1
+                    switch(r_vci_cmd_cpt.read()){
+                        case 0:
+                            p_vci_ini_rw.wdata = (uint32_t)(r_dcache_ll_data.read() & 0xFFFFFFFF);
+                            break;
+                        case 1:
+                            p_vci_ini_rw.wdata = r_dcache_wdata_save.read();
+                            break;
+                    }
+                }
+                p_vci_ini_rw.be     = 0xF;
+                p_vci_ini_rw.cmd    = vci_param::CMD_STORE_COND;
+                p_vci_ini_rw.plen   = 4*(r_vci_cmd_max.read()+1);
+                p_vci_ini_rw.trdid  = 0;   // data cache uncached read
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = m_srcid_rw;
+                p_vci_ini_rw.cons   = true;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = false;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop    = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_DATA_WRITE:
+                p_vci_ini_rw.cmdval  = true;
+                p_vci_ini_rw.address = r_wbuf.getAddress(r_vci_cmd_cpt)&~0x3;
+                p_vci_ini_rw.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
+                p_vci_ini_rw.be      = r_wbuf.getBe(r_vci_cmd_cpt);
+                p_vci_ini_rw.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
+                p_vci_ini_rw.cmd     = vci_param::CMD_WRITE;
+                p_vci_ini_rw.trdid   = 0;  // data cache write
+                p_vci_ini_rw.pktid   = 0;
+                p_vci_ini_rw.srcid   = m_srcid_rw;
+                p_vci_ini_rw.cons    = false;
+                p_vci_ini_rw.wrap    = false;
+                p_vci_ini_rw.contig  = true;
+                p_vci_ini_rw.clen    = 0;
+                p_vci_ini_rw.cfixed  = false;
+                p_vci_ini_rw.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_DATA_MISS:
+                p_vci_ini_rw.cmdval = true;
+                p_vci_ini_rw.address = r_dcache_addr_save.read() & (addr_40) m_dcache_yzmask;
+                p_vci_ini_rw.be     = 0xF;
+                p_vci_ini_rw.plen   = m_dcache_words << 2;
+                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
+                p_vci_ini_rw.trdid  = 1;   // data cache cached read
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = m_srcid_rw;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = true;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop = true;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_INS_MISS:
+                p_vci_ini_rw.cmdval = true;
+                p_vci_ini_rw.address = r_icache_addr_save.read() & (addr_40) m_icache_yzmask;
+                p_vci_ini_rw.be     = 0xF;
+                p_vci_ini_rw.plen   = m_icache_words << 2;
+                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
+                p_vci_ini_rw.trdid  = 3;   // ins cache cached read
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = m_srcid_rw;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = true;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop = true;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+                break;
+
+            case CMD_INS_UNC:
+                p_vci_ini_rw.cmdval = true;
+                p_vci_ini_rw.address = r_icache_addr_save.read() & ~0x3;
+                p_vci_ini_rw.be     = 0xF;
+                p_vci_ini_rw.plen   = 4;
+                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
+                p_vci_ini_rw.trdid  = 2;   // ins cache uncached read
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = m_srcid_rw;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = true;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop = true;
+
+                p_vci_ini_c.cmdval  = false;
+                p_vci_ini_c.address = 0;
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 0;
+                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_c.trdid  = 0;
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = 0;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = false;
+
+
+                break;
+
+            case CMD_INS_CLEANUP:
+                p_vci_ini_rw.cmdval = false;
+                p_vci_ini_rw.address = 0;
+                p_vci_ini_rw.wdata  = 0;
+                p_vci_ini_rw.be     = 0;
+                p_vci_ini_rw.plen   = 0;
+                p_vci_ini_rw.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_rw.trdid  = 0;
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = 0;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = false;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop    = false;
+
+                p_vci_ini_c.cmdval  = true;
+                p_vci_ini_c.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 4;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.trdid  = 1; // cleanup instruction
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = m_srcid_c;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = true;
+
+                break;
+
+
+            case CMD_DATA_CLEANUP:
+                p_vci_ini_rw.cmdval = false;
+                p_vci_ini_rw.address = 0;
+                p_vci_ini_rw.wdata  = 0;
+                p_vci_ini_rw.be     = 0;
+                p_vci_ini_rw.plen   = 0;
+                p_vci_ini_rw.cmd    = vci_param::CMD_NOP;
+                p_vci_ini_rw.trdid  = 0;
+                p_vci_ini_rw.pktid  = 0;
+                p_vci_ini_rw.srcid  = 0;
+                p_vci_ini_rw.cons   = false;
+                p_vci_ini_rw.wrap   = false;
+                p_vci_ini_rw.contig = false;
+                p_vci_ini_rw.clen   = 0;
+                p_vci_ini_rw.cfixed = false;
+                p_vci_ini_rw.eop    = false;
+
+                p_vci_ini_c.cmdval  = true;
+                p_vci_ini_c.address = r_dcache_cleanup_line.read() * (m_dcache_words<<2);
+                p_vci_ini_c.wdata  = 0;
+                p_vci_ini_c.be     = 0;
+                p_vci_ini_c.plen   = 4;
+                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
+                p_vci_ini_c.trdid  = 0; // cleanup data
+                p_vci_ini_c.pktid  = 0;
+                p_vci_ini_c.srcid  = m_srcid_c;
+                p_vci_ini_c.cons   = false;
+                p_vci_ini_c.wrap   = false;
+                p_vci_ini_c.contig = false;
+                p_vci_ini_c.clen   = 0;
+                p_vci_ini_c.cfixed = false;
+                p_vci_ini_c.eop = true;
+
+                break;
+
+        } // end switch r_vci_cmd_fsm
+
+        // VCI_TGT
+
+        switch ( r_vci_tgt_fsm.read() ) {
+
+            case TGT_IDLE:
+            case TGT_UPDT_WORD:
+            case TGT_UPDT_DATA:
+                p_vci_tgt.cmdack  = true;
+                p_vci_tgt.rspval  = false;
+                break;
+
+            case TGT_RSP_BROADCAST:
+                p_vci_tgt.cmdack  = false;
+                p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
+                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+                p_vci_tgt.rpktid  = r_tgt_pktid.read();
+                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+                p_vci_tgt.rdata   = 0;
+                p_vci_tgt.rerror  = 0;
+                p_vci_tgt.reop    = true;
+                break;
+
+            case TGT_RSP_ICACHE:
+                p_vci_tgt.cmdack  = false;
+                p_vci_tgt.rspval  = !r_tgt_icache_req.read() && r_tgt_icache_rsp.read();
+                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+                p_vci_tgt.rpktid  = r_tgt_pktid.read();
+                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+                p_vci_tgt.rdata   = 0;
+                p_vci_tgt.rerror  = 0;
+                p_vci_tgt.reop    = true;
+                break;
+
+            case TGT_RSP_DCACHE:
+                p_vci_tgt.cmdack  = false;
+                p_vci_tgt.rspval  = !r_tgt_dcache_req.read() && r_tgt_dcache_rsp.read();
+                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
+                p_vci_tgt.rpktid  = r_tgt_pktid.read();
+                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
+                p_vci_tgt.rdata   = 0;
+                p_vci_tgt.rerror  = 0;
+                p_vci_tgt.reop    = true;
+                break;
+
+            case TGT_REQ_BROADCAST:
+            case TGT_REQ_ICACHE:
+            case TGT_REQ_DCACHE:
+                p_vci_tgt.cmdack  = false;
+                p_vci_tgt.rspval  = false;
+                break;
+
+        } // end switch TGT_FSM
+    } // end genMoore()
+
+}} // end namespace
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
+
+
+
Index: trunk/modules/vci_dma_tsar/caba/metadata/vci_dma_tsar.sd
===================================================================
--- trunk/modules/vci_dma_tsar/caba/metadata/vci_dma_tsar.sd	(revision 2)
+++ trunk/modules/vci_dma_tsar/caba/metadata/vci_dma_tsar.sd	(revision 2)
@@ -0,0 +1,43 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_dma_tsar',
+	classname = 'soclib::caba::VciDmaTsar',
+	   tmpl_parameters = [
+	parameter.Module('vci_param',  default = 'caba:vci_param'),
+	],
+	header_files = ['../source/include/vci_dma_tsar.h',
+					],
+    interface_files = [
+					'../../include/soclib/dma_tsar.h',
+					],
+	implementation_files = ['../source/src/vci_dma_tsar.cpp',],
+			  ports = [
+	Port('caba:vci_target', 'p_vci_target'),
+	Port('caba:vci_initiator', 'p_vci_initiator'),
+	Port('caba:bit_out', 'p_irq'),
+	Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+	Port('caba:clock_in', 'p_clk', auto = 'clock'),
+	],
+	uses = [
+		Uses('caba:base_module'),
+		Uses('caba:vci_target_fsm', default_target = 'true', support_llsc = 'false'),
+		Uses('caba:vci_initiator_simple_read_req'),
+		Uses('caba:vci_initiator_simple_write_req'),
+		Uses('caba:vci_initiator_fsm'),
+		],
+	instance_parameters = [
+        parameter.Module('mt', typename = 'common:mapping_table', auto = 'env:mapping_table'),
+		parameter.IntTab('srcid'),
+		parameter.IntTab('tgtid'),
+        parameter.Int('burst_size'),
+	],
+	   extensions = [
+	'dsx:addressable=tgtid',
+	'dsx:max_segments=1',
+	'dsx:get_ident=srcid:p_vci_target,tgtid:p_vci_initiator',
+   ],
+)
Index: trunk/modules/vci_dma_tsar/caba/source/include/vci_dma_tsar.h
===================================================================
--- trunk/modules/vci_dma_tsar/caba/source/include/vci_dma_tsar.h	(revision 2)
+++ trunk/modules/vci_dma_tsar/caba/source/include/vci_dma_tsar.h	(revision 2)
@@ -0,0 +1,106 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *
+ * Maintainers: nipo
+ */
+#ifndef SOCLIB_VCI_DMA_TSAR_H
+#define SOCLIB_VCI_DMA_TSAR_H
+
+#include <stdint.h>
+#include <systemc>
+#include "vci_target_fsm.h"
+#include "vci_initiator_fsm.h"
+#include "caba_base_module.h"
+#include "mapping_table.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+template<typename vci_param>
+class VciDmaTsar
+	: public caba::BaseModule
+{
+private:
+    soclib::caba::VciTargetFsm<vci_param, true> m_vci_target_fsm;
+    soclib::caba::VciInitiatorFsm<vci_param> m_vci_init_fsm;
+    typedef typename soclib::caba::VciInitiatorReq<vci_param> req_t;
+
+    bool on_write(int seg, typename vci_param::addr_t addr, typename vci_param::data_t data, int be);
+    bool on_read(int seg, typename vci_param::addr_t addr, typename vci_param::data_t &data);
+    void read_done( req_t *req );
+    void write_finish( req_t *req );
+    void transition();
+    void genMoore();
+
+	uint32_t m_src;
+	uint32_t m_dst;
+	uint32_t m_len;
+	uint32_t m_offset;
+    uint32_t m_offset_buffer;
+    bool m_partial;
+    bool m_must_finish;
+	bool m_irq_enabled;
+	bool r_irq;
+
+	std::vector<uint8_t> m_data;
+
+	bool m_handling;
+
+	void next_req();
+	void ended();
+
+protected:
+    SC_HAS_PROCESS(VciDmaTsar);
+
+public:
+    sc_in<bool> p_clk;
+    sc_in<bool> p_resetn;
+    soclib::caba::VciTarget<vci_param> p_vci_target;
+    soclib::caba::VciInitiator<vci_param> p_vci_initiator;
+    sc_out<bool> p_irq;
+
+	VciDmaTsar(
+		sc_module_name name,
+		const soclib::common::MappingTable &mt,
+		const soclib::common::IntTab &srcid,
+		const soclib::common::IntTab &tgtid,
+		const size_t burst_size );
+};
+
+}}
+
+#endif /* SOCLIB_VCI_DMA_TSAR_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_dma_tsar/caba/source/src/vci_dma_tsar.cpp
===================================================================
--- trunk/modules/vci_dma_tsar/caba/source/src/vci_dma_tsar.cpp	(revision 2)
+++ trunk/modules/vci_dma_tsar/caba/source/src/vci_dma_tsar.cpp	(revision 2)
@@ -0,0 +1,267 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ */
+
+#include <stdint.h>
+#include "register.h"
+#include "../include/vci_dma_tsar.h"
+#include "dma_tsar.h"
+
+namespace soclib { namespace caba {
+
+#define tmpl(t) template<typename vci_param> t VciDmaTsar<vci_param>
+
+tmpl(bool)::on_write(int seg, typename vci_param::addr_t addr, typename vci_param::data_t data, int be)
+{
+    int cell = (int)addr / vci_param::B;
+
+	switch ((enum SoclibDmaRegisters)cell) {
+	case DMA_SRC:
+		m_src = data;
+		return true;
+    case DMA_DST:
+		m_dst = data;
+		return true;
+    case DMA_LEN:
+		m_len = data;
+		return true;
+    case DMA_RESET:
+        m_must_finish = true;
+        m_irq_enabled = false;
+		r_irq = false;
+        return true;
+    case DMA_IRQ_DISABLED:
+		m_irq_enabled = !data;
+		return true;
+	};
+	return false;
+}
+
+tmpl(void)::ended()
+{
+	if ( m_irq_enabled )
+		r_irq = true;
+	m_len = 0;
+    m_must_finish = false;
+	m_handling = false;
+}
+
+tmpl(bool)::on_read(int seg, typename vci_param::addr_t addr, typename vci_param::data_t &data)
+{
+    int cell = (int)addr / vci_param::B;
+
+	switch ((enum SoclibDmaRegisters)cell) {
+	case DMA_SRC:
+		data = m_src;
+		return true;
+    case DMA_DST:
+		data = m_dst;
+		return true;
+	case DMA_LEN:
+		data = m_len;
+		return true;
+    default:
+        return false;
+	}
+	return false;
+}
+
+tmpl(void)::read_done( req_t *req )
+{
+	if ( !req->failed() && !m_must_finish ) {
+		ssize_t remaining = (ssize_t)m_len-(size_t)m_offset;
+		ssize_t burst = m_offset_buffer;
+
+        if ( ( ( 0 < ( remaining-(size_t)m_offset_buffer ) ) 
+            && ( ( remaining-(size_t)m_offset_buffer ) < m_data.size()) ) && m_partial ){
+            VciInitSimpleReadReq<vci_param> *new_req =
+                new VciInitSimpleReadReq<vci_param>(
+                        &m_data[m_offset_buffer], m_src+m_offset+m_offset_buffer, 4 );
+            m_offset_buffer+=4;
+            new_req->setDone( this, ON_T(read_done) );
+            m_vci_init_fsm.doReq( new_req );
+            delete req;
+            return;
+        }
+        if ( (( m_src+m_offset+m_offset_buffer ) & ( m_data.size()-1 )) && m_partial ){
+            VciInitSimpleReadReq<vci_param> *new_req =
+                new VciInitSimpleReadReq<vci_param>(
+                        &m_data[m_offset_buffer], m_src+m_offset+m_offset_buffer, 4 );
+            m_offset_buffer+=4;
+            new_req->setDone( this, ON_T(read_done) );
+            m_vci_init_fsm.doReq( new_req );
+            delete req;
+            return;
+        }
+        m_partial = false;
+        if( (( m_dst+m_offset ) & ~( m_data.size()-1 )) !=
+            (( m_dst+m_offset+m_offset_buffer-4 ) & ~( m_data.size()-1 )) ){
+            burst = (((m_dst+m_offset) & ~( m_data.size()-1))+m_data.size()) - (m_dst+m_offset);
+            m_partial = true;
+        }
+		VciInitSimpleWriteReq<vci_param> *new_req =
+			new VciInitSimpleWriteReq<vci_param>( m_dst+m_offset, &m_data[0], burst );
+		new_req->setDone( this, ON_T(write_finish) );
+		m_vci_init_fsm.doReq( new_req );
+	} else {
+		ended();
+	}
+	delete req;
+}
+
+tmpl(void)::write_finish( req_t *req )
+{
+    ssize_t burst = 0;
+    uint32_t offset = 0;
+    if( m_partial ){
+        burst = m_dst + m_offset + m_offset_buffer - ((m_dst+m_offset+m_offset_buffer) & ~( m_data.size()-1));
+        offset = m_offset_buffer - burst;
+    } else {
+	    m_offset += m_offset_buffer;
+    }
+	if ( !req->failed() && !m_must_finish ){
+        if(m_partial){
+            VciInitSimpleWriteReq<vci_param> *new_req =
+                new VciInitSimpleWriteReq<vci_param>( m_dst+m_offset+offset, &m_data[offset], burst );
+            new_req->setDone( this, ON_T(write_finish) );
+            m_partial = false;
+            m_vci_init_fsm.doReq( new_req );
+            delete req;
+            return;
+        }
+		next_req();
+    }
+	else {
+		ended();
+	}
+	delete req;
+}
+
+tmpl(void)::next_req()
+{
+	ssize_t remaining = (ssize_t)m_len-(size_t)m_offset;
+	if ( remaining <= 0 ) {
+		ended();
+		return;
+	}
+
+	ssize_t burst = m_data.size();
+    m_partial = false;
+	if ( remaining < burst ){
+		burst = 4;
+        m_partial = true;
+    }
+    if ( ( m_src+m_offset ) & ( m_data.size()-1 ) ){
+        burst = 4;
+        m_partial = true;
+    }
+
+    m_offset_buffer = burst;
+	VciInitSimpleReadReq<vci_param> *req =
+		new VciInitSimpleReadReq<vci_param>(
+			&m_data[0], m_src+m_offset, burst );
+	req->setDone( this, ON_T(read_done) );
+	m_vci_init_fsm.doReq( req );
+}
+
+tmpl(void)::transition()
+{
+	if (!p_resetn) {
+		m_vci_target_fsm.reset();
+		m_vci_init_fsm.reset();
+		r_irq = false;
+		m_irq_enabled = false;
+		m_len = 0;
+        m_offset_buffer = 0;
+		m_handling = false;
+        m_must_finish = false;
+		return;
+	}
+
+
+	if ( m_len && !m_handling ) {
+		m_handling = true;
+		m_offset = 0;
+
+		next_req();
+	}
+    
+    if( !m_handling )
+        m_must_finish = false;
+
+	m_vci_target_fsm.transition();
+	m_vci_init_fsm.transition();
+}
+
+tmpl(void)::genMoore()
+{
+	m_vci_target_fsm.genMoore();
+	m_vci_init_fsm.genMoore();
+
+	p_irq = r_irq && m_irq_enabled;
+}
+
+tmpl(/**/)::VciDmaTsar(
+    sc_module_name name,
+    const MappingTable &mt,
+    const IntTab &srcid,
+    const IntTab &tgtid,
+	const size_t burst_size )
+	: caba::BaseModule(name),
+	  m_vci_target_fsm(p_vci_target, mt.getSegmentList(tgtid)),
+	  m_vci_init_fsm(p_vci_initiator, mt.indexForId(srcid)),
+	  m_len(0),
+	  m_data(burst_size, (uint8_t)0),
+      p_clk("clk"),
+      p_resetn("resetn"),
+      p_vci_target("vci_target"),
+      p_vci_initiator("vci_initiator"),
+      p_irq("irq")
+{
+	m_vci_target_fsm.on_read_write(on_read, on_write);
+    
+    assert(burst_size && "Useless DMA with no buffer");
+    assert(burst_size < (1<<vci_param::K) && "I will be unable to create requests that big");
+
+	SC_METHOD(transition);
+	dont_initialize();
+	sensitive << p_clk.pos();
+
+	SC_METHOD(genMoore);
+	dont_initialize();
+	sensitive << p_clk.neg();
+}
+
+}}
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_dma_tsar/include/soclib/dma_tsar.h
===================================================================
--- trunk/modules/vci_dma_tsar/include/soclib/dma_tsar.h	(revision 2)
+++ trunk/modules/vci_dma_tsar/include/soclib/dma_tsar.h	(revision 2)
@@ -0,0 +1,49 @@
+/*
+ * 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *         Eric Guthmuller  <eric.guthmuller@polytechnique.edu>, 2009
+ *
+ * Maintainers: nipo eric.guthmuller@polytechnique.edu
+ */
+#ifndef DMA_REGS_TSAR_H
+#define DMA_REGS_TSAR_H
+
+enum SoclibDmaRegisters {
+    DMA_SRC,
+    DMA_DST,
+    DMA_LEN,
+    DMA_RESET,
+    DMA_IRQ_DISABLED,
+};
+
+#endif /* DMA_REGS_TSAR_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_dma_tsar_v2/caba/metadata/vci_dma_tsar_v2.sd
===================================================================
--- trunk/modules/vci_dma_tsar_v2/caba/metadata/vci_dma_tsar_v2.sd	(revision 2)
+++ trunk/modules/vci_dma_tsar_v2/caba/metadata/vci_dma_tsar_v2.sd	(revision 2)
@@ -0,0 +1,43 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_dma_tsar_v2',
+	classname = 'soclib::caba::VciDmaTsarV2',
+	   tmpl_parameters = [
+	parameter.Module('vci_param',  default = 'caba:vci_param'),
+	],
+	header_files = ['../source/include/vci_dma_tsar_v2.h',
+					],
+    interface_files = [
+					'../../include/soclib/dma_tsar_v2.h',
+					],
+	implementation_files = ['../source/src/vci_dma_tsar_v2.cpp',],
+			  ports = [
+	Port('caba:vci_target', 'p_vci_target'),
+	Port('caba:vci_initiator', 'p_vci_initiator'),
+	Port('caba:bit_out', 'p_irq'),
+	Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+	Port('caba:clock_in', 'p_clk', auto = 'clock'),
+	],
+	uses = [
+		Uses('caba:base_module'),
+		Uses('caba:vci_target_fsm', default_target = 'true', support_llsc = 'false'),
+		Uses('caba:vci_initiator_simple_read_req'),
+		Uses('caba:vci_initiator_simple_write_req'),
+		Uses('caba:vci_initiator_fsm'),
+		],
+	instance_parameters = [
+        parameter.Module('mt', typename = 'common:mapping_table', auto = 'env:mapping_table'),
+		parameter.IntTab('srcid'),
+		parameter.IntTab('tgtid'),
+        parameter.Int('burst_size'),
+	],
+	   extensions = [
+	'dsx:addressable=tgtid',
+	'dsx:max_segments=1',
+	'dsx:get_ident=srcid:p_vci_target,tgtid:p_vci_initiator',
+   ],
+)
Index: trunk/modules/vci_dma_tsar_v2/caba/source/include/vci_dma_tsar_v2.h
===================================================================
--- trunk/modules/vci_dma_tsar_v2/caba/source/include/vci_dma_tsar_v2.h	(revision 2)
+++ trunk/modules/vci_dma_tsar_v2/caba/source/include/vci_dma_tsar_v2.h	(revision 2)
@@ -0,0 +1,106 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *
+ * Maintainers: nipo
+ */
+#ifndef SOCLIB_VCI_DMA_TSAR_V2_H
+#define SOCLIB_VCI_DMA_TSAR_V2_H
+
+#include <stdint.h>
+#include <systemc>
+#include "vci_target_fsm.h"
+#include "vci_initiator_fsm.h"
+#include "caba_base_module.h"
+#include "mapping_table.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+template<typename vci_param>
+class VciDmaTsarV2
+	: public caba::BaseModule
+{
+private:
+    soclib::caba::VciTargetFsm<vci_param, true> m_vci_target_fsm;
+    soclib::caba::VciInitiatorFsm<vci_param> m_vci_init_fsm;
+    typedef typename soclib::caba::VciInitiatorReq<vci_param> req_t;
+
+    bool on_write(int seg, typename vci_param::addr_t addr, typename vci_param::data_t data, int be);
+    bool on_read(int seg, typename vci_param::addr_t addr, typename vci_param::data_t &data);
+    void read_done( req_t *req );
+    void write_finish( req_t *req );
+    void transition();
+    void genMoore();
+
+	uint32_t m_src;
+	uint32_t m_dst;
+	uint32_t m_len;
+	uint32_t m_offset;
+    uint32_t m_offset_buffer;
+    bool m_partial;
+    bool m_must_finish;
+	bool m_irq_enabled;
+	bool r_irq;
+
+	std::vector<uint8_t> m_data;
+
+	bool m_handling;
+
+	void next_req();
+	void ended();
+
+protected:
+    SC_HAS_PROCESS(VciDmaTsarV2);
+
+public:
+    sc_in<bool> p_clk;
+    sc_in<bool> p_resetn;
+    soclib::caba::VciTarget<vci_param> p_vci_target;
+    soclib::caba::VciInitiator<vci_param> p_vci_initiator;
+    sc_out<bool> p_irq;
+
+	VciDmaTsarV2(
+		sc_module_name name,
+		const soclib::common::MappingTable &mt,
+		const soclib::common::IntTab &srcid,
+		const soclib::common::IntTab &tgtid,
+		const size_t burst_size );
+};
+
+}}
+
+#endif /* SOCLIB_VCI_DMA_TSAR_V2_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_dma_tsar_v2/caba/source/src/vci_dma_tsar_v2.cpp
===================================================================
--- trunk/modules/vci_dma_tsar_v2/caba/source/src/vci_dma_tsar_v2.cpp	(revision 2)
+++ trunk/modules/vci_dma_tsar_v2/caba/source/src/vci_dma_tsar_v2.cpp	(revision 2)
@@ -0,0 +1,246 @@
+/* -*- 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ */
+
+#include <stdint.h>
+#include "register.h"
+#include "../include/vci_dma_tsar_v2.h"
+#include "dma_tsar_v2.h"
+
+namespace soclib { namespace caba {
+
+#define tmpl(t) template<typename vci_param> t VciDmaTsarV2<vci_param>
+
+tmpl(bool)::on_write(int seg, typename vci_param::addr_t addr, typename vci_param::data_t data, int be)
+{
+    int cell = (int)addr / vci_param::B;
+
+	switch ((enum SoclibDmaRegisters)cell) {
+	case DMA_SRC:
+		m_src = data;
+		return true;
+    case DMA_DST:
+		m_dst = data;
+		return true;
+    case DMA_LEN:
+		m_len = data;
+		return true;
+    case DMA_RESET:
+        m_must_finish = true;
+        m_irq_enabled = false;
+		r_irq = false;
+        return true;
+    case DMA_IRQ_DISABLED:
+		m_irq_enabled = !data;
+		return true;
+	};
+	return false;
+}
+
+tmpl(void)::ended()
+{
+	if ( m_irq_enabled )
+		r_irq = true;
+	m_len = 0;
+    m_must_finish = false;
+	m_handling = false;
+}
+
+tmpl(bool)::on_read(int seg, typename vci_param::addr_t addr, typename vci_param::data_t &data)
+{
+    int cell = (int)addr / vci_param::B;
+
+	switch ((enum SoclibDmaRegisters)cell) {
+	case DMA_SRC:
+		data = m_src;
+		return true;
+    case DMA_DST:
+		data = m_dst;
+		return true;
+	case DMA_LEN:
+		data = m_len;
+		return true;
+    default:
+        return false;
+	}
+	return false;
+}
+
+tmpl(void)::read_done( req_t *req )
+{
+	if ( !req->failed() && !m_must_finish ) {
+		ssize_t burst = m_offset_buffer;
+
+        m_partial = false;
+        if( (( m_dst+m_offset ) & ~( m_data.size()-1 )) !=
+            (( m_dst+m_offset+m_offset_buffer-1 ) & ~( m_data.size()-1 )) ){
+            burst = (((m_dst+m_offset) & ~( m_data.size()-1))+m_data.size()) - (m_dst+m_offset);
+            m_partial = true;
+        }
+		VciInitSimpleWriteReq<vci_param> *new_req =
+			new VciInitSimpleWriteReq<vci_param>( m_dst+m_offset, &m_data[0], burst );
+		new_req->setDone( this, ON_T(write_finish) );
+		m_vci_init_fsm.doReq( new_req );
+	} else {
+		ended();
+	}
+	delete req;
+}
+
+tmpl(void)::write_finish( req_t *req )
+{
+    ssize_t burst = 0;
+    uint32_t offset = 0;
+    if( m_partial ){
+        burst = m_dst + m_offset + m_offset_buffer - ((m_dst+m_offset+m_offset_buffer) & ~( m_data.size()-1));
+        offset = m_offset_buffer - burst ;
+    } else {
+	    m_offset += m_offset_buffer;
+    }
+	if ( !req->failed() && !m_must_finish ){
+        if(m_partial){
+            VciInitSimpleWriteReq<vci_param> *new_req =
+                new VciInitSimpleWriteReq<vci_param>( m_dst+m_offset+offset, &m_data[offset], burst );
+            new_req->setDone( this, ON_T(write_finish) );
+            m_partial = false;
+            m_vci_init_fsm.doReq( new_req );
+            delete req;
+            return;
+        }
+		next_req();
+    }
+	else {
+		ended();
+	}
+	delete req;
+}
+
+tmpl(void)::next_req()
+{
+	ssize_t remaining = (ssize_t)m_len-(size_t)m_offset;
+	if ( remaining <= 0 ) {
+		ended();
+		return;
+	}
+
+	ssize_t burst = m_data.size();
+    m_partial = false;
+    if ( ( m_src+m_offset ) & ( m_data.size()-1 ) ){
+        burst = m_data.size() - ( (m_src+m_offset) & (m_data.size()-1) );
+        m_partial = true;
+    }
+	if ( remaining < burst ){
+		burst = remaining;
+        m_partial = true;
+    }
+
+    m_offset_buffer = burst;
+
+	VciInitSimpleReadReq<vci_param> *req =
+		new VciInitSimpleReadReq<vci_param>(
+			&m_data[0], (m_src+m_offset), burst );
+	req->setDone( this, ON_T(read_done) );
+	m_vci_init_fsm.doReq( req );
+}
+
+tmpl(void)::transition()
+{
+	if (!p_resetn) {
+		m_vci_target_fsm.reset();
+		m_vci_init_fsm.reset();
+		r_irq = false;
+		m_irq_enabled = false;
+		m_len = 0;
+        m_offset_buffer = 0;
+		m_handling = false;
+        m_must_finish = false;
+		return;
+	}
+
+
+	if ( m_len && !m_handling ) {
+		m_handling = true;
+		m_offset = 0;
+
+		next_req();
+	}
+    
+    if( !m_handling )
+        m_must_finish = false;
+
+	m_vci_target_fsm.transition();
+	m_vci_init_fsm.transition();
+}
+
+tmpl(void)::genMoore()
+{
+	m_vci_target_fsm.genMoore();
+	m_vci_init_fsm.genMoore();
+
+	p_irq = r_irq && m_irq_enabled;
+}
+
+tmpl(/**/)::VciDmaTsarV2(
+    sc_module_name name,
+    const MappingTable &mt,
+    const IntTab &srcid,
+    const IntTab &tgtid,
+	const size_t burst_size )
+	: caba::BaseModule(name),
+	  m_vci_target_fsm(p_vci_target, mt.getSegmentList(tgtid)),
+	  m_vci_init_fsm(p_vci_initiator, mt.indexForId(srcid)),
+	  m_len(0),
+	  m_data(burst_size, (uint8_t)0),
+      p_clk("clk"),
+      p_resetn("resetn"),
+      p_vci_target("vci_target"),
+      p_vci_initiator("vci_initiator"),
+      p_irq("irq")
+{
+	m_vci_target_fsm.on_read_write(on_read, on_write);
+    
+    assert(burst_size && "Useless DMA with no buffer");
+    assert(burst_size < (1<<vci_param::K) && "I will be unable to create requests that big");
+
+	SC_METHOD(transition);
+	dont_initialize();
+	sensitive << p_clk.pos();
+
+	SC_METHOD(genMoore);
+	dont_initialize();
+	sensitive << p_clk.neg();
+}
+
+}}
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_dma_tsar_v2/include/soclib/dma_tsar_v2.h
===================================================================
--- trunk/modules/vci_dma_tsar_v2/include/soclib/dma_tsar_v2.h	(revision 2)
+++ trunk/modules/vci_dma_tsar_v2/include/soclib/dma_tsar_v2.h	(revision 2)
@@ -0,0 +1,49 @@
+/*
+ * 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
+ *
+ * Copyright (c) UPMC, Lip6, Asim
+ *         Nicolas Pouillon <nipo@ssji.net>, 2007
+ *         Eric Guthmuller  <eric.guthmuller@polytechnique.edu>, 2009
+ *
+ * Maintainers: nipo eric.guthmuller@polytechnique.edu
+ */
+#ifndef DMA_REGS_TSAR_V2_H
+#define DMA_REGS_TSAR_V2_H
+
+enum SoclibDmaRegisters {
+    DMA_SRC,
+    DMA_DST,
+    DMA_LEN,
+    DMA_RESET,
+    DMA_IRQ_DISABLED,
+};
+
+#endif /* DMA_REGS_TSAR_V2_H */
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache/caba/metadata/vci_mem_cache.sd
===================================================================
--- trunk/modules/vci_mem_cache/caba/metadata/vci_mem_cache.sd	(revision 2)
+++ trunk/modules/vci_mem_cache/caba/metadata/vci_mem_cache.sd	(revision 2)
@@ -0,0 +1,26 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_mem_cache',
+       classname = 'soclib::caba::VciMemCache',
+       tmpl_parameters = [parameter.Module('vci_param', default = 'caba:vci_param'),],
+       header_files = ['../source/include/vci_mem_cache.h',
+                       '../source/include/xram_transaction.h',
+                       '../source/include/mem_cache_directory.h',
+                       '../source/include/atomic_tab.h',
+                       '../source/include/update_tab.h',],
+       implementation_files = ['../source/src/vci_mem_cache.cpp',],
+       uses = [Uses('caba:base_module'),
+               Uses('common:loader'),
+               Uses('common:mapping_table'),
+               Uses('caba:generic_fifo'),
+               ],
+       ports = [Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:vci_initiator','p_vci_init'),
+                Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+                Port('caba:clock_in', 'p_clk', auto = 'clock'),],
+       extensions = ['dsx:get_ident=ident:p_vci',],
+)
Index: trunk/modules/vci_mem_cache/caba/source/include/atomic_tab.h
===================================================================
--- trunk/modules/vci_mem_cache/caba/source/include/atomic_tab.h	(revision 2)
+++ trunk/modules/vci_mem_cache/caba/source/include/atomic_tab.h	(revision 2)
@@ -0,0 +1,112 @@
+#ifndef ATOMIC_TAB_H_
+#define ATOMIC_TAB_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+/*                  The atomic access tab                             */
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+class AtomicTab{
+    typedef uint32_t size_t;
+    typedef uint32_t addr_t;
+
+private:
+    size_t size_tab;                            // The size of the tab
+    std::vector<addr_t> addr_tab;               // Address entries
+    std::vector<bool>   valid_tab;              // Valid entries
+
+public:
+
+    AtomicTab()
+	: addr_tab(0),
+	  valid_tab(0)
+	{
+	size_tab=0;
+    }
+
+    AtomicTab(size_t size_tab_i)
+	: addr_tab(size_tab_i),
+	  valid_tab(size_tab_i)
+	{
+	size_tab=size_tab_i;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The size() function returns the size of the tab */
+    /////////////////////////////////////////////////////////////////////
+    const size_t size(){
+	return size_tab;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The init() function initializes the transaction tab entries */
+    /////////////////////////////////////////////////////////////////////
+    void init(){
+    	for ( size_t i=0; i<size_tab; i++) {
+		addr_tab[i]=0;
+		valid_tab[i]=false;
+    	}
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The set() function sets an entry 
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void set(const size_t id, const addr_t addr){
+	assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	addr_tab[id]=addr;
+	valid_tab[id]=true;
+	return;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The isatomic() function tests if the SC request corresponds to an entry
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+
+       This function return true if the request corresponds
+     */
+    /////////////////////////////////////////////////////////////////////
+    bool isatomic(const size_t id, const addr_t addr){
+	assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	bool test=valid_tab[id];
+	test=test && (addr == addr_tab[id]);
+	return test;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The reset() function resets all the entries for this lock
+       Arguments :
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void reset(const addr_t addr){
+	for(size_t i=0 ; i<size_tab ; i++){
+		if(addr == addr_tab[i]){
+			valid_tab[i]=false;
+		}
+	}
+	return;
+    }
+
+};
+ 
+#endif
+
Index: trunk/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h
===================================================================
--- trunk/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h	(revision 2)
+++ trunk/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h	(revision 2)
@@ -0,0 +1,288 @@
+#ifndef SOCLIB_CABA_MEM_CACHE_DIRECTORY_H
+#define SOCLIB_CABA_MEM_CACHE_DIRECTORY_H 
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+namespace soclib { namespace caba {
+
+  using namespace sc_core;
+
+////////////////////////////////////////////////////////////////////////
+//                    A LRU entry 
+////////////////////////////////////////////////////////////////////////
+class LruEntry {
+
+public:
+
+    bool recent;            
+
+    void init()
+    {
+	recent=false;
+    }
+
+}; // end class LruEntry
+
+////////////////////////////////////////////////////////////////////////
+//                    A directory entry                               
+////////////////////////////////////////////////////////////////////////
+class DirectoryEntry {
+
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+    typedef uint32_t copy_t;
+
+public:
+
+    bool	 	valid;                  // entry valid
+    bool	 	dirty;                  // entry dirty
+    bool	 	lock;                   // entry locked
+    tag_t	 	tag;                    // tag of the entry
+    copy_t 		copies;              	// vector of copies 
+
+    DirectoryEntry()
+    {
+	valid   = false;
+	dirty   = false;
+	lock    = false;
+	tag     = 0;
+	copies	= 0;
+    }
+    
+    DirectoryEntry(const DirectoryEntry &source)
+    {
+	valid	= source.valid;
+	dirty	= source.dirty;
+	tag	= source.tag;
+	lock	= source.lock;
+	copies	= source.copies;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    // The init() function initializes the entry 
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+	valid = false;
+	dirty = false;
+	lock  = false;
+    }
+    
+    /////////////////////////////////////////////////////////////////////
+    // The copy() function copies an existing source entry to a target 
+    /////////////////////////////////////////////////////////////////////
+    void copy(const DirectoryEntry &source)
+    {
+	valid	= source.valid;
+	dirty	= source.dirty;
+	tag	= source.tag;
+	lock	= source.lock;
+	copies	= source.copies;
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // The print() function prints the entry 
+    ////////////////////////////////////////////////////////////////////
+    void print()
+    {
+	std::cout << "Valid = " << valid << " ; Dirty = " << dirty << " ; Lock = " 
+  	   << lock << " ; Tag = " << std::hex << tag << " ; copies = " << copies << std::endl;
+    }
+
+}; // end class DirectoryEntry
+
+////////////////////////////////////////////////////////////////////////
+//                       The directory  
+////////////////////////////////////////////////////////////////////////
+class CacheDirectory {
+
+    typedef uint32_t addr_t;
+    typedef uint32_t data_t;
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+
+ private:
+
+// Directory constants
+    size_t					m_ways;
+    size_t					m_sets;
+    size_t					m_words;
+    size_t					m_width;
+
+// the directory & lru tables
+    DirectoryEntry 				**m_dir_tab;
+    LruEntry	 				**m_lru_tab;
+
+ public:
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+    CacheDirectory( size_t ways, size_t sets, size_t words, size_t address_width)	 
+    {
+	m_ways 	= ways; 
+	m_sets 	= sets;
+	m_words = words;
+        m_width = address_width;
+
+        m_dir_tab = new DirectoryEntry*[sets];
+        for ( size_t i=0; i<sets; i++ ) {
+            m_dir_tab[i] = new DirectoryEntry[ways];
+            for ( size_t j=0 ; j<ways ; j++) m_dir_tab[i][j].init();
+        }
+        m_lru_tab = new LruEntry*[sets];
+        for ( size_t i=0; i<sets; i++ ) {
+	    m_lru_tab[i] = new LruEntry[ways];
+            for ( size_t j=0 ; j<ways ; j++) m_lru_tab[i][j].init();
+        }
+    } // end constructor
+
+    /////////////////
+    // Destructor
+    /////////////////
+    ~CacheDirectory()
+    {
+        for(size_t i=0 ; i<m_sets ; i++){
+	    delete [] m_dir_tab[i];
+    	    delete [] m_lru_tab[i];
+        }
+        delete [] m_dir_tab;
+        delete [] m_lru_tab;
+    } // end destructor
+
+    /////////////////////////////////////////////////////////////////////
+    // The read() function reads a directory entry. In case of hit, the
+    // LRU is updated.
+    // Arguments :
+    // - address : the address of the entry 
+    // - way : (return argument) the way of the entry in case of hit
+    // The function returns a copy of a (valid or invalid) entry  
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry read(const addr_t &address,size_t &way)
+    {
+
+      #define L2 soclib::common::uint32_log2
+      const size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
+      const tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
+      #undef L2
+
+      bool hit       = false;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        bool equal = ( m_dir_tab[set][i].tag == tag );
+        bool valid = m_dir_tab[set][i].valid;
+        hit = equal && valid;
+        if ( hit ) {			
+          way = i;
+          break;
+        } 
+      }
+      if ( hit ) {
+        m_lru_tab[set][way].recent = true;
+        return DirectoryEntry(m_dir_tab[set][way]);
+      } else {
+        return DirectoryEntry();
+      }
+    } // end read()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write function writes a new entry, 
+    // and updates the LRU bits if necessary.
+    // Arguments :
+    // - set : the set of the entry
+    // - way : the way of the entry
+    // - entry : the entry value
+    /////////////////////////////////////////////////////////////////////
+    void write(const size_t &set, const size_t &way, const DirectoryEntry &entry)
+    {
+      assert( (set<m_sets) 
+		&& "Cache Directory write : The set index is invalid");
+      assert( (way<m_ways) 
+		&& "Cache Directory write : The way index is invalid");
+
+      // update Directory
+      m_dir_tab[set][way].copy(entry);
+
+      // update LRU bits
+      bool all_recent = true;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
+      }
+      if ( all_recent ) {
+        for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
+      } else {
+        m_lru_tab[set][way].recent = true;
+      }
+    } // end write()
+
+    /////////////////////////////////////////////////////////////////////
+    // The print() function prints a selected directory entry
+    // Arguments :
+    // - set : the set of the entry to print
+    // - way : the way of the entry to print
+    /////////////////////////////////////////////////////////////////////
+    void print(const size_t &set, const size_t &way)
+    {
+	std::cout << std::dec << " set : " << set << " ; way : " << way << " ; " ;
+	m_dir_tab[set][way].print();
+    } // end print()
+    
+    /////////////////////////////////////////////////////////////////////
+    // The select() function selects a directory entry to evince.
+    // Arguments :
+    // - set   : (input argument) the set to modify
+    // - way   : (return argument) the way to evince
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry select(const size_t &set, size_t &way)
+    {
+	assert( (set < m_sets) 
+		&& "Cache Directory : (select) The set index is invalid");
+
+	for(size_t i=0; i<m_ways; i++){
+		if(!(m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+			way=i;
+			return DirectoryEntry(m_dir_tab[set][way]);
+		}
+	}
+	for(size_t i=0; i<m_ways; i++){
+		if( !(m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
+			way=i;
+			return DirectoryEntry(m_dir_tab[set][way]);
+		}
+	}
+	for(size_t i=0; i<m_ways; i++){
+		if( (m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+			way=i;
+			return DirectoryEntry(m_dir_tab[set][way]);
+		}
+	}
+	for(size_t i=0; i<m_ways; i++){
+		if( (m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
+			way=i;
+			return DirectoryEntry(m_dir_tab[set][way]);
+		}
+	}
+	way = 0;
+	return DirectoryEntry(m_dir_tab[set][0]);
+    } // end select()
+
+    /////////////////////////////////////////////////////////////////////
+    // 		Global initialisation function
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+        for ( size_t set=0 ; set<m_sets ; set++ ) {
+            for ( size_t way=0 ; way<m_ways ; way++ ) {
+                m_dir_tab[set][way].init();
+                m_lru_tab[set][way].init();
+            }
+        }
+    } // end init()
+ 
+}; // end class CacheDirectory
+ 
+}} // end namespaces
+
+#endif
Index: trunk/modules/vci_mem_cache/caba/source/include/update_tab.h
===================================================================
--- trunk/modules/vci_mem_cache/caba/source/include/update_tab.h	(revision 2)
+++ trunk/modules/vci_mem_cache/caba/source/include/update_tab.h	(revision 2)
@@ -0,0 +1,264 @@
+#ifndef UPDATE_TAB_H_
+#define UPDATE_TAB_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+////////////////////////////////////////////////////////////////////////
+//                  An update tab entry    
+////////////////////////////////////////////////////////////////////////
+class UpdateTabEntry {
+  typedef uint32_t size_t;
+
+ public:
+  bool 	valid;                // It is a valid pending transaction
+  bool	update;               // It is an update transaction 
+  size_t 	srcid;                // The srcid of the initiator which wrote the data
+  size_t 	trdid;                // The trdid of the initiator which wrote the data
+  size_t 	pktid;                // The pktid of the initiator which wrote the data
+  size_t 	count;                // The number of acknowledge responses to receive
+
+  UpdateTabEntry(){
+    valid	= false;
+    update	= false;
+    srcid	= 0;
+    trdid	= 0;
+    pktid	= 0;
+    count	= 0;
+  }
+
+  UpdateTabEntry(bool   i_valid, 
+		 bool   i_update, 
+		 size_t i_srcid, 
+		 size_t i_trdid, 
+		 size_t i_pktid, 
+		 size_t i_count) 
+    {
+      valid		= i_valid;
+      update		= i_update;
+      srcid		= i_srcid;
+      trdid		= i_trdid;
+      pktid		= i_pktid;
+      count		= i_count;
+    }
+
+  UpdateTabEntry(const UpdateTabEntry &source)
+    {
+      valid		= source.valid;
+      update 		= source.update;
+      srcid		= source.srcid;
+      trdid		= source.trdid;
+      pktid		= source.pktid;
+      count  		= source.count;
+    }
+
+  ////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  ///////////////////////////////////////////////////
+  void init()
+  {
+    valid=false;
+    update=false;
+    srcid=0;
+    trdid=0;
+    pktid=0;
+    count=0;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the update tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const UpdateTabEntry &source)
+  {
+    valid=source.valid;
+    update=source.update;
+    srcid=source.srcid;
+    trdid=source.trdid;
+    pktid=source.pktid;
+    count=source.count;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << "valid = " << valid << std::endl;
+    std::cout << "update = " << update << std::endl;
+    std::cout << "srcid = " << srcid << std::endl; 
+    std::cout << "trdid = " << trdid << std::endl; 
+    std::cout << "pktid = " << pktid << std::endl; 
+    std::cout << "count = " << count << std::endl;
+  }
+};
+
+////////////////////////////////////////////////////////////////////////
+//                        The update tab             
+////////////////////////////////////////////////////////////////////////
+class UpdateTab{
+
+  typedef uint32_t size_t;
+
+ private:
+  size_t size_tab;
+  std::vector<UpdateTabEntry> tab;
+
+ public:
+
+ UpdateTab()
+   : tab(0)
+    {
+      size_tab=0;
+    }
+
+ UpdateTab(size_t size_tab_i)
+   : tab(size_tab_i)
+  {
+    size_tab=size_tab_i;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  const size_t size(){
+    return size_tab;
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the tab 
+  /////////////////////////////////////////////////////////////////////
+  void init(){
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The reads() function reads an entry 
+  // Arguments :
+  // - entry : the entry to read
+  // This function returns a copy of the entry.
+  /////////////////////////////////////////////////////////////////////
+  UpdateTabEntry read (size_t entry)
+  {
+    assert(entry<size_tab && "Bad Update Tab Entry");
+    return UpdateTabEntry(tab[entry]);
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // The set() function writes an entry in the Update Table
+  // Arguments :
+  // - update : transaction type (bool)
+  // - srcid : srcid of the initiator
+  // - trdid : trdid of the initiator
+  // - pktid : pktid of the initiator
+  // - count : number of expected responses
+  // - index : (return argument) index of the selected entry
+  // This function returns true if the write successed (an entry was empty).
+  ///////////////////////////////////////////////////////////////////////////
+  bool set(const bool	update,
+	   const size_t srcid,
+	   const size_t trdid,
+	   const size_t pktid,
+	   const size_t count,
+	   size_t &index)
+  {
+    for ( size_t i=0 ; i<size_tab ; i++ ) {
+      if( !tab[i].valid ) {
+	tab[i].valid		= true;
+	tab[i].update		= update;
+	tab[i].srcid		= (size_t) srcid;
+	tab[i].trdid		= (size_t) trdid;
+	tab[i].pktid		= (size_t) pktid;
+	tab[i].count		= (size_t) count;
+	index			= i;
+	return true;
+      }
+    }
+    return false;
+  } // end set()
+
+    /////////////////////////////////////////////////////////////////////
+    // The decrement() function decrements the counter for a given entry.
+    // Arguments :
+    // - index   : the index of the entry
+    // - counter : (return argument) value of the counter after decrement
+    // This function returns true if the entry is valid.
+    /////////////////////////////////////////////////////////////////////
+  bool decrement( const size_t index,
+		  size_t &counter ) 
+  {
+    assert((index<size_tab) && "Bad Update Tab Entry");
+    if ( tab[index].valid ) {
+      tab[index].count--;
+      counter = tab[index].count;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_update(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].update;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The srcid() function returns the srcid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t srcid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].srcid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The trdid() function returns the trdid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t trdid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].trdid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The pktid() function returns the pktid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t pktid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].pktid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The clear() function erases an entry of the tab
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////       
+  void clear(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    tab[index].valid=false;
+    return;	
+  }
+
+};
+
+#endif
Index: trunk/modules/vci_mem_cache/caba/source/include/vci_mem_cache.h
===================================================================
--- trunk/modules/vci_mem_cache/caba/source/include/vci_mem_cache.h	(revision 2)
+++ trunk/modules/vci_mem_cache/caba/source/include/vci_mem_cache.h	(revision 2)
@@ -0,0 +1,563 @@
+/* -*- c++ -*-
+ * File         : vci_mem_cache.h
+ * Date         : 26/10/2008
+ * Copyright    : UPMC / LIP6
+ * Authors      : Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+
+#ifndef SOCLIB_CABA_MEM_CACHE_H
+#define SOCLIB_CABA_MEM_CACHE_H
+
+#include <inttypes.h>
+#include <systemc>
+#include <list>
+#include <cassert>
+#include "arithmetics.h"
+#include "alloc_elems.h"
+#include "caba_base_module.h"
+#include "vci_target.h"
+#include "vci_initiator.h"
+#include "generic_fifo.h"
+#include "mapping_table.h"
+#include "int_tab.h"
+#include "mem_cache_directory.h"
+#include "xram_transaction.h"
+#include "update_tab.h"
+#include "atomic_tab.h"
+
+#define TRANSACTION_TAB_LINES 4     // Number of lines in the transaction tab
+#define UPDATE_TAB_LINES 4          // Number of lines in the update tab
+
+namespace soclib {  namespace caba {
+    using namespace sc_core;
+
+    template<typename vci_param>
+    class VciMemCache
+      : public soclib::caba::BaseModule
+    {
+      typedef uint32_t addr_t;
+      typedef uint32_t data_t;
+      typedef uint32_t tag_t;
+      typedef uint32_t size_t;
+      typedef uint32_t be_t;
+      typedef uint32_t copy_t;
+
+      /* States of the TGT_CMD fsm */
+      enum tgt_cmd_fsm_state_e{
+        TGT_CMD_IDLE,
+	TGT_CMD_READ,
+	TGT_CMD_READ_EOP,
+	TGT_CMD_WRITE,
+	TGT_CMD_ATOMIC,
+	TGT_CMD_CLEANUP,
+      };
+
+      /* States of the TGT_RSP fsm */
+      enum tgt_rsp_fsm_state_e{
+	TGT_RSP_READ_IDLE,
+	TGT_RSP_WRITE_IDLE,
+	TGT_RSP_LLSC_IDLE,
+        TGT_RSP_CLEANUP_IDLE,
+	TGT_RSP_XRAM_IDLE,
+	TGT_RSP_INIT_IDLE,
+        TGT_RSP_READ_TEST,
+	TGT_RSP_READ_WORD,
+	TGT_RSP_READ_LINE,
+	TGT_RSP_WRITE,
+	TGT_RSP_LLSC,
+	TGT_RSP_CLEANUP,
+        TGT_RSP_XRAM_TEST,
+	TGT_RSP_XRAM_WORD,
+	TGT_RSP_XRAM_LINE,
+        TGT_RSP_INIT,
+      };
+
+      /* States of the INIT_CMD fsm */
+      enum init_cmd_fsm_state_e{
+	INIT_CMD_INVAL_IDLE,
+	INIT_CMD_INVAL_SEL,
+	INIT_CMD_INVAL_NLINE,
+        INIT_CMD_UPDT_IDLE,
+	INIT_CMD_UPDT_SEL,
+	INIT_CMD_UPDT_NLINE,
+	INIT_CMD_UPDT_INDEX,
+	INIT_CMD_UPDT_DATA,
+      };
+
+      /* States of the INIT_RSP fsm */
+      enum init_rsp_fsm_state_e{
+        INIT_RSP_IDLE,
+	INIT_RSP_UPT_LOCK,
+	INIT_RSP_UPT_CLEAR,
+	INIT_RSP_END,
+      };
+
+      /* States of the READ fsm */
+      enum read_fsm_state_e{
+        READ_IDLE,
+	READ_DIR_LOCK,
+	READ_DIR_HIT,
+	READ_RSP,
+	READ_TRT_LOCK,
+        READ_TRT_SET,
+	READ_XRAM_REQ,
+      };
+
+      /* States of the WRITE fsm */
+      enum write_fsm_state_e{
+        WRITE_IDLE,
+        WRITE_NEXT,
+	WRITE_DIR_LOCK,
+	WRITE_DIR_HIT_READ,
+	WRITE_DIR_HIT,
+        WRITE_UPT_LOCK,
+        WRITE_WAIT_UPT,
+	WRITE_UPDATE,
+	WRITE_RSP,
+	WRITE_TRT_LOCK,
+	WRITE_TRT_DATA,
+	WRITE_TRT_SET,
+	WRITE_WAIT_TRT,
+	WRITE_XRAM_REQ,
+      };
+
+      /* States of the IXR_RSP fsm */
+      enum ixr_rsp_fsm_state_e{
+    	IXR_RSP_IDLE,
+        IXR_RSP_ACK,
+	IXR_RSP_TRT_ERASE,
+	IXR_RSP_TRT_READ,
+      };
+
+      /* States of the XRAM_RSP fsm */
+      enum xram_rsp_fsm_state_e{
+    	XRAM_RSP_IDLE,
+	XRAM_RSP_TRT_COPY,
+	XRAM_RSP_TRT_DIRTY,
+	XRAM_RSP_DIR_LOCK,
+	XRAM_RSP_DIR_UPDT,
+	XRAM_RSP_DIR_RSP,
+        XRAM_RSP_UPT_LOCK,
+        XRAM_RSP_WAIT,
+	XRAM_RSP_INVAL,
+        XRAM_RSP_WRITE_DIRTY,
+      };
+
+      /* States of the XRAM_CMD fsm */
+      enum xram_cmd_fsm_state_e{
+    	XRAM_CMD_READ_IDLE,
+    	XRAM_CMD_WRITE_IDLE,
+    	XRAM_CMD_LLSC_IDLE,
+    	XRAM_CMD_XRAM_IDLE,
+    	XRAM_CMD_READ_NLINE,
+    	XRAM_CMD_WRITE_NLINE,
+    	XRAM_CMD_LLSC_NLINE,
+    	XRAM_CMD_XRAM_DATA,
+      };
+
+      /* States of the LLSC fsm */
+      enum llsc_fsm_state_e{
+	LLSC_IDLE,
+	LL_DIR_LOCK,
+	LL_DIR_HIT,
+	LL_RSP,
+	SC_DIR_LOCK,
+	SC_DIR_HIT,
+	SC_RSP_FALSE,
+	SC_RSP_TRUE,
+	LLSC_TRT_LOCK,
+	LLSC_TRT_SET,
+	LLSC_XRAM_REQ,
+      };
+
+      /* States of the CLEANUP fsm */
+      enum cleanup_fsm_state_e{
+	CLEANUP_IDLE,
+	CLEANUP_DIR_LOCK,
+	CLEANUP_DIR_WRITE,
+	CLEANUP_RSP,
+      };
+
+      /* States of the ALLOC_DIR fsm */
+      enum alloc_dir_fsm_state_e{
+	ALLOC_DIR_READ,
+	ALLOC_DIR_WRITE,
+	ALLOC_DIR_LLSC,
+        ALLOC_DIR_CLEANUP,
+	ALLOC_DIR_XRAM_RSP,
+      };
+
+      /* States of the ALLOC_TRT fsm */
+      enum alloc_trt_fsm_state_e{
+	ALLOC_TRT_READ,
+	ALLOC_TRT_WRITE,
+	ALLOC_TRT_LLSC,
+	ALLOC_TRT_XRAM_RSP,
+	ALLOC_TRT_IXR_RSP,
+      };
+
+      /* States of the ALLOC_UPT fsm */
+      enum alloc_upt_fsm_state_e{
+	ALLOC_UPT_WRITE,
+	ALLOC_UPT_XRAM_RSP,
+	ALLOC_UPT_INIT_RSP,
+      };
+
+      uint32_t	   m_cpt_cycles;            // Counter of cycles 
+      uint32_t	   m_cpt_read;              // Number of READ transactions
+      uint32_t	   m_cpt_read_miss;         // Number of MISS READ 
+      uint32_t	   m_cpt_write;             // Number of WRITE transactions
+      uint32_t	   m_cpt_write_miss;        // Number of MISS WRITE
+      uint32_t       m_cpt_write_cells;	    // Cumulated length for WRITE transactions
+      uint32_t       m_cpt_write_dirty;	    // Cumulated length for WRITE transactions
+      uint32_t	   m_cpt_update;            // Number of UPDATE transactions
+      uint32_t	   m_cpt_update_mult;       // Number of targets for UPDATE
+      uint32_t	   m_cpt_inval;             // Number of INVAL  transactions
+      uint32_t	   m_cpt_inval_mult;        // Number of targets for INVAL  
+      uint32_t	   m_cpt_cleanup;           // Number of CLEANUP transactions
+      uint32_t	   m_cpt_ll;                // Number of LL transactions
+      uint32_t	   m_cpt_sc;                // Number of SC transactions
+
+    protected:
+
+      SC_HAS_PROCESS(VciMemCache);
+    
+    public:
+      sc_in<bool> 			  	p_clk;
+      sc_in<bool> 			  	p_resetn;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt;
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ini;	
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ixr;
+
+      VciMemCache(
+		  sc_module_name name,                            // Instance Name 
+		  const soclib::common::MappingTable &mtp,        // Mapping table for primary requets
+		  const soclib::common::MappingTable &mtc,        // Mapping table for coherence requets
+		  const soclib::common::MappingTable &mtx,        // Mapping table for XRAM
+		  const soclib::common::IntTab &vci_ixr_index,  	// VCI port to XRAM (initiator)
+		  const soclib::common::IntTab &vci_ini_index,  	// VCI port to PROC (initiator)
+		  const soclib::common::IntTab &vci_tgt_index,    // VCI port to PROC (target)
+		  size_t nways,                                   // Number of ways per set 
+		  size_t nsets,                                   // Number of sets
+		  size_t nwords);                                 // Number of words per line
+
+      ~VciMemCache();
+
+      void transition();
+
+      void genMoore();
+
+      void print_stats();
+
+    private:
+
+      // Component attributes
+      const size_t   			  m_initiators;		// Number of initiators
+      const size_t			  m_ways;		// Number of ways in a set
+      const size_t			  m_sets;		// Number of cache sets
+      const size_t			  m_words;		// Number of words in a line
+      const size_t  		  	  m_srcid_ixr;		// Srcid for requests to XRAM 
+      const size_t  		  	  m_srcid_ini;		// Srcid for requests to processors
+      //soclib::common::Segment	  	  m_mem_segment;	// memory cached into the cache
+      std::list<soclib::common::Segment>	  	  m_seglist;	// memory cached into the cache
+      soclib::common::Segment	  	  m_reg_segment;	// memory cache mapped registers
+      addr_t	        		  *m_coherence_table; 	// address(srcid)
+      AtomicTab	   			  m_atomic_tab;		// atomic access table
+      TransactionTab      		  m_transaction_tab;	// xram transaction table
+      UpdateTab				  m_update_tab;		// pending update & invalidate 
+      CacheDirectory			  m_cache_directory;	// data cache directory
+
+      data_t	        	          ***m_cache_data;	// data array[set][way][word]
+
+      // adress masks
+      const soclib::common::AddressMaskingTable<addr_t>   m_x;
+      const soclib::common::AddressMaskingTable<addr_t>   m_y;
+      const soclib::common::AddressMaskingTable<addr_t>   m_z;
+      const soclib::common::AddressMaskingTable<addr_t>	m_nline; 
+
+      //////////////////////////////////////////////////
+      // Registers controlled by the TGT_CMD fsm
+      //////////////////////////////////////////////////
+
+      // Fifo between TGT_CMD fsm and READ fsm
+      GenericFifo<addr_t>    m_cmd_read_addr_fifo;
+      GenericFifo<bool>      m_cmd_read_word_fifo;
+      GenericFifo<size_t>    m_cmd_read_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_read_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_read_pktid_fifo;
+
+      // Fifo between TGT_CMD fsm and WRITE fsm    
+      GenericFifo<addr_t>    m_cmd_write_addr_fifo;
+      GenericFifo<bool>      m_cmd_write_eop_fifo;
+      GenericFifo<size_t>    m_cmd_write_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_write_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_write_pktid_fifo;
+      GenericFifo<data_t>	   m_cmd_write_data_fifo;
+      GenericFifo<be_t>	   m_cmd_write_be_fifo;
+
+      // Fifo between TGT_CMD fsm and LLSC fsm
+      GenericFifo<addr_t>    m_cmd_llsc_addr_fifo;
+      GenericFifo<bool>      m_cmd_llsc_sc_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_pktid_fifo;
+      GenericFifo<data_t>	   m_cmd_llsc_wdata_fifo;
+
+      // Fifo between TGT_CMD fsm and CLEANUP fsm
+      GenericFifo<size_t>    m_cmd_cleanup_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_cleanup_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_cleanup_pktid_fifo;
+      GenericFifo<data_t>	   m_cmd_cleanup_nline_fifo;
+
+      sc_signal<int>         r_tgt_cmd_fsm;
+	
+      sc_signal<size_t>	     r_index;
+      size_t nseg;
+      soclib::common::Segment  **m_seg;
+      ///////////////////////////////////////////////////////
+      // Registers controlled by the READ fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>         r_read_fsm;				// FSM state 
+      sc_signal<copy_t>      r_read_copies;			// bit-vector of copies 
+      sc_signal<tag_t>       r_read_tag;				// cache line tag (in directory)
+      sc_signal<bool>        r_read_lock;				// lock bit (in directory)
+      sc_signal<bool>        r_read_dirty;			// dirty bit (in directory)
+      sc_signal<data_t>     *r_read_data;				// data (one cache line)
+      sc_signal<bool>        r_read_word;				// single word read
+      sc_signal<size_t>      r_read_way;				// associative way (in cache)
+      sc_signal<size_t>      r_read_trt_index;			// Transaction Table index
+    
+      // Buffer between READ fsm and XRAM_CMD fsm (ask a missing cache line to XRAM)   
+      sc_signal<bool>        r_read_to_xram_cmd_req;		// valid request
+      sc_signal<data_t>      r_read_to_xram_cmd_nline;		// cache line index
+      sc_signal<size_t>      r_read_to_xram_cmd_trdid;		// index in Transaction Table
+
+      // Buffer between READ fsm and TGT_RSP fsm (send a hit read response to L1 cache)
+      sc_signal<bool>	   r_read_to_tgt_rsp_req;		// valid request
+      sc_signal<size_t>	   r_read_to_tgt_rsp_srcid;		// Transaction srcid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_trdid;		// Transaction trdid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_pktid;		// Transaction pktid
+      sc_signal<data_t> 	  *r_read_to_tgt_rsp_data;		// data (one cache line)
+      sc_signal<bool> 	  *r_read_to_tgt_rsp_val;		// valid bit (for single_word)
+
+      ///////////////////////////////////////////////////////////////
+      // Registers controlled by the WRITE fsm
+      ///////////////////////////////////////////////////////////////
+
+      sc_signal<int>         r_write_fsm;				// FSM state
+      sc_signal<addr_t>	   r_write_address;			// first word address
+      sc_signal<size_t>      r_write_word_index;			// first word index in line
+      sc_signal<size_t>      r_write_word_count;			// number of words in line
+      sc_signal<size_t>      r_write_srcid;			// transaction srcid
+      sc_signal<size_t>      r_write_trdid;			// transaction trdid
+      sc_signal<size_t>      r_write_pktid;			// transaction pktid
+      sc_signal<data_t>	  *r_write_data;			// data (one cache line)	
+      sc_signal<be_t>       *r_write_be;				// one byte enable per word
+      sc_signal<bool>        r_write_byte;			// is it a byte write
+      sc_signal<bool>        r_write_lock;			// lock bit (in directory)
+      sc_signal<tag_t>       r_write_tag;	  			// cache line tag (in directory)
+      sc_signal<copy_t>      r_write_copies;			// bit vector of copies
+      sc_signal<size_t>	   r_write_nb_copies;			// number of copies
+      sc_signal<size_t>	   r_write_way;				// way of the line
+      sc_signal<size_t>      r_write_trt_index;			// index in Transaction Table
+      sc_signal<size_t>      r_write_upt_index;			// index in Update Table
+
+      // 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
+
+      // Buffer between WRITE fsm and XRAM_CMD fsm (ask a missing cache line to XRAM) 
+      sc_signal<bool>	   r_write_to_xram_cmd_req;		// valid request
+      sc_signal<data_t>      r_write_to_xram_cmd_nline;		// cache line index
+      sc_signal<size_t>      r_write_to_xram_cmd_trdid;		// index in Transaction Table
+
+      // Buffer between WRITE fsm and INIT_CMD fsm (Update L1 caches)
+      sc_signal<bool>	   r_write_to_init_cmd_req;		// valid request
+      sc_signal<data_t>	   r_write_to_init_cmd_nline;		// cache line index
+      sc_signal<size_t>	   r_write_to_init_cmd_trdid;		// index in Update Table
+      sc_signal<copy_t>      r_write_to_init_cmd_copies;		// bit_vector of L1 to update
+      sc_signal<data_t>     *r_write_to_init_cmd_data;		// data (one cache line)
+      sc_signal<bool>       *r_write_to_init_cmd_we;		// word enable
+      sc_signal<size_t>	   r_write_to_init_cmd_count;		// number of words in line
+      sc_signal<size_t>	   r_write_to_init_cmd_index;		// index of first word in line
+
+      /////////////////////////////////////////////////////////
+      // Registers controlled by INIT_RSP fsm
+      //////////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_init_rsp_fsm;			// FSM state
+      sc_signal<size_t>	   r_init_rsp_upt_index;		// index in the Update Table
+      sc_signal<size_t>	   r_init_rsp_srcid;			// pending write srcid      
+      sc_signal<size_t>	   r_init_rsp_trdid;			// pending write trdid      
+      sc_signal<size_t>	   r_init_rsp_pktid;			// pending write pktid      
+
+      // Buffer between INIT_RSP fsm and TGT_RSP fsm (complete write/update transaction)
+      sc_signal<bool>	   r_init_rsp_to_tgt_rsp_req;   	// valid request
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_srcid;		// Transaction srcid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_trdid;		// Transaction trdid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_pktid;		// Transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by CLEANUP fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_cleanup_fsm;			// FSM state
+      sc_signal<size_t>      r_cleanup_srcid;			// transaction srcid
+      sc_signal<size_t>      r_cleanup_trdid;			// transaction trdid
+      sc_signal<size_t>      r_cleanup_pktid;			// transaction pktid
+      sc_signal<data_t>      r_cleanup_nline;			// cache line index
+
+      sc_signal<copy_t>      r_cleanup_copies;			// bit-vector of copies 
+      sc_signal<tag_t>       r_cleanup_tag;			// cache line tag (in directory)
+      sc_signal<bool>        r_cleanup_lock;			// lock bit (in directory)
+      sc_signal<bool>        r_cleanup_dirty;			// dirty bit (in directory)
+      sc_signal<size_t>      r_cleanup_way;			// associative way (in cache)
+
+      // Buffer between CLEANUP fsm and TGT_RSP fsm (acknowledge a cleanup command from L1)
+      sc_signal<bool>        r_cleanup_to_tgt_rsp_req;		// valid request
+      sc_signal<size_t>      r_cleanup_to_tgt_rsp_srcid;		// transaction srcid
+      sc_signal<size_t>      r_cleanup_to_tgt_rsp_trdid;		// transaction trdid
+      sc_signal<size_t>      r_cleanup_to_tgt_rsp_pktid;		// transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by LLSC fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_llsc_fsm;				// FSM state
+      sc_signal<data_t>	   r_llsc_data;				// read data word
+      sc_signal<copy_t>  	   r_llsc_copies;			// bit_vector of copies
+      sc_signal<bool>    	   r_llsc_dirty;			// dirty bit (in directory)
+      sc_signal<size_t>  	   r_llsc_way;				// way in directory
+      sc_signal<size_t>  	   r_llsc_set;				// set in directory
+      sc_signal<data_t>  	   r_llsc_tag;				// cache line tag (in directory)
+      sc_signal<size_t>  	   r_llsc_trt_index;    		// Transaction Table index
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (XRAM read)	
+      sc_signal<bool>	   r_llsc_to_xram_cmd_req;		// valid request
+      sc_signal<data_t>	   r_llsc_to_xram_cmd_nline;		// cache line index
+      sc_signal<size_t>	   r_llsc_to_xram_cmd_trdid;		// index in Transaction Table
+
+      // Buffer between LLSC fsm and TGT_RSP fsm
+      sc_signal<bool>	   r_llsc_to_tgt_rsp_req;		// valid request
+      sc_signal<data_t> 	   r_llsc_to_tgt_rsp_data;		// read data word
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_srcid;		// Transaction srcid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_trdid;		// Transaction trdid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_pktid;		// Transaction pktid
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_rsp_fsm;			// FSM state
+      sc_signal<size_t>	   r_ixr_rsp_trt_index;			// TRT entry index
+      sc_signal<size_t> 	   r_ixr_rsp_cpt;			// word counter
+
+      // Buffer between IXR_RSP fsm and XRAM_RSP fsm  (response from the XRAM)
+      sc_signal<bool>	  *r_ixr_rsp_to_xram_rsp_rok;		// A xram response is ready
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the XRAM_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_xram_rsp_fsm;			// FSM state
+      sc_signal<size_t>	   r_xram_rsp_trt_index;		// TRT entry index
+      TransactionTabEntry    r_xram_rsp_trt_buf;			// TRT entry local buffer
+      sc_signal<bool>	   r_xram_rsp_victim_inval;		// victim line invalidate 
+      sc_signal<bool>	   r_xram_rsp_victim_dirty;		// victim line dirty bit
+      sc_signal<size_t> 	   r_xram_rsp_victim_way;		// victim line way
+      sc_signal<size_t> 	   r_xram_rsp_victim_set;		// victim line set
+      sc_signal<data_t> 	   r_xram_rsp_victim_nline;		// victim line index
+      sc_signal<copy_t>      r_xram_rsp_victim_copies;		// victim line copies
+      sc_signal<data_t>	  *r_xram_rsp_victim_data;		// victim line data
+      sc_signal<size_t>	   r_xram_rsp_upt_index;		// UPT entry index
+
+      // Buffer between XRAM_RSP fsm and TGT_RSP fsm  (response to L1 cache)
+      sc_signal<bool>	   r_xram_rsp_to_tgt_rsp_req;		// Valid request
+      sc_signal<size_t>      r_xram_rsp_to_tgt_rsp_srcid;		// Transaction srcid
+      sc_signal<size_t>      r_xram_rsp_to_tgt_rsp_trdid;		// Transaction trdid
+      sc_signal<size_t>      r_xram_rsp_to_tgt_rsp_pktid;		// Transaction pktid
+      sc_signal<data_t>     *r_xram_rsp_to_tgt_rsp_data;		// data (one cache line)
+      sc_signal<bool>       *r_xram_rsp_to_tgt_rsp_val;		// valid bit (for single word)
+
+      // Buffer between XRAM_RSP fsm and INIT_CMD fsm (Inval L1 Caches) 
+      sc_signal<bool>	   r_xram_rsp_to_init_cmd_req;		// Valid request
+      sc_signal<data_t>      r_xram_rsp_to_init_cmd_nline;	// cache line index;
+      sc_signal<size_t>	   r_xram_rsp_to_init_cmd_trdid;	// index of UPT entry
+      sc_signal<copy_t>      r_xram_rsp_to_init_cmd_copies;	// bit_vector of copies
+
+      // Buffer between XRAM_RSP fsm and XRAM_CMD fsm (XRAM write)
+      sc_signal<bool>	   r_xram_rsp_to_xram_cmd_req;		// Valid request
+      sc_signal<data_t>	   r_xram_rsp_to_xram_cmd_nline;	// cache line index
+      sc_signal<data_t>	  *r_xram_rsp_to_xram_cmd_data;		// cache line data
+      sc_signal<size_t>	   r_xram_rsp_to_xram_cmd_trdid;	// index in transaction table
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the XRAM_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_xram_cmd_fsm;
+      sc_signal<size_t>		r_xram_cmd_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by TGT_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_tgt_rsp_fsm;
+      sc_signal<size_t> 		r_tgt_rsp_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by INIT_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_init_cmd_fsm;
+      sc_signal<size_t>		r_init_cmd_cpt;
+      sc_signal<size_t>		r_init_cmd_target;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_DIR fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_dir_fsm;
+    
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_TRT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_trt_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_UPT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_upt_fsm;
+
+    }; // end class VciMemCache
+ 
+  }}
+
+#endif
Index: trunk/modules/vci_mem_cache/caba/source/include/xram_transaction.h
===================================================================
--- trunk/modules/vci_mem_cache/caba/source/include/xram_transaction.h	(revision 2)
+++ trunk/modules/vci_mem_cache/caba/source/include/xram_transaction.h	(revision 2)
@@ -0,0 +1,392 @@
+#ifndef XRAM_TRANSACTION_H_
+#define XRAM_TRANSACTION_H_
+ 
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+#define DEBUG_XRAM_TRANSACTION 0
+
+////////////////////////////////////////////////////////////////////////
+//                  A transaction tab entry         
+////////////////////////////////////////////////////////////////////////
+
+class TransactionTabEntry {
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef uint32_t be_t;
+
+ public:
+  bool 	valid;     		// entry valid 
+  bool 	xram_read; 		// read request to XRAM
+  data_t  	nline;    		// index (zy) of the requested line
+  size_t 	srcid;     		// processor requesting the transaction
+  size_t 	trdid;     		// processor requesting the transaction
+  size_t 	pktid;     		// processor requesting the transaction
+  bool 	proc_read;	 	// read request from processor
+  bool 	single_word;   		// single word in case of processor read 
+  size_t 	word_index;    		// word index in case of single word read
+  std::vector<data_t> wdata;        	// write buffer (one cache line)
+  std::vector<be_t> wdata_be;    	// be for each data in the write buffer
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    valid		= false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The alloc() function initializes the vectors of an entry
+  // Its arguments are :
+  // - n_words : number of words per line in the cache
+  /////////////////////////////////////////////////////////////////////
+  void alloc(size_t n_words)
+  {
+    wdata_be.reserve( (int)n_words );
+    wdata.reserve( (int)n_words );
+    for(size_t i=0; i<n_words; i++){
+      wdata_be.push_back(false);
+      wdata.push_back(0);
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the transaction tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const TransactionTabEntry &source)
+  {
+    valid		= source.valid;
+    xram_read 	= source.xram_read;
+    nline		= source.nline;
+    srcid		= source.srcid;
+    trdid		= source.trdid;
+    pktid		= source.pktid;
+    proc_read 	= source.proc_read;
+    single_word 	= source.single_word;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry 
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << "valid       = " << valid        << std::endl;
+    std::cout << "xram_read   = " << xram_read    << std::endl;
+    std::cout << "nline       = " << nline        << std::endl;
+    std::cout << "srcid       = " << srcid        << std::endl;
+    std::cout << "trdid       = " << trdid        << std::endl;
+    std::cout << "pktid       = " << pktid        << std::endl;
+    std::cout << "proc_read   = " << proc_read    << std::endl;
+    std::cout << "single_word = " << single_word  << std::endl;
+    std::cout << "word_index  = " << word_index   << std::endl; 
+    for(size_t i=0; i<wdata_be.size() ; i++){
+      std::cout << "wdata_be [" << i <<"] = " << wdata_be[i] << std::endl;
+    }
+    for(size_t i=0; i<wdata.size() ; i++){
+      std::cout << "wdata [" << i <<"] = " << wdata[i] << std::endl;
+    }
+    std::cout << std::endl;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // 		Constructors
+  /////////////////////////////////////////////////////////////////////
+
+  TransactionTabEntry()
+    {
+      wdata_be.clear();
+      wdata.clear();
+      valid=false;
+    }
+
+  TransactionTabEntry(const TransactionTabEntry &source){
+    valid		= source.valid;
+    xram_read	= source.xram_read;
+    nline		= source.nline;
+    srcid		= source.srcid;
+    trdid		= source.trdid;
+    pktid		= source.pktid;
+    proc_read	= source.proc_read;
+    single_word 	= source.single_word;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+}; // end class TransactionTabEntry
+
+////////////////////////////////////////////////////////////////////////
+//                  The transaction tab                              
+////////////////////////////////////////////////////////////////////////
+class TransactionTab{
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef uint32_t be_t;
+
+ private:
+  size_t size_tab;                // The size of the tab
+
+  data_t be_to_mask(be_t be)
+  {
+    data_t ret = 0;
+    if ( be&0x1 ) {
+      ret = ret | 0x000000FF;
+    }
+    if ( be&0x2 ) {
+      ret = ret | 0x0000FF00;
+    }
+    if ( be&0x4 ) {
+      ret = ret | 0x00FF0000;
+    }
+    if ( be&0x8 ) {
+      ret = ret | 0xFF000000;
+    }
+    return ret;
+  }
+
+ public:
+  TransactionTabEntry *tab;       // The transaction tab
+
+  ////////////////////////////////////////////////////////////////////
+  //		Constructors
+  ////////////////////////////////////////////////////////////////////
+  TransactionTab()
+    {
+      size_tab=0;
+      tab=NULL;
+    }
+
+  TransactionTab(size_t n_entries, size_t n_words)
+    {
+      size_tab = n_entries;
+      tab = new TransactionTabEntry[size_tab];
+      for ( size_t i=0; i<size_tab; i++) {
+	tab[i].alloc(n_words);
+      }
+    }
+
+  ~TransactionTab()
+    {
+      delete [] tab;
+    }
+
+  /////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab
+  /////////////////////////////////////////////////////////////////////
+  size_t size()
+  {
+    return size_tab;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the transaction tab entries
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The print() function prints a transaction tab entry
+  // Arguments :
+  // - index : the index of the entry to print
+  /////////////////////////////////////////////////////////////////////
+  void print(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    tab[index].print();
+    return;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read() function returns a transaction tab entry.
+  // Arguments :
+  // - index : the index of the entry to read
+  /////////////////////////////////////////////////////////////////////
+  TransactionTabEntry read(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    return tab[index];
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The full() function returns the state of the transaction tab
+  // Arguments :
+  // - index : (return argument) the index of an empty entry 
+  // The function returns true if the transaction tab is full
+  /////////////////////////////////////////////////////////////////////
+  bool full(size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(!tab[i].valid){
+	index=i;
+	return false;	
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The hit_read() function checks if an XRAM read transaction exists 
+  // for a given cache line.
+  // Arguments :
+  // - index : (return argument) the index of the hit entry, if there is 
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a read request has already been sent
+  //////////////////////////////////////////////////////////////////////
+  bool hit_read(const data_t nline,size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(tab[i].valid && (nline==tab[i].nline) && tab[i].xram_read) {
+	index=i;
+	return true;	
+      }
+    }
+    return false;
+  }
+
+  ///////////////////////////////////////////////////////////////////////
+  // The hit_write() function looks if an XRAM write transaction exists 
+  // for a given line.
+  // Arguments :
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a write request has already been sent
+  ///////////////////////////////////////////////////////////////////////
+  bool hit_write(const data_t nline)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(tab[i].valid && (nline==tab[i].nline) && !(tab[i].xram_read)) {
+	return true;	
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_data_mask() function writes a vector of data (a line).
+  // The data is written only if the corresponding bits are set
+  // in the be vector. 
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  // - be   : vector of be 
+  // - data : vector of data
+  /////////////////////////////////////////////////////////////////////
+  void write_data_mask(const size_t index, 
+		       const std::vector<be_t> &be, 
+		       const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    assert(be.size()==tab[index].wdata_be.size() 
+	   && "Bad data mask in write_data_mask in TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data in write_data_mask in TransactionTab");
+
+    for(size_t i=0; i<tab[index].wdata_be.size() ; i++) {
+      tab[index].wdata_be[i] = tab[index].wdata_be[i] | be[i];
+      data_t mask = be_to_mask(be[i]);
+      tab[index].wdata[i] = (tab[index].wdata[i] & ~mask) | (data[i] & mask);
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The set() function registers a transaction (read or write)
+  // to the XRAM in the transaction tab.
+  // Arguments :
+  // - index : index in the transaction tab
+  // - xram_read : transaction type (read or write a cache line)
+  // - nline : the index (zy) of the cache line
+  // - srcid : srcid of the initiator that caused the transaction
+  // - trdid : trdid of the initiator that caused the transaction
+  // - pktid : pktid of the initiator that caused the transaction
+  // - proc_read : does the initiator want a copy
+  // - single_word : single word read (in case of processor read)
+  // - word_index : index in the line (in case of single word read)
+  // - data : the data to write (in case of write)
+  // - data_be : the mask of the data to write (in case of write)
+  /////////////////////////////////////////////////////////////////////
+  void set(const size_t index,
+	   const bool xram_read,
+	   const data_t nline,
+	   const size_t srcid,
+	   const size_t trdid,
+	   const size_t pktid,
+	   const bool proc_read,
+	   const bool single_word,
+	   const size_t word_index,
+	   const std::vector<be_t> &data_be,
+	   const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in set() Transaction Tab");
+    assert(data_be.size()==tab[index].wdata_be.size() 
+	   && "Bad data_be argument in set() TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data argument in set() TransactionTab");
+
+    tab[index].valid	= true;
+    tab[index].xram_read	= xram_read;
+    tab[index].nline	= nline;
+    tab[index].srcid	= srcid;
+    tab[index].trdid	= trdid;
+    tab[index].pktid	= pktid;
+    tab[index].proc_read	= proc_read;
+    tab[index].single_word	= single_word;
+    tab[index].word_index	= word_index;
+    for(size_t i=0; i<tab[index].wdata.size(); i++) {
+      tab[index].wdata_be[i] = data_be[i];
+      tab[index].wdata[i]    = data[i];
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_rsp() function writes a word of the response to an 
+  // XRAM read transaction.
+  // The data is only written when the corresponding BE field is Ox0.
+  // Arguments :
+  // - index : the index of the transaction in the transaction tab
+  // - word_index : the index of the data in the line
+  // - data : the data to write
+  /////////////////////////////////////////////////////////////////////
+  void write_rsp(const size_t index,
+		 const size_t word,
+		 const data_t data)
+  {
+    assert( (index < size_tab) 
+	    && "Selected entry  out of range in write_rsp() Transaction Tab");
+    assert( (word <= tab[index].wdata_be.size()) 
+	    && "Bad word_index in write_rsp() in TransactionTab");
+    assert( tab[index].valid 
+	    && "Transaction Tab Entry invalid in write_rsp()");
+    assert( tab[index].xram_read 
+	    && "Selected entry is not an XRAM read transaction in write_rsp()");
+
+    data_t mask = be_to_mask(tab[index].wdata_be[word]);
+    tab[index].wdata[word] = (tab[index].wdata[word] & mask) | (data & ~mask);
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The erase() function erases an entry in the transaction tab.
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  /////////////////////////////////////////////////////////////////////
+  void erase(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in erase() Transaction Tab");
+    tab[index].valid	= false;
+  }
+}; // end class TransactionTab
+
+#endif
Index: trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp
===================================================================
--- trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 2)
+++ trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 2)
@@ -0,0 +1,2790 @@
+/* -*- c++ -*-
+ * File 	: vci_mem_cache.cpp
+ * Date 	: 30/10/2008
+ * Copyright 	: UPMC / LIP6
+ * Authors 	: Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+
+#include "../include/vci_mem_cache.h"
+
+#define DEBUG_VCI_MEM_CACHE 0
+
+namespace soclib { namespace caba {
+
+#ifdef DEBUG_VCI_MEM_CACHE 
+  const char *tgt_cmd_fsm_str[] = {
+    "TGT_CMD_IDLE",
+    "TGT_CMD_READ",
+    "TGT_CMD_READ_EOP",
+    "TGT_CMD_WRITE",
+    "TGT_CMD_ATOMIC",
+    "TGT_CMD_CLEANUP",
+  };
+  const char *tgt_rsp_fsm_str[] = {
+    "TGT_RSP_READ_IDLE",
+    "TGT_RSP_WRITE_IDLE",
+    "TGT_RSP_LLSC_IDLE",
+    "TGT_RSP_CLEANUP_IDLE",
+    "TGT_RSP_XRAM_IDLE",
+    "TGT_RSP_INIT_IDLE",
+    "TGT_RSP_READ_TEST",
+    "TGT_RSP_READ_WORD",
+    "TGT_RSP_READ_LINE",
+    "TGT_RSP_WRITE",
+    "TGT_RSP_LLSC",
+    "TGT_RSP_CLEANUP",
+    "TGT_RSP_XRAM_TEST",
+    "TGT_RSP_XRAM_WORD",
+    "TGT_RSP_XRAM_LINE",
+    "TGT_RSP_INIT",
+  };
+  const char *init_cmd_fsm_str[] = {
+    "INIT_CMD_INVAL_IDLE",
+    "INIT_CMD_INVAL_SEL",
+    "INIT_CMD_INVAL_NLINE",
+    "INIT_CMD_UPDT_IDLE",
+    "INIT_CMD_UPDT_SEL",
+    "INIT_CMD_UPDT_NLINE",
+    "INIT_CMD_UPDT_INDEX",
+    "INIT_CMD_UPDT_DATA",
+  };
+  const char *init_rsp_fsm_str[] = {
+    "INIT_RSP_IDLE",
+    "INIT_RSP_UPT_LOCK",
+    "INIT_RSP_UPT_CLEAR",
+    "INIT_RSP_END",
+  };
+  const char *read_fsm_str[] = {
+    "READ_IDLE",
+    "READ_DIR_LOCK",
+    "READ_DIR_HIT",
+    "READ_RSP",
+    "READ_TRT_LOCK",
+    "READ_TRT_SET",
+    "READ_XRAM_REQ",
+  };
+  const char *write_fsm_str[] = {
+    "WRITE_IDLE",
+    "WRITE_NEXT"
+      "WRITE_DIR_LOCK",
+    "WRITE_DIR_HIT_READ",
+    "WRITE_DIR_HIT",
+    "WRITE_UPT_LOCK",
+    "WRITE_WAIT_UPT",
+    "WRITE_UPDATE",
+    "WRITE_RSP",
+    "WRITE_TRT_LOCK",
+    "WRITE_TRT_DATA",
+    "WRITE_TRT_SET",
+    "WRITE_WAIT_TRT",
+    "WRITE_XRAM_REQ",
+  };
+  const char *ixr_rsp_fsm_str[] = {
+    "IXR_RSP_IDLE",
+    "IXR_RSP_ACK",
+    "IXR_RSP_TRT_ERASE",
+    "IXR_RSP_TRT_READ",
+  };
+  const char *xram_rsp_fsm_str[] = {
+    "XRAM_RSP_IDLE",
+    "XRAM_RSP_TRT_COPY",
+    "XRAM_RSP_TRT_DIRTY",
+    "XRAM_RSP_DIR_LOCK",
+    "XRAM_RSP_DIR_UPDT",
+    "XRAM_RSP_DIR_RSP",
+    "XRAM_RSP_UPT_LOCK",
+    "XRAM_RSP_WAIT",
+    "XRAM_RSP_INVAL",
+    "XRAM_RSP_WRITE_DIRTY",
+  };
+  const char *xram_cmd_fsm_str[] = {
+    "XRAM_CMD_READ_IDLE",
+    "XRAM_CMD_WRITE_IDLE",
+    "XRAM_CMD_LLSC_IDLE",
+    "XRAM_CMD_XRAM_IDLE",
+    "XRAM_CMD_READ_NLINE",
+    "XRAM_CMD_WRITE_NLINE",
+    "XRAM_CMD_LLSC_NLINE",
+    "XRAM_CMD_XRAM_DATA",
+  };
+  const char *llsc_fsm_str[] = {
+    "LLSC_IDLE",
+    "LL_DIR_LOCK",
+    "LL_DIR_HIT",
+    "LL_RSP",
+    "SC_DIR_LOCK",
+    "SC_DIR_HIT",
+    "SC_RSP_FALSE",
+    "SC_RSP_TRUE",
+    "LLSC_TRT_LOCK",
+    "LLSC_TRT_SET",
+    "LLSC_XRAM_REQ",
+  };
+  const char *cleanup_fsm_str[] = {
+    "CLEANUP_IDLE",
+    "CLEANUP_DIR_LOCK",
+    "CLEANUP_DIR_WRITE",
+    "CLEANUP_RSP",
+  };
+  const char *alloc_dir_fsm_str[] = {
+    "ALLOC_DIR_READ",
+    "ALLOC_DIR_WRITE",
+    "ALLOC_DIR_LLSC",
+    "ALLOC_DIR_CLEANUP",
+    "ALLOC_DIR_XRAM_RSP",
+  };
+  const char *alloc_trt_fsm_str[] = {
+    "ALLOC_TRT_READ",
+    "ALLOC_TRT_WRITE",
+    "ALLOC_TRT_LLSC",
+    "ALLOC_TRT_XRAM_RSP",
+    "ALLOC_TRT_IXR_RSP",
+  };
+  const char *alloc_upt_fsm_str[] = {
+    "ALLOC_UPT_WRITE",
+    "ALLOC_UPT_XRAM_RSP",
+    "ALLOC_UPT_INIT_RSP",
+  };
+#endif
+
+#define tmpl(x) template<typename vci_param> x VciMemCache<vci_param>
+
+  using soclib::common::uint32_log2;
+
+  ////////////////////////////////
+  // 	Constructor 
+  ////////////////////////////////
+
+  tmpl(/**/)::VciMemCache( 
+      sc_module_name name,
+      const soclib::common::MappingTable &mtp,
+      const soclib::common::MappingTable &mtc,
+      const soclib::common::MappingTable &mtx,
+      const soclib::common::IntTab &vci_ixr_index,
+      const soclib::common::IntTab &vci_ini_index,
+      const soclib::common::IntTab &vci_tgt_index,
+      size_t nways,
+      size_t nsets,
+      size_t nwords)
+
+    : soclib::caba::BaseModule(name),
+
+    p_clk("clk"),
+    p_resetn("resetn"),
+    p_vci_tgt("vci_tgt"),
+    p_vci_ini("vci_ini"),
+
+    m_initiators( 32 ),
+    m_ways( nways ),
+    m_sets( nsets ),
+    m_words( nwords ),
+    m_srcid_ixr( mtx.indexForId(vci_ixr_index) ),
+    m_srcid_ini( mtc.indexForId(vci_ini_index) ),
+    //m_mem_segment("bidon",0,0,soclib::common::IntTab(),false),
+    m_seglist(mtp.getSegmentList(vci_tgt_index)),
+    m_reg_segment("bidon",0,0,soclib::common::IntTab(),false),
+    m_coherence_table( mtc.getCoherenceTable() ),
+    m_atomic_tab( m_initiators ),
+    m_transaction_tab( TRANSACTION_TAB_LINES, nwords ),
+    m_update_tab( UPDATE_TAB_LINES ),
+    m_cache_directory( nways, nsets, nwords, vci_param::N ),
+    nseg(0),	
+#define L2 soclib::common::uint32_log2
+    m_x( L2(m_words), 2),
+    m_y( L2(m_sets), L2(m_words) + 2),
+    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
+    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
+#undef L2
+
+    //  FIFOs 
+    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
+    m_cmd_read_word_fifo("m_cmd_read_word_fifo", 4),
+    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
+    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
+    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
+
+    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
+    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
+    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
+    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
+    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
+    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
+    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
+
+    m_cmd_llsc_addr_fifo("m_cmd_llsc_addr_fifo",4),
+    m_cmd_llsc_sc_fifo("m_cmd_llsc_sc_fifo",4),
+    m_cmd_llsc_srcid_fifo("m_cmd_llsc_srcid_fifo",4),
+    m_cmd_llsc_trdid_fifo("m_cmd_llsc_trdid_fifo",4),
+    m_cmd_llsc_pktid_fifo("m_cmd_llsc_pktid_fifo",4),
+    m_cmd_llsc_wdata_fifo("m_cmd_llsc_wdata_fifo",4),
+
+    m_cmd_cleanup_srcid_fifo("m_cmd_cleanup_srcid_fifo",4),
+    m_cmd_cleanup_trdid_fifo("m_cmd_cleanup_trdid_fifo",4),
+    m_cmd_cleanup_pktid_fifo("m_cmd_cleanup_pktid_fifo",4),
+    m_cmd_cleanup_nline_fifo("m_cmd_cleanup_nline_fifo",4),
+
+    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
+    r_read_fsm("r_read_fsm"),
+    r_write_fsm("r_write_fsm"),
+    r_init_rsp_fsm("r_init_rsp_fsm"),
+    r_cleanup_fsm("r_cleanup_fsm"),
+    r_llsc_fsm("r_llsc_fsm"),
+    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
+    r_xram_rsp_fsm("r_xram_rsp_fsm"),
+    r_xram_cmd_fsm("r_xram_cmd_fsm"),
+    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
+    r_init_cmd_fsm("r_init_cmd_fsm"),
+    r_alloc_dir_fsm("r_alloc_dir_fsm"),
+    r_alloc_trt_fsm("r_alloc_trt_fsm"),
+    r_alloc_upt_fsm("r_alloc_upt_fsm")
+    {
+      assert(IS_POW_OF_2(nsets));
+      assert(IS_POW_OF_2(nwords));
+      assert(IS_POW_OF_2(nways));
+      assert(nsets);
+      assert(nwords);
+      assert(nways);
+      assert(nsets <= 1024);
+      assert(nwords <= 32);
+      assert(nways <= 32);
+
+      // Get the segments associated to the MemCache 
+      //std::list<soclib::common::Segment> segList(mtp.getSegmentList(vci_tgt_index));
+      std::list<soclib::common::Segment>::iterator seg;
+      /*
+         for(seg = segList.begin(); seg != segList.end() ; seg++) {
+         if( seg->size() > 8 ) m_mem_segment = *seg; 
+         else                  m_reg_segment = *seg;
+         nseg++;
+         }
+         */
+
+      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
+        if( seg->size() > 8 ) nseg++;
+      }
+      //assert( (nseg == 2) && (m_reg_segment.size() == 8) );
+
+      m_seg = new soclib::common::Segment*[nseg];
+      size_t i = 0;
+      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) { 
+        if ( seg->size() > 8 ) 
+        {
+          m_seg[i] = &(*seg);
+          i++;
+        }
+        else
+        {
+          m_reg_segment = *seg;
+        }		
+      }
+
+      assert( (m_reg_segment.size() == 8) );
+
+      // Memory cache allocation & initialisation
+      m_cache_data = new data_t**[nways];
+      for ( size_t i=0 ; i<nways ; ++i ) {
+        m_cache_data[i] = new data_t*[nsets];
+      }
+      for ( size_t i=0; i<nways; ++i ) {
+        for ( size_t j=0; j<nsets; ++j ) {
+          m_cache_data[i][j] = new data_t[nwords];
+          for ( size_t k=0; k<nwords; k++){
+            m_cache_data[i][j][k]=0;
+          }	
+        }
+      }
+
+      // Allocation for IXR_RSP FSM
+      r_ixr_rsp_to_xram_rsp_rok	    	= new sc_signal<bool>[TRANSACTION_TAB_LINES];
+
+      // Allocation for XRAM_RSP FSM
+      r_xram_rsp_victim_data        	= new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_tgt_rsp_data    	= new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_tgt_rsp_val     	= new sc_signal<bool>[nwords];
+      r_xram_rsp_to_xram_cmd_data   	= new sc_signal<data_t>[nwords];
+
+      // Allocation for READ FSM
+      r_read_data 			= new sc_signal<data_t>[nwords];
+      r_read_to_tgt_rsp_data 		= new sc_signal<data_t>[nwords];
+      r_read_to_tgt_rsp_val 		= new sc_signal<bool>[nwords];
+
+      // Allocation for WRITE FSM
+      r_write_data 			= new sc_signal<data_t>[nwords];
+      r_write_be 			= new sc_signal<be_t>[nwords];
+      r_write_to_init_cmd_data 		= new sc_signal<data_t>[nwords];
+      r_write_to_init_cmd_we		= new sc_signal<bool>[nwords];
+
+      // Simulation
+
+      SC_METHOD(transition);
+      dont_initialize();
+      sensitive << p_clk.pos();
+
+      SC_METHOD(genMoore);
+      dont_initialize();
+      sensitive << p_clk.neg();
+
+    } // end constructor
+
+  /////////////////////////////////////////
+  // This function prints the statistics 
+  /////////////////////////////////////////
+
+  tmpl(void)::print_stats()
+  {
+    std::cout << "----------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
+      << "- READ RATE           = " << (float)m_cpt_read/m_cpt_cycles << std::endl
+      << "- READ MISS RATE      = " << (float)m_cpt_read_miss/m_cpt_read << std::endl
+      << "- WRITE RATE          = " << (float)m_cpt_write/m_cpt_cycles << std::endl
+      << "- WRITE MISS RATE     = " << (float)m_cpt_write_miss/m_cpt_write << std::endl
+      << "- WRITE BURST LENGTH  = " << (float)m_cpt_write_cells/m_cpt_write << std::endl
+      << "- UPDATE RATE         = " << (float)m_cpt_update/m_cpt_cycles << std::endl
+      << "- UPDATE ARITY        = " << (float)m_cpt_update_mult/m_cpt_update << std::endl
+      << "- INVAL RATE          = " << (float)m_cpt_inval/m_cpt_cycles << std::endl
+      << "- INVAL ARITY         = " << (float)m_cpt_inval_mult/m_cpt_inval << std::endl
+      << "- SAVE DIRTY RATE     = " << (float)m_cpt_write_dirty/m_cpt_cycles << std::endl
+      << "- CLEANUP RATE        = " << (float)m_cpt_cleanup/m_cpt_cycles << std::endl
+      << "- LL RATE             = " << (float)m_cpt_ll/m_cpt_cycles << std::endl
+      << "- SC RATE             = " << (float)m_cpt_sc/m_cpt_cycles << std::endl;
+  }
+
+  /////////////////////////////////
+  tmpl(/**/)::~VciMemCache()
+    /////////////////////////////////
+  {
+    for(size_t i=0; i<m_ways ; i++){
+      for(size_t j=0; j<m_sets ; j++){
+        delete [] m_cache_data[i][j];
+      }
+    }
+    for(size_t i=0; i<m_ways ; i++){
+      delete [] m_cache_data[i];
+    }
+    delete [] m_cache_data;
+    delete [] m_coherence_table;
+
+    delete [] r_ixr_rsp_to_xram_rsp_rok;
+
+    delete [] r_xram_rsp_victim_data;
+    delete [] r_xram_rsp_to_tgt_rsp_data;
+    delete [] r_xram_rsp_to_tgt_rsp_val;
+    delete [] r_xram_rsp_to_xram_cmd_data;
+
+    delete [] r_read_data;
+    delete [] r_read_to_tgt_rsp_data;
+    delete [] r_read_to_tgt_rsp_val;
+
+    delete [] r_write_data;
+    delete [] r_write_be;
+    delete [] r_write_to_init_cmd_data;
+  }
+
+  //////////////////////////////////
+  tmpl(void)::transition()
+    //////////////////////////////////
+  {
+    using soclib::common::uint32_log2;
+    //  RESET          
+    if ( ! p_resetn.read() ) {
+
+      //     Initializing FSMs
+      r_tgt_cmd_fsm 	= TGT_CMD_IDLE;
+      r_tgt_rsp_fsm 	= TGT_RSP_READ_IDLE;
+      r_init_cmd_fsm 	= INIT_CMD_INVAL_IDLE;
+      r_init_rsp_fsm 	= INIT_RSP_IDLE;
+      r_read_fsm 	= READ_IDLE;
+      r_write_fsm 	= WRITE_IDLE;
+      r_llsc_fsm 	= LLSC_IDLE;
+      r_cleanup_fsm 	= CLEANUP_IDLE;
+      r_alloc_dir_fsm = ALLOC_DIR_READ;
+      r_alloc_trt_fsm = ALLOC_TRT_READ;
+      r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+      r_ixr_rsp_fsm 	= IXR_RSP_IDLE;
+      r_xram_rsp_fsm 	= XRAM_RSP_IDLE;
+      r_xram_cmd_fsm 	= XRAM_CMD_READ_IDLE;
+
+      //  Initializing Tables
+      m_cache_directory.init();
+      m_atomic_tab.init();	
+      m_transaction_tab.init();
+
+      // initializing FIFOs and communication Buffers
+
+      m_cmd_read_addr_fifo.init();
+      m_cmd_read_word_fifo.init();
+      m_cmd_read_srcid_fifo.init();
+      m_cmd_read_trdid_fifo.init();
+      m_cmd_read_pktid_fifo.init();
+
+      m_cmd_write_addr_fifo.init();
+      m_cmd_write_eop_fifo.init();
+      m_cmd_write_srcid_fifo.init();
+      m_cmd_write_trdid_fifo.init();
+      m_cmd_write_pktid_fifo.init();
+      m_cmd_write_data_fifo.init();
+
+      m_cmd_llsc_addr_fifo.init();
+      m_cmd_llsc_srcid_fifo.init();
+      m_cmd_llsc_trdid_fifo.init();
+      m_cmd_llsc_pktid_fifo.init();
+      m_cmd_llsc_wdata_fifo.init();
+      m_cmd_llsc_sc_fifo.init();
+
+      m_cmd_cleanup_srcid_fifo.init();
+      m_cmd_cleanup_trdid_fifo.init();
+      m_cmd_cleanup_pktid_fifo.init();
+      m_cmd_cleanup_nline_fifo.init();
+
+      r_read_to_tgt_rsp_req		= false;
+      r_read_to_xram_cmd_req		= false;
+
+      r_write_to_tgt_rsp_req		= false;
+      r_write_to_xram_cmd_req		= false;
+      r_write_to_init_cmd_req		= false;
+
+      r_init_rsp_to_tgt_rsp_req	= false;
+
+      r_cleanup_to_tgt_rsp_req	= false;
+
+      r_llsc_to_tgt_rsp_req		= false;
+      r_llsc_to_xram_cmd_req		= false;
+
+      for(size_t i=0; i<TRANSACTION_TAB_LINES ; i++){
+        r_ixr_rsp_to_xram_rsp_rok[i]= false;
+      }
+
+      r_xram_rsp_to_tgt_rsp_req	= false;
+      r_xram_rsp_to_init_cmd_req	= false;
+      r_xram_rsp_to_xram_cmd_req	= false;
+      r_xram_rsp_trt_index		= 0;
+
+      r_xram_cmd_cpt = 0;
+
+      // Activity counters
+      m_cpt_cycles		= 0;
+      m_cpt_read		= 0;
+      m_cpt_read_miss		= 0;
+      m_cpt_write		= 0;
+      m_cpt_write_miss	= 0;
+      m_cpt_write_cells	= 0;
+      m_cpt_write_dirty	= 0;
+      m_cpt_update		= 0;
+      m_cpt_update_mult 	= 0;
+      m_cpt_inval 		= 0;
+      m_cpt_inval_mult 	= 0;
+      m_cpt_cleanup		= 0;
+      m_cpt_ll     		= 0;
+      m_cpt_sc     		= 0;
+
+      return;
+    }
+
+    bool    cmd_read_fifo_put = false;
+    bool    cmd_read_fifo_get = false;
+
+    bool    cmd_write_fifo_put = false;
+    bool    cmd_write_fifo_get = false;
+
+    bool    cmd_llsc_fifo_put = false;
+    bool    cmd_llsc_fifo_get = false;
+
+    bool    cmd_cleanup_fifo_put = false;
+    bool    cmd_cleanup_fifo_get = false;
+
+#if DEBUG_VCI_MEM_CACHE 
+    std::cout << "---------------------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
+      << " - TGT_CMD FSM   = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
+      << " - TGT_RSP FSM   = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
+      << " - INIT_CMD FSM  = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
+      << " - INIT_RSP FSM  = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
+      << " - READ FSM      = " << read_fsm_str[r_read_fsm] << std::endl
+      << " - WRITE FSM     = " << write_fsm_str[r_write_fsm] << std::endl
+      << " - LLSC FSM      = " << llsc_fsm_str[r_llsc_fsm] << std::endl
+      << " - CLEANUP FSM   = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
+      << " - XRAM_CMD FSM  = " << xram_cmd_fsm_str[r_xram_cmd_fsm] << std::endl
+      << " - IXR_RSP FSM   = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
+      << " - XRAM_RSP FSM  = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
+      << " - ALLOC_DIR FSM = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
+      << " - ALLOC_TRT FSM = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
+      << " - ALLOC_UPT FSM = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl;
+#endif
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
+    //
+    // There is 4 types of packets for the m_mem_segment :
+    // - READ    : a READ request has a length of 1 VCI cell. It can be a single word 
+    //             or an entire cache line, depending on the PLEN value.
+    // - WRITE   : a WRITE request has a maximum length of 16 cells, and can only
+    //             concern words in a same line.
+    // - LL      : The LL request has a length of 1 cell.
+    // - SC      : The SC request has a length of 1 cell. 
+    //             The WDATA field contains the data to write.
+    //
+    // There is one type of packet for the m_reg_segment :
+    // - CLEANUP : it is a one cell VCI packet. The VCI CMD field is WRITE, and the
+    //             WDATA field contains the cache line number (z & y).
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_cmd_fsm.read() ) {
+
+      //////////////////
+      case TGT_CMD_IDLE:
+        {
+          if ( p_vci_tgt.cmdval ) {
+            assert( (p_vci_tgt.srcid.read() < m_initiators)
+                && "error in VCI_MEM_CACHE : The received SRCID is larger than 31");
+
+            bool reached = false;
+            for ( size_t index = 0 ; index < nseg && !reached ; index++) 
+            {
+              if ( m_seg[index]->contains(p_vci_tgt.address.read()) ) {
+                reached = true;
+                r_index = index;
+              }
+            }
+
+            if ( !reached ) 
+            { 
+              std::cout << "Out of segment access in VCI_MEM_CACHE" << std::endl;
+              std::cout << "Faulty address = " << p_vci_tgt.address.read() << std::endl;
+              std::cout << "Faulty initiator = " << p_vci_tgt.srcid.read() << std::endl;
+              exit(0);
+            } 
+            else if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_READ;
+            } 
+            else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ) && ( p_vci_tgt.trdid.read() == 0x0 ) )
+            {  
+              r_tgt_cmd_fsm = TGT_CMD_WRITE;
+            } 
+            else if ((p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ) || 
+                (p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND) ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
+            } 
+            else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ) && ( p_vci_tgt.trdid.read() == 0x1 ))
+            {  
+              r_tgt_cmd_fsm = TGT_CMD_CLEANUP;
+            } 
+          }
+          break;
+        }
+        //////////////////
+      case TGT_CMD_READ:
+        {
+          assert(((p_vci_tgt.plen.read() == 4) || (p_vci_tgt.plen.read() == m_words*4))
+              && "All read request to the MemCache must have PLEN = 4 or PLEN = 4*nwords"); 
+
+          if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) {
+            cmd_read_fifo_put = true;
+            if ( p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+            else                  r_tgt_cmd_fsm = TGT_CMD_READ_EOP;		
+          } 
+          break;
+        }
+        //////////////////////
+      case TGT_CMD_READ_EOP:
+        {
+          if ( p_vci_tgt.cmdval && p_vci_tgt.eop ){
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_CMD_WRITE:
+        {
+          if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() ) {
+            cmd_write_fifo_put = true;
+            if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+        ////////////////////
+      case TGT_CMD_ATOMIC:
+        {
+          assert(p_vci_tgt.eop && "Memory Cache Error: LL or SC command with length > 1 ");
+
+          if ( p_vci_tgt.cmdval && m_cmd_llsc_addr_fifo.wok() ) {
+            cmd_llsc_fifo_put = true;
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+        /////////////////////
+      case TGT_CMD_CLEANUP:
+        {
+          assert(p_vci_tgt.eop && "Memory Cache Error: CLEANUP request with length > 1 ");
+
+          if ( p_vci_tgt.cmdval && m_cmd_cleanup_nline_fifo.wok() ) {
+            cmd_cleanup_fifo_put = true;
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+    } // end switch tgt_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////////
+    //		INIT_RSP FSM
+    /////////////////////////////////////////////////////////////////////////
+    // This FSM controls the response to the update or invalidate requests
+    // sent by the memory cache to the L1 caches :
+    //
+    // - update request initiated by the WRITE FSM.  
+    //   The FSM decrements the proper entry in the Update/Inval Table.
+    //   It sends a request to the TGT_RSP FSM to complete the pending 
+    //   write transaction (acknowledge response to the writer processor), 
+    //   and clear the UPT entry when all responses have been received.  
+    // - invalidate request initiated by the XRAM_RSP FSM.
+    //   The FSM decrements the proper entry in the Update/Inval_Table,
+    //   and clear the entry when all responses have been received.
+    //
+    // All those response packets are one word, compact
+    // packets complying with the VCI advanced format. 
+    // The index in the Table is defined in the RTRDID field, and
+    // the Transaction type is defined in the Update/Inval Table.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_rsp_fsm.read() ) {
+
+      ///////////////////
+      case INIT_RSP_IDLE:
+        {
+          if ( p_vci_ini.rspval ) {
+            assert ( ( p_vci_ini.rtrdid.read() < m_update_tab.size() )
+                && "UPT index too large in VCI response paquet received by memory cache" );
+            assert ( p_vci_ini.reop 
+                && "All response packets to update/invalidate requests must be one cell" );
+            r_init_rsp_upt_index = p_vci_ini.rtrdid.read(); 
+            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_RSP_UPT_LOCK:	// decrement the number of expected responses
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) { 
+            size_t count = 0;
+            bool valid  = m_update_tab.decrement(r_init_rsp_upt_index.read(), count); 
+            assert ( valid 
+                && "Invalid UPT entry in VCI response paquet received by memory cache" );
+            if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
+            else              r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_RSP_UPT_CLEAR:	// clear the UPT entry
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) { 
+            r_init_rsp_srcid = m_update_tab.srcid(r_init_rsp_upt_index.read());
+            r_init_rsp_trdid = m_update_tab.trdid(r_init_rsp_upt_index.read());
+            r_init_rsp_pktid = m_update_tab.pktid(r_init_rsp_upt_index.read());
+            bool update = m_update_tab.is_update(r_init_rsp_upt_index.read());
+            if ( update ) r_init_rsp_fsm = INIT_RSP_END;
+            else          r_init_rsp_fsm = INIT_RSP_IDLE;
+            m_update_tab.clear(r_init_rsp_upt_index.read());
+          }
+          break;
+        }
+        //////////////////
+      case INIT_RSP_END:
+        {
+          if ( !r_init_rsp_to_tgt_rsp_req ) {
+            r_init_rsp_to_tgt_rsp_req = true;
+            r_init_rsp_to_tgt_rsp_srcid = r_init_rsp_srcid.read();
+            r_init_rsp_to_tgt_rsp_trdid = r_init_rsp_trdid.read();
+            r_init_rsp_to_tgt_rsp_pktid = r_init_rsp_pktid.read();
+            r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+    } // end switch r_init_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		READ FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The READ FSM controls the read requests sent by processors.
+    // It takes the lock protecting the cache directory to check the cache line status:
+    // - In case of HIT, the fsm copies the data (one line, or one single word)
+    //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
+    //   The requesting initiator is registered in the cache directory.
+    // - In case of MISS, the READ fsm takes the lock protecting the transaction tab.
+    //   If a read transaction to the XRAM for this line already exists,
+    //   or if the transaction tab is full, the fsm is stalled.
+    //   If a transaction entry is free, the READ fsm sends a request to the XRAM.
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_read_fsm.read() ) {
+
+      ///////////////
+      case READ_IDLE:
+        {
+          if (m_cmd_read_addr_fifo.rok()) {
+            m_cpt_read++;
+            r_read_fsm = READ_DIR_LOCK;
+          }
+          break;
+        }
+        ///////////////////
+      case READ_DIR_LOCK:	// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            size_t way = 0;
+            DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
+
+            r_read_dirty	= entry.dirty;
+            r_read_tag	= entry.tag;
+            r_read_lock	= entry.lock;
+            r_read_way	= way;
+            r_read_word	= m_cmd_read_word_fifo.read();
+            r_read_copies = entry.copies | (0x1 << m_cmd_read_srcid_fifo.read());
+
+            // In case of hit, the read acces must be registered in the copies bit-vector
+            // for both a cache line read & a single word read (TLB coherence)
+
+            if( entry.valid )  { 
+              r_read_fsm = READ_DIR_HIT;
+            } else {
+              r_read_fsm = READ_TRT_LOCK;
+              m_cpt_read_miss++;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_DIR_HIT:	// read hit : update the memory cache
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+
+            // read data in the cache
+            size_t set = m_y[m_cmd_read_addr_fifo.read()];
+            size_t way = r_read_way.read();
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_data[i] = m_cache_data[way][set][i];
+            }
+
+            // update the cache directory (for the copies)
+            DirectoryEntry entry;
+            entry.valid	= true;
+            entry.dirty	= r_read_dirty.read();
+            entry.tag	= r_read_tag.read();
+            entry.lock	= r_read_lock.read();
+            entry.copies  = r_read_copies.read();
+            m_cache_directory.write(set, way, entry);
+            r_read_fsm    = READ_RSP;
+          }
+          break;
+        }
+        //////////////
+      case READ_RSP: 		//  request the TGT_RSP FSM to return data
+        {
+          if( !r_read_to_tgt_rsp_req ) {	
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_to_tgt_rsp_data[i] = r_read_data[i];
+              if ( r_read_word ) {	// single word
+                r_read_to_tgt_rsp_val[i] = (i == m_x[m_cmd_read_addr_fifo.read()]);
+              } else {			// cache line
+                r_read_to_tgt_rsp_val[i] = true;
+              }
+            }
+            cmd_read_fifo_get 		= true;
+            r_read_to_tgt_rsp_req		= true;
+            r_read_to_tgt_rsp_srcid	= m_cmd_read_srcid_fifo.read();
+            r_read_to_tgt_rsp_trdid	= m_cmd_read_trdid_fifo.read();
+            r_read_to_tgt_rsp_pktid	= m_cmd_read_pktid_fifo.read();
+            r_read_fsm 			= READ_IDLE;  
+          }
+          break;
+        }
+        ///////////////////
+      case READ_TRT_LOCK:	// read miss : check the Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+            size_t index = 0;
+            bool   hit = m_transaction_tab.hit_read(m_nline[m_cmd_read_addr_fifo.read()], index);
+            bool   wok = !m_transaction_tab.full(index);
+            if( hit || !wok ) {  // missing line already requested or no space
+              r_read_fsm = READ_IDLE;
+            } else {			   // missing line is requested to the XRAM
+              r_read_trt_index = index;
+              r_read_fsm       = READ_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_TRT_SET:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+            m_transaction_tab.set(r_read_trt_index.read(),
+                true,
+                m_nline[m_cmd_read_addr_fifo.read()],
+                m_cmd_read_srcid_fifo.read(),
+                m_cmd_read_trdid_fifo.read(),
+                m_cmd_read_pktid_fifo.read(),
+                true,
+                m_cmd_read_word_fifo.read(),
+                m_x[m_cmd_read_addr_fifo.read()],
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+            r_read_fsm 	 = READ_XRAM_REQ;
+          }
+          break;
+        }
+        /////////////////////
+      case READ_XRAM_REQ:
+        {
+          if( !r_read_to_xram_cmd_req ) {
+            cmd_read_fifo_get		= true;
+            r_read_to_xram_cmd_req  	= true;
+            r_read_to_xram_cmd_nline 	= m_nline[m_cmd_read_addr_fifo.read()];
+            r_read_to_xram_cmd_trdid 	= r_read_trt_index.read();
+            r_read_fsm 			= READ_IDLE;
+          }
+          break;
+        }
+    } // end switch read_fsm
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //		WRITE FSM
+    ///////////////////////////////////////////////////////////////////////////////////
+    // The WRITE FSM handles the write bursts 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.
+    // Then the FSM takes the lock protecting the cache directory, to check
+    // if the line is in the cache.
+    //
+    // - In case of HIT, the cache is updated.
+    //   If there is no other copy, an acknowledge response is immediately
+    //   returned to the writing processor.
+    //   if the data is cached by other processoris, the FSM takes the lock
+    //   protecting the Update Table (UPT) to register this update transaction.
+    //   If the UPT is full, it releases the lock  and waits. Then, it sends 
+    //   a multi-update request to all owners of the line (but the writer), 
+    //   through the INIT_CMD FSM. In case of multi-update transaction, the WRITE FSM 
+    //   does not respond to the writing processor, as this response will be sent by 
+    //   the INIT_RSP FSM when all update responses have been received.
+    //
+    // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
+    //   table (TRT). If a read transaction to the XRAM for this line already exists, 
+    //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free, 
+    //   the WRITE FSM register a new transaction in TRT, and sends a read line request 
+    //   to the XRAM. If the TRT is full, it releases the lock, and waits.
+    //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_write_fsm.read() ) {
+
+      ////////////////
+      case WRITE_IDLE:	// copy first word of a write burst in local buffer	
+        {
+          if ( m_cmd_write_addr_fifo.rok()) {
+            m_cpt_write++;
+            m_cpt_write_cells++;
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get	= true;
+            size_t index 		= m_x[m_cmd_write_addr_fifo.read()];
+            r_write_address	= m_cmd_write_addr_fifo.read();
+            r_write_word_index	= index;
+            r_write_word_count	= 1;
+            r_write_data[index]	= m_cmd_write_data_fifo.read();
+            r_write_srcid		= m_cmd_write_srcid_fifo.read();
+            r_write_trdid		= m_cmd_write_trdid_fifo.read();
+            r_write_pktid		= m_cmd_write_pktid_fifo.read();
+
+            // the be field must be set for all words 
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              if ( i == index ) 	r_write_be[i] = m_cmd_write_be_fifo.read();
+              else		r_write_be[i] = 0x0;
+            }
+            if( !((m_cmd_write_be_fifo.read()==0x0)||(m_cmd_write_be_fifo.read()==0xF)) )
+              r_write_byte=true;
+            else  r_write_byte=false;
+
+            if( m_cmd_write_eop_fifo.read() )
+            {  
+              r_write_fsm = WRITE_DIR_LOCK;
+            }
+            else
+            {
+              r_write_fsm = WRITE_NEXT;
+            }
+          }
+          break;
+        }
+        ////////////////
+      case WRITE_NEXT:	// copy next word of a write burst in local buffer
+        {
+          if ( m_cmd_write_addr_fifo.rok() ) {
+            m_cpt_write_cells++;
+
+            // check that the next word is in the same cache line
+            assert( (m_nline[r_write_address.read()] == m_nline[m_cmd_write_addr_fifo.read()])  
+                && "write error in vci_mem_cache : write burst over a line" );
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get=true;
+            size_t index 		= r_write_word_index.read() + r_write_word_count.read();
+            r_write_be[index]   	= m_cmd_write_be_fifo.read();
+            r_write_data[index] 	= m_cmd_write_data_fifo.read();
+            r_write_word_count 	= r_write_word_count.read() + 1;
+            if( !((m_cmd_write_be_fifo.read()==0x0)||(m_cmd_write_be_fifo.read()==0xF)) )
+              r_write_byte=true;
+            if ( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_LOCK:	// access directory to check hit/miss
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ) {
+            size_t  way = 0;
+            DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
+
+            // copy directory entry in local buffers in case of hit
+            if ( entry.valid )  {	
+              r_write_lock	= entry.lock;
+              r_write_tag         = entry.tag;
+              r_write_copies      = entry.copies;
+              r_write_way  	= way;
+              if(r_write_byte.read())
+                r_write_fsm         = WRITE_DIR_HIT_READ;
+              else  r_write_fsm         = WRITE_DIR_HIT;
+            } else {
+              r_write_fsm		= WRITE_TRT_LOCK;
+              m_cpt_write_miss++;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_READ:	// read the cache and complete the buffer (data, when be!=0xF)
+        {			
+          // update local buffer
+          size_t set	= m_y[r_write_address.read()];
+          size_t way	= r_write_way.read();
+          for(size_t i=0 ; i<m_words ; i++) {
+            data_t mask      = 0;
+            if  (r_write_be[i].read() & 0x1) mask = mask | 0x000000FF;
+            if  (r_write_be[i].read() & 0x2) mask = mask | 0x0000FF00;
+            if  (r_write_be[i].read() & 0x4) mask = mask | 0x00FF0000;
+            if  (r_write_be[i].read() & 0x8) mask = mask | 0xFF000000;
+            if(r_write_be[i].read()) { // complete only if mask is not null (for energy consumption)
+              r_write_data[i]  = (r_write_data[i].read() & mask) | 
+                (m_cache_data[way][set][i] & ~mask);
+              r_write_be[i]=0xF;
+            }
+          } // end for
+
+          r_write_fsm            = WRITE_DIR_HIT;
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT:	// update the cache (data & dirty bit)
+        {			
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.dirty	= true;
+          entry.tag	= r_write_tag.read();
+          entry.lock	= r_write_lock.read();
+          entry.copies    = r_write_copies.read();
+          size_t set	= m_y[r_write_address.read()];
+          size_t way	= r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          // write data in cache
+          for(size_t i=0 ; i<m_words ; i++) {
+            if  ( r_write_be[i].read() ) {
+              m_cache_data[way][set][i]  = r_write_data[i].read();
+            }
+          } // end for
+
+          // compute the actual number of copies & the modified bit vector
+          size_t	n	= 0;
+          copy_t  mask    = 0x1;
+          copy_t  copies  = r_write_copies.read();
+          for ( size_t i=0 ; i<32 ; i++) {
+            if ( i != r_write_srcid.read() ) {
+              if ( copies & mask ) n++;
+            } else {
+              copies = copies &  ~mask;
+            }
+            mask = (mask << 1);
+          }
+          r_write_nb_copies = n;
+          r_write_copies    = copies;
+
+          if ( n == 0 )   r_write_fsm = WRITE_RSP;
+          else  		r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        /////////////////////
+      case WRITE_UPT_LOCK: 	// Try to register the request in Update Table
+        {			
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool          wok=false;
+            size_t	index=0;
+            size_t        srcid=r_write_srcid.read();
+            size_t        trdid=r_write_trdid.read();
+            size_t        pktid=r_write_pktid.read();
+            size_t        nb_copies=r_write_nb_copies.read();
+            wok                =m_update_tab.set(true,	// it's an update transaction
+                srcid,
+                trdid,
+                pktid,
+                nb_copies,
+                index);
+            r_write_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_write_fsm = WRITE_UPDATE;
+            else       r_write_fsm = WRITE_WAIT_UPT;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT_UPT:	// release the lock protecting UPT
+        {
+          r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        //////////////////
+      case WRITE_UPDATE:	// send a multi-update request to INIT_CMD fsm
+        {
+          if ( !r_write_to_init_cmd_req ) {
+            r_write_to_init_cmd_req    = true;
+            r_write_to_init_cmd_trdid  = r_write_upt_index.read();
+            r_write_to_init_cmd_nline  = m_nline[r_write_address.read()];
+            r_write_to_init_cmd_index  = r_write_word_index.read();
+            r_write_to_init_cmd_count  = r_write_word_count.read();
+            r_write_to_init_cmd_copies = r_write_copies;
+
+            for(size_t i=0; i<m_words ; i++){
+              assert( ((r_write_be[i].read()==0xF)||(r_write_be[i].read()==0x0)) &&
+                  "write error in vci_mem_cache : invalid BE");
+              if(r_write_be[i].read())  r_write_to_init_cmd_we[i]=true;
+              else                      r_write_to_init_cmd_we[i]=false;
+            }
+
+            size_t min = r_write_word_index.read();
+            size_t max = r_write_word_index.read() + r_write_word_count.read();
+            for (size_t i=min ; i<max ; i++) {
+              r_write_to_init_cmd_data[i] = r_write_data[i];
+            }
+            r_write_fsm = WRITE_IDLE;
+          }
+          break;
+        }
+        ///////////////
+      case WRITE_RSP:		// send a request to TGT_RSP FSM to acknowledge the write
+        {
+          if ( !r_write_to_tgt_rsp_req ) {
+            r_write_to_tgt_rsp_req	= true;
+            r_write_to_tgt_rsp_srcid	= r_write_srcid;
+            r_write_to_tgt_rsp_trdid	= r_write_trdid;
+            r_write_to_tgt_rsp_pktid	= r_write_pktid;
+            r_write_fsm 			= WRITE_IDLE;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_LOCK:	// Miss : check Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            size_t hit_index = 0;
+            size_t wok_index = 0;
+            bool hit = m_transaction_tab.hit_read(m_nline[r_write_address.read()],hit_index);
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( hit ) {		// register the modified data in TRT 
+              r_write_trt_index = hit_index;
+              r_write_fsm       = WRITE_TRT_DATA;
+            } else if ( wok ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_TRT_SET;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT_TRT;
+            }
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT_TRT:	// release the lock protecting TRT
+        {  
+          r_write_fsm = WRITE_DIR_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_TRT_SET:	// register a new transaction in TRT (Write Buffer)
+        {  
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.set(r_write_trt_index.read(),
+                true,				// read request to XRAM
+                m_nline[r_write_address.read()],
+                r_write_srcid.read(),
+                r_write_trdid.read(),
+                r_write_pktid.read(),
+                false,				// not a processor read
+                false,				// not a single word 
+                0,				// word index
+                be_vector,
+                data_vector);
+            r_write_fsm = WRITE_XRAM_REQ;
+          }
+          break;
+        }  
+        ///////////////////
+      case WRITE_TRT_DATA:	// update an entry in TRT (Write Buffer)
+        {  
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.write_data_mask(r_write_trt_index.read(),
+                be_vector,
+                data_vector);
+            r_write_fsm = WRITE_RSP;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_REQ:	// send a request to XRAM_CMD FSM
+        {  
+          if ( !r_write_to_xram_cmd_req ) {
+            r_write_to_xram_cmd_req     = true;
+            r_write_to_xram_cmd_nline   = m_nline[r_write_address.read()];
+            r_write_to_xram_cmd_trdid   = r_write_trt_index.read();
+            r_write_fsm                 = WRITE_RSP;
+          }
+          break;
+        }
+    } // end switch r_write_fsm
+
+    ///////////////////////////////////////////////////////////////////////
+    //		XRAM_CMD FSM
+    ///////////////////////////////////////////////////////////////////////
+    // The XRAM_CMD fsm controls the command packets to the XRAM :
+    // - It sends a single cell VCI write in case of MISS request
+    // posted by the READ, WRITE or LLSC FSMs : the WDATA field
+    // contains the cache line index and the TRDID fiels contains 
+    // the Transaction Tab index.
+    // The VCI response is a multi-cell packet : the N cells contain
+    // the N data words.
+    // - It sends a multi-cell VCI write when the XRAM_RSP FSM request 
+    // to save a dirty line to the XRAM : The first cell contain the
+    // cache line index, the following cells contain the data.
+    // The VCI response is a single cell packet.
+    // This FSM handles requests from the READ, WRITE, LLSC & XRAM_RSP FSMs 
+    // with a round-robin priority.
+    ////////////////////////////////////////////////////////////////////////
+
+    switch ( r_xram_cmd_fsm.read() ) {
+
+      //////////////////////// 
+      case XRAM_CMD_READ_IDLE:
+        if      ( r_write_to_xram_cmd_req )     r_xram_cmd_fsm = XRAM_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_xram_cmd_req  )     r_xram_cmd_fsm = XRAM_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_xram_cmd_req  ) r_xram_cmd_fsm = XRAM_CMD_XRAM_DATA;
+        else if ( r_read_to_xram_cmd_req  )     r_xram_cmd_fsm = XRAM_CMD_READ_NLINE;
+        break;
+        //////////////////////// 
+      case XRAM_CMD_WRITE_IDLE:
+        if      ( r_llsc_to_xram_cmd_req  )     r_xram_cmd_fsm = XRAM_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_xram_cmd_req  ) r_xram_cmd_fsm = XRAM_CMD_XRAM_DATA;
+        else if ( r_read_to_xram_cmd_req  )     r_xram_cmd_fsm = XRAM_CMD_READ_NLINE;
+        else if ( r_write_to_xram_cmd_req )     r_xram_cmd_fsm = XRAM_CMD_WRITE_NLINE;
+        break;
+        //////////////////////// 
+      case XRAM_CMD_LLSC_IDLE:
+        if      ( r_xram_rsp_to_xram_cmd_req  ) r_xram_cmd_fsm = XRAM_CMD_XRAM_DATA;
+        else if ( r_read_to_xram_cmd_req  )     r_xram_cmd_fsm = XRAM_CMD_READ_NLINE;
+        else if ( r_write_to_xram_cmd_req )     r_xram_cmd_fsm = XRAM_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_xram_cmd_req  )     r_xram_cmd_fsm = XRAM_CMD_LLSC_NLINE;
+        break;
+        //////////////////////// 
+      case XRAM_CMD_XRAM_IDLE:
+        if      ( r_read_to_xram_cmd_req  )     r_xram_cmd_fsm = XRAM_CMD_READ_NLINE;
+        else if ( r_write_to_xram_cmd_req )     r_xram_cmd_fsm = XRAM_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_xram_cmd_req  )     r_xram_cmd_fsm = XRAM_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_xram_cmd_req  ) r_xram_cmd_fsm = XRAM_CMD_XRAM_DATA;
+        break;
+        /////////////////////////
+      case XRAM_CMD_READ_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          r_xram_cmd_fsm = XRAM_CMD_READ_IDLE;		
+          r_read_to_xram_cmd_req = false;
+        }
+        break;
+        //////////////////////////
+      case XRAM_CMD_WRITE_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          r_xram_cmd_fsm = XRAM_CMD_WRITE_IDLE;		
+          r_write_to_xram_cmd_req = false;
+        }
+        break;
+        /////////////////////////
+      case XRAM_CMD_LLSC_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          r_xram_cmd_fsm = XRAM_CMD_LLSC_IDLE;		
+          r_llsc_to_xram_cmd_req = false;
+        }
+        break;
+        ////////////////////////
+      case XRAM_CMD_XRAM_DATA:
+        if ( p_vci_ixr.cmdack ) {
+          if ( r_xram_cmd_cpt.read() == (m_words - 1) ) {
+            r_xram_cmd_cpt = 0;
+            r_xram_cmd_fsm = XRAM_CMD_XRAM_IDLE;
+            r_xram_rsp_to_xram_cmd_req = false;
+          } else {
+            r_xram_cmd_cpt = r_xram_cmd_cpt + 1;
+          }
+        }
+        break;
+
+    } // end switch r_xram_cmd_fsm
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                IXR_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The IXR_RSP FSM receives the response packets from the XRAM,
+    // for both write transaction, and read transaction.
+    //
+    // - A response to a write request is a single-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The FSM takes the lock protecting the TRT, and the corresponding
+    // entry is erased.
+    //	
+    // - A response to a read request is a multi-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The N cells contain the N words of the cache line in the RDATA field.
+    // The FSM takes the lock protecting the TRT to store the line in the TRT
+    // (taking into account the write requests already stored in the TRT).
+    // When the line is completely written, the corresponding rok signal is set.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_rsp_fsm.read() ) {
+
+      ///////////////////
+      case IXR_RSP_IDLE:	// test if it's a read or a write transaction
+        {
+          if ( p_vci_ixr.rspval ) {
+            r_ixr_rsp_cpt   = 0;
+            r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
+            if ( p_vci_ixr.reop )  r_ixr_rsp_fsm = IXR_RSP_ACK;
+            else                   r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
+          }
+          break;  
+        }
+        ////////////////////////
+      case IXR_RSP_ACK:        // Acknowledge the vci response
+        r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
+        break;
+        ////////////////////////
+      case IXR_RSP_TRT_ERASE: 	// erase the entry in the TRT
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP ) {
+            m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
+            r_ixr_rsp_fsm = IXR_RSP_IDLE;
+          }
+          break;
+        }
+        ///////////////////////
+      case IXR_RSP_TRT_READ:		// write data in the TRT
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval ) {
+            bool   eop  	= p_vci_ixr.reop.read();
+            data_t data 	= p_vci_ixr.rdata.read();
+            size_t index        = r_ixr_rsp_trt_index.read();
+            assert( eop == (r_ixr_rsp_cpt.read() == (m_words-1)) 
+                && "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
+            m_transaction_tab.write_rsp(index, r_ixr_rsp_cpt.read(), data);
+            r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
+            if ( eop ) {
+              r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
+              r_ixr_rsp_fsm = IXR_RSP_IDLE;
+            }
+          }
+          break;
+        }
+    } // end swich r_ixr_rsp_fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                XRAM_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The XRAM_RSP FSM handles the response packets from the XRAM,
+    // for read transactions.
+    //
+    // When a response is available, the corresponding TRT entry 
+    // is copied in a local buffer to be written in the cache. 
+    // Then, the FSM releases the lock protecting the TRT, and takes the lock 
+    // protecting the cache directory.
+    // It selects a cache slot and writes the line in the cache.
+    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
+    // FSM to return the cache line to the registered processor.
+    // If there is no empty slot, a victim line is evicted, and
+    // invalidate requests are sent to the L1 caches containing copies.
+    // If this line is dirty, the XRAM_RSP FSM send a request to the XRAM_CMD 
+    // FSM to save the victim line to the XRAM, and register the write transaction
+    // in the TRT (using the entry previously used by the read transaction).
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_xram_rsp_fsm.read() ) {
+
+      ///////////////////
+      case XRAM_RSP_IDLE:	// test if there is a response with a round robin priority
+        {
+          size_t ptr   = r_xram_rsp_trt_index.read();
+          size_t lines = TRANSACTION_TAB_LINES;
+          for(size_t i=0; i<lines; i++){
+            size_t index=(i+ptr+1)%lines;
+            if(r_ixr_rsp_to_xram_rsp_rok[index]){
+              r_xram_rsp_trt_index=index;
+              r_ixr_rsp_to_xram_rsp_rok[index]=false;
+              r_xram_rsp_fsm           = XRAM_RSP_DIR_LOCK;
+              break;
+            }
+          }
+          break;  
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_LOCK: 	// Take the lock on the directory
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) {
+            r_xram_rsp_fsm           = XRAM_RSP_TRT_COPY;
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_TRT_COPY:		// Copy the TRT entry in the local buffer and eviction of a cache line
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) ) {
+            size_t index = r_xram_rsp_trt_index.read();
+            TransactionTabEntry    trt_entry(m_transaction_tab.read(index));	
+
+            r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
+
+            // selects & extracts a victim line from cache
+            size_t way = 0;
+            size_t set = m_y[trt_entry.nline * m_words * 4];
+            DirectoryEntry victim(m_cache_directory.select(set, way));
+
+            for (size_t i=0 ; i<m_words ; i++) r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
+
+            r_xram_rsp_victim_copies = victim.copies;
+            r_xram_rsp_victim_way    = way;
+            r_xram_rsp_victim_set    = set;
+            r_xram_rsp_victim_nline  = victim.tag*m_sets + set;
+            r_xram_rsp_victim_inval  = victim.valid && (victim.copies != 0);
+            r_xram_rsp_victim_dirty  = victim.dirty;
+
+            r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_UPDT:		// updates the cache (both data & directory)
+        {
+          // update data
+          size_t set   = r_xram_rsp_victim_set.read();
+          size_t way   = r_xram_rsp_victim_way.read();
+          for(size_t i=0; i<m_words ; i++){
+            m_cache_data[way][set][i] = r_xram_rsp_trt_buf.wdata[i];
+          }
+          // update directory
+          bool dirty = false;
+          for(size_t i=0; i<m_words;i++){
+            dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
+          }
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.lock	= false;
+          entry.dirty	= dirty;
+          entry.tag	= r_xram_rsp_trt_buf.nline / m_sets;
+          if(r_xram_rsp_trt_buf.proc_read) {
+            entry.copies    = 0x1 << r_xram_rsp_trt_buf.srcid;
+          } else {
+            entry.copies    = 0;
+          }
+          m_cache_directory.write(set, way, entry);
+          // If the victim is not dirty, we erase the entry in the TRT
+          if      (!r_xram_rsp_victim_dirty.read()) m_transaction_tab.erase(r_xram_rsp_trt_index.read());
+          // Next state
+          if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
+          else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+          else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_UPT_LOCK;
+          else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          break;
+        }
+        ////////////////////////
+      case XRAM_RSP_TRT_DIRTY:		// set the TRT entry (write line to XRAM) if the victim is dirty
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP ) {
+            m_transaction_tab.set(r_xram_rsp_trt_index.read(),
+                false,				// write to XRAM
+                r_xram_rsp_victim_nline.read(), // line index
+                0,
+                0,
+                0,
+                false,
+                false,
+                0,
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0) );
+            if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_UPT_LOCK;
+            else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+          }
+          break;
+        }
+        //////////////////////
+      case XRAM_RSP_DIR_RSP:     // send a request to TGT_RSP FSM in case of read
+        {
+          if ( !r_xram_rsp_to_tgt_rsp_req ) {
+            r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
+            r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
+            r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
+            for (size_t i=0; i < m_words; i++) {
+              r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
+              if( r_xram_rsp_trt_buf.single_word ) {
+                r_xram_rsp_to_tgt_rsp_val[i] = (r_xram_rsp_trt_buf.word_index == i);
+              } else {
+                r_xram_rsp_to_tgt_rsp_val[i] = true;
+              }
+            } 
+            r_xram_rsp_to_tgt_rsp_req   = true;
+            if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_UPT_LOCK;
+            else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY; 
+            else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_UPT_LOCK:	// Try to register the inval transaction in UPT
+        {
+          if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP ) {
+            size_t index;
+            copy_t  copies  = r_xram_rsp_victim_copies.read();
+            copy_t  mask = 0x1;
+            size_t n=0;
+            for ( size_t i=0 ; i<32 ; i++) {
+              if ( copies & mask ) n++;
+              mask = (mask << 1);
+            }
+            bool	 wok = m_update_tab.set(false,	// it's an inval transaction
+                0,
+                0,
+                0,
+                n,
+                index);
+            if ( wok ) {
+              r_xram_rsp_upt_index = index;
+              r_xram_rsp_fsm       = XRAM_RSP_INVAL;
+            } else {
+              r_xram_rsp_fsm       = XRAM_RSP_WAIT;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case XRAM_RSP_WAIT:	// releases UPT lock for one cycle
+        {
+          r_xram_rsp_fsm = XRAM_RSP_UPT_LOCK;
+        }
+        ////////////////////
+      case XRAM_RSP_INVAL:	// send invalidate request to INIT_CMD FSM
+        {
+          if( !r_xram_rsp_to_init_cmd_req ) {	      
+            r_xram_rsp_to_init_cmd_req     = true; 
+            r_xram_rsp_to_init_cmd_nline   = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_init_cmd_trdid   = r_xram_rsp_upt_index;
+            r_xram_rsp_to_init_cmd_copies  = r_xram_rsp_victim_copies;
+            if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+            else		                 r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_WRITE_DIRTY:	// send a write request to XRAM_CMD FSM
+        {
+          if ( !r_xram_rsp_to_xram_cmd_req ) {
+            r_xram_rsp_to_xram_cmd_req = true;
+            r_xram_rsp_to_xram_cmd_nline = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_xram_cmd_trdid = r_xram_rsp_trt_index.read();
+            for(size_t i=0; i<m_words ; i++) {
+              r_xram_rsp_to_xram_cmd_data[i] = r_xram_rsp_victim_data[i];
+            }
+            m_cpt_write_dirty++;
+            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          }
+          break;
+        }
+    } // end swich r_xram_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		CLEANUP FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The CLEANUP FSM handles the cleanup request from L1 caches.
+    // It accesses the cache directory to update the list of copies.
+    //
+    // !!!!!!!! The actual cleanup of the cache directory has to be done...
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_cleanup_fsm.read() ) {
+
+      ///////////////////
+      case CLEANUP_IDLE:
+        {
+          if ( m_cmd_cleanup_nline_fifo.rok() ) {
+            m_cpt_cleanup++;
+            cmd_cleanup_fifo_get = true;
+            r_cleanup_nline      = m_cmd_cleanup_nline_fifo.read();
+            r_cleanup_srcid      = m_cmd_cleanup_srcid_fifo.read();
+            r_cleanup_trdid      = m_cmd_cleanup_trdid_fifo.read();
+            r_cleanup_pktid      = m_cmd_cleanup_pktid_fifo.read();
+
+            r_cleanup_fsm        = CLEANUP_DIR_LOCK;
+          }
+          break;
+        }
+        //////////////////////
+      case CLEANUP_DIR_LOCK:
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) {
+
+            // Read the directory
+            size_t way = 0;
+            DirectoryEntry entry = m_cache_directory.read(r_cleanup_nline.read() << (m_words +2) , way);
+
+            r_cleanup_dirty	= entry.dirty;
+            r_cleanup_tag		= entry.tag;
+            r_cleanup_lock	= entry.lock;
+            r_cleanup_way		= way;
+            r_cleanup_copies	= entry.copies & ~(0x1 << r_cleanup_srcid.read());
+
+            // In case of hit, the copy must be cleaned in the copies bit-vector
+            if( entry.valid )  { 
+              r_cleanup_fsm = CLEANUP_DIR_WRITE;
+            } else {
+              r_cleanup_fsm = CLEANUP_RSP;
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case CLEANUP_DIR_WRITE:
+        {
+          size_t way      = r_cleanup_way.read();
+#define L2 soclib::common::uint32_log2
+          size_t set      = m_y[r_cleanup_nline.read() << (L2(m_words) +2)];
+#undef L2
+
+          // update the cache directory (for the copies)
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.dirty	= r_cleanup_dirty.read();
+          entry.tag	= r_cleanup_tag.read();
+          entry.lock	= r_cleanup_lock.read();
+          entry.copies    = r_cleanup_copies.read();
+          m_cache_directory.write(set, way, entry);  
+
+          // response to the cache      
+          r_cleanup_fsm = CLEANUP_RSP;
+
+          break;
+        }
+        /////////////////
+      case CLEANUP_RSP:
+        {
+          if ( !r_cleanup_to_tgt_rsp_req ) {
+            r_cleanup_to_tgt_rsp_req   = true;
+            r_cleanup_to_tgt_rsp_srcid = r_cleanup_srcid.read();
+            r_cleanup_to_tgt_rsp_trdid = r_cleanup_trdid.read();
+            r_cleanup_to_tgt_rsp_pktid = r_cleanup_pktid.read();
+            r_cleanup_fsm = CLEANUP_IDLE;
+          }
+          break;
+        }
+    } // end switch cleanup fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		LLSC FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The LLSC FSM handles the LL & SC atomic access.
+    //
+    // For a LL :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the LL request is registered in the Atomic Table and the
+    // response is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state.
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the LL request is not consumed in the FIFO.
+    //
+    // For a SC :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the Atomic Table is checked and the proper response
+    // (true or false is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state. 
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the SC request is not consumed in the FIFO.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_llsc_fsm.read() ) {
+
+      ///////////////
+      case LLSC_IDLE:		// test LL / SC
+        {
+          if( m_cmd_llsc_addr_fifo.rok() ) {
+            if(m_cmd_llsc_sc_fifo.read()){
+              m_cpt_sc++;
+              r_llsc_fsm = SC_DIR_LOCK;
+            }
+            else{
+              m_cpt_ll++;
+              r_llsc_fsm = LL_DIR_LOCK;
+            }
+          }	
+          break;
+        }
+        /////////////////
+      case LL_DIR_LOCK:		// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+            size_t way = 0;
+            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+            r_llsc_dirty  = entry.dirty;
+            r_llsc_tag    = entry.tag;
+            r_llsc_way    = way;
+            r_llsc_copies = entry.copies | (0x1 << m_cmd_llsc_srcid_fifo.read());
+
+            if ( entry.valid )  r_llsc_fsm = LL_DIR_HIT;
+            else                r_llsc_fsm = LLSC_TRT_LOCK;
+          }
+          break;
+        }
+        ////////////////
+      case LL_DIR_HIT:		// read hit : update the memory cache
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[m_cmd_llsc_addr_fifo.read()];
+          size_t word	= m_x[m_cmd_llsc_addr_fifo.read()];
+
+          // update directory (lock bit & copies)
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.dirty	= r_llsc_dirty.read();
+          entry.lock	= true;
+          entry.tag	= r_llsc_tag.read();
+          entry.copies    = r_llsc_copies.read();
+          m_cache_directory.write(set, way, entry);
+
+          // read data in cache
+          r_llsc_data	= m_cache_data[way][set][word];
+
+          // set Atomic Table
+          m_atomic_tab.set(m_cmd_llsc_srcid_fifo.read(), m_cmd_llsc_addr_fifo.read());
+
+          r_llsc_fsm 	= LL_RSP;
+          break;
+        }
+        ////////////
+      case LL_RSP:		// request the TGT_RSP FSM to return data
+        {
+          if ( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_data	= r_llsc_data.read();
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_to_tgt_rsp_req		= true;
+            r_llsc_fsm = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_DIR_LOCK:
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+            size_t way = 0;
+            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+            bool ok = m_atomic_tab.isatomic(m_cmd_llsc_srcid_fifo.read(),m_cmd_llsc_addr_fifo.read());
+            if( ok ) {
+              r_llsc_dirty 	= entry.dirty;
+              r_llsc_tag		= entry.tag;
+              r_llsc_way		= way;
+              r_llsc_copies 	= entry.copies;
+              if ( entry.valid )  r_llsc_fsm = SC_DIR_HIT;
+              else                r_llsc_fsm = LLSC_TRT_LOCK;
+            } else {
+              r_llsc_fsm = SC_RSP_FALSE;
+            }
+          }
+          break;
+        }
+        ////////////////
+      case SC_DIR_HIT:
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[m_cmd_llsc_addr_fifo.read()]; 
+          size_t word	= m_x[m_cmd_llsc_addr_fifo.read()]; 
+
+          // update directory (lock & dirty bits
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.dirty	= true;
+          entry.lock	= true;
+          entry.tag	= r_llsc_tag.read();
+          entry.copies    = r_llsc_copies.read();
+          m_cache_directory.write(set, way, entry);
+
+          // write data in cache
+          m_cache_data[way][set][word] = m_cmd_llsc_wdata_fifo.read();
+
+          // reset Atomic Table
+          m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+
+          r_llsc_fsm = SC_RSP_TRUE;
+          break;
+        }
+        //////////////////
+      case SC_RSP_FALSE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_req		= true;
+            r_llsc_to_tgt_rsp_data	= 1;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			= LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_RSP_TRUE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_req		= true;
+            r_llsc_to_tgt_rsp_data	= 0;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			= LLSC_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_TRT_LOCK:         // read or write miss : check the Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            size_t   index = 0;
+            bool hit = m_transaction_tab.hit_read(m_nline[m_cmd_llsc_addr_fifo.read()],index);
+            bool wok = !m_transaction_tab.full(index);
+
+            if ( hit || !wok ) {  // missing line already requested or no space in TRT
+              r_llsc_fsm = LLSC_IDLE;
+            } else {
+              r_llsc_trt_index = index;
+              r_llsc_fsm       = LLSC_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case LLSC_TRT_SET:	// register the XRAM transaction in Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            m_transaction_tab.set(r_llsc_trt_index.read(),
+                true,
+                m_nline[m_cmd_llsc_addr_fifo.read()],
+                m_cmd_llsc_srcid_fifo.read(),
+                m_cmd_llsc_trdid_fifo.read(),
+                m_cmd_llsc_pktid_fifo.read(),
+                false,
+                false,
+                0,
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+            r_llsc_fsm = LLSC_XRAM_REQ;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_XRAM_REQ:	// request the XRAM_CMD FSM to tetch the missing line
+        {
+          if ( !r_llsc_to_xram_cmd_req ) {
+            r_llsc_to_xram_cmd_req        = true;
+            r_llsc_to_xram_cmd_trdid      = r_llsc_trt_index.read();
+            r_llsc_to_xram_cmd_nline      = m_nline[m_cmd_llsc_addr_fifo.read()];
+            if( m_cmd_llsc_sc_fifo.read() ) {
+              r_llsc_fsm                    = SC_RSP_FALSE;
+            } else {
+              cmd_llsc_fifo_get             = true;
+              r_llsc_fsm                    = LLSC_IDLE;
+            }
+          }
+          break;
+        }
+    } // end switch r_llsc_fsm
+
+
+    //////////////////////////////////////////////////////////////////////////////
+    //		INIT_CMD FSM
+    //////////////////////////////////////////////////////////////////////////////
+    // The INIT_CMD fsm controls the VCI CMD initiator port, used to update
+    // or invalidate cache lines in L1 caches.
+    // It implements a round-robin priority between the two following requests:
+    // - r_write_to_init_cmd_req : update request from WRITE FSM 
+    // - r_xram_rsp_to_init_cmd_req : invalidate request from XRAM_RSP FSM 
+    // The inval request is a single cell VCI write command containing the 
+    // index of the line to be invalidated.
+    // The update request is a multi-cells VCI write command : The first cell 
+    // contains the index of the cache line to be updated. The second cell contains 
+    // the index of the first modified word in the line. The following cells
+    // contain the data.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      //////////////////////// 
+      case INIT_CMD_UPDT_IDLE:	// Invalidate requests have highest priority
+        {
+          if ( r_xram_rsp_to_init_cmd_req ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          } else if ( r_write_to_init_cmd_req ) {
+            r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+            m_cpt_update++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_INVAL_IDLE:	// Update requests have highest priority
+        {
+          if ( r_write_to_init_cmd_req ) {
+            r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+            m_cpt_update++;
+          } else if ( r_xram_rsp_to_init_cmd_req ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_INVAL_SEL:	// selects the next L1 cache
+        {
+
+          if (r_xram_rsp_to_init_cmd_copies.read() == 0) {	// no more copies
+            r_xram_rsp_to_init_cmd_req = false;
+            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+          } else {						// select the first target
+            copy_t copies = r_xram_rsp_to_init_cmd_copies.read();
+            copy_t mask   = 0x1;
+            for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+              if ( copies & mask ) {
+                r_init_cmd_target = i;
+                break;
+              }
+              mask = mask << 1;
+            } // end for 
+            m_cpt_inval_mult++;
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            r_xram_rsp_to_init_cmd_copies = copies & ~mask;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_INVAL_NLINE:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ) r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+          break;
+        }
+        ///////////////////////
+      case INIT_CMD_UPDT_SEL:	// selects the next L1 cache
+        {
+          if (r_write_to_init_cmd_copies.read() == 0) {	// no more copies
+            r_write_to_init_cmd_req = false;
+            r_init_cmd_fsm    = INIT_CMD_UPDT_IDLE;
+          } else {						// select the first target
+            copy_t copies = r_write_to_init_cmd_copies.read();
+            copy_t mask   = 0x1;
+            for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+              if ( copies & mask ) {
+                r_init_cmd_target = i;
+                break;
+              }
+              mask = mask << 1;
+            } // end for 
+            r_init_cmd_fsm    = INIT_CMD_UPDT_NLINE;
+            r_write_to_init_cmd_copies = copies & ~mask;
+            r_init_cmd_cpt    = 0;
+            m_cpt_update_mult++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_NLINE:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_INDEX:	// send the first word index
+        {
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) ) {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+            } else {
+              r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+    } // end switch r_init_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_RSP FSM
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_RSP fsm sends the responses on the VCI target port
+    // with a round robin priority between six requests :
+    // - r_read_to_tgt_rsp_req
+    // - r_write_to_tgt_rsp_req
+    // - r_llsc_to_tgt_rsp_req
+    // - r_cleanup_to_tgt_rsp_req
+    // - r_init_rsp_to_tgt_rsp_req
+    // - r_xram_rsp_to_tgt_rsp_req
+    // The  ordering is :  read > write > llsc > cleanup > xram > init
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      ///////////////////////
+      case TGT_RSP_READ_IDLE:		// write requests have the highest priority
+        {
+          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          break;
+        }
+        ////////////////////////
+      case TGT_RSP_WRITE_IDLE:		// llsc requests have the highest priority
+        {
+          if      ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_LLSC_IDLE:		// cleanup requests have the highest priority
+        {
+          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          break;
+        }
+        //////////////////////////
+      case TGT_RSP_CLEANUP_IDLE:	// xram requests have the highest priority
+        {
+          if      ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_XRAM_IDLE:		// init requests have the highest priority
+        {
+          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_INIT_IDLE:		// read requests have the highest priority
+        {
+          if      ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ_TEST:		// test if word or cache line
+        {
+          bool 		line = true;
+          size_t	index;
+          for ( size_t i=0; i< m_words ; i++ ) {
+            line = line && r_read_to_tgt_rsp_val[i];
+            if ( r_read_to_tgt_rsp_val[i] ) index = i;
+          }
+          if ( line ) {
+            r_tgt_rsp_cpt = 0;
+            r_tgt_rsp_fsm = TGT_RSP_READ_LINE;
+          } else {
+            r_tgt_rsp_cpt = index;
+            r_tgt_rsp_fsm = TGT_RSP_READ_WORD;
+          } 
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ_WORD:		// send one word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
+            r_read_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ_LINE:		// send one complete cache line
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (m_words-1) ) {
+              r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
+              r_read_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_WRITE:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
+            r_write_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        //////////////////
+      case TGT_RSP_LLSC:		// send one atomic word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_LLSC_IDLE;
+            r_llsc_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        /////////////////////
+      case TGT_RSP_CLEANUP:		// send the cleanup acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
+            r_cleanup_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_XRAM_TEST:		// test if word or cache line
+        {
+          bool 	line = true;
+          size_t	index;
+          for ( size_t i=0; i< m_words ; i++ ) {
+            line = line && r_xram_rsp_to_tgt_rsp_val[i];
+            if ( r_xram_rsp_to_tgt_rsp_val[i] ) index = i;
+          }
+          if ( line ) {
+            r_tgt_rsp_cpt = 0;
+            r_tgt_rsp_fsm = TGT_RSP_XRAM_LINE;
+          } else {
+            r_tgt_rsp_cpt = index;
+            r_tgt_rsp_fsm = TGT_RSP_XRAM_WORD;
+          } 
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_XRAM_WORD:		// send one word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
+            r_xram_rsp_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_XRAM_LINE:		// send one complete cache line
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (m_words-1) ) {
+              r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
+              r_xram_rsp_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_INIT:		// send the pending write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
+            r_init_rsp_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+    } // end switch tgt_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_UPT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
+    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP 
+    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
+    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
+    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
+    // The ressource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_upt_fsm.read() ) {
+
+      ////////////////////////
+      case ALLOC_UPT_INIT_RSP:
+        if ( (r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK) && 
+            (r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR) ) 
+        {
+          if      (r_write_fsm.read()==WRITE_UPT_LOCK)       r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read()==XRAM_RSP_UPT_LOCK) r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_UPT_WRITE:
+        if ( r_write_fsm.read() != WRITE_UPT_LOCK ) 
+        {
+          if      (r_xram_rsp_fsm.read()==XRAM_RSP_UPT_LOCK) r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_init_rsp_fsm.read()==INIT_RSP_UPT_LOCK) r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+        }
+        break;
+
+        ////////////////////////
+      case ALLOC_UPT_XRAM_RSP:
+        if ( r_xram_rsp_fsm.read() != XRAM_RSP_UPT_LOCK ) 
+        { 
+          if      (r_init_rsp_fsm.read()==INIT_RSP_UPT_LOCK) r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if (r_write_fsm.read()==WRITE_UPT_LOCK)       r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+        }
+        break;
+
+    } // end switch r_alloc_upt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_DIR FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_DIR FSM allocates the access to the directory and
+    // the data cache with a round robin priority between 5 user FSMs :
+    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
+    // The ressource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_dir_fsm.read() ) {
+
+      ////////////////////
+      case ALLOC_DIR_READ:
+        if ( ( (r_read_fsm.read() != READ_DIR_LOCK) &&
+              (r_read_fsm.read() != READ_TRT_LOCK)     )
+            ||
+            ( (r_read_fsm.read()      == READ_TRT_LOCK)  &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)    )  ) 
+        {
+          if      (r_write_fsm.read()==WRITE_DIR_LOCK)       r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if ((r_llsc_fsm.read()==LL_DIR_LOCK) || 
+              (r_llsc_fsm.read()==SC_DIR_LOCK))         r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if (r_cleanup_fsm.read()==CLEANUP_DIR_LOCK)   r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if (r_xram_rsp_fsm.read()==XRAM_RSP_DIR_LOCK) r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_DIR_WRITE:
+        if ( ( (r_write_fsm.read() != WRITE_DIR_LOCK)     &&
+              (r_write_fsm.read() != WRITE_TRT_LOCK)     &&
+              (r_write_fsm.read() != WRITE_DIR_HIT_READ)      )
+            ||
+            ( (r_write_fsm.read()     == WRITE_TRT_LOCK) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
+        {
+          if      ((r_llsc_fsm.read()==LL_DIR_LOCK) || 
+              (r_llsc_fsm.read()==SC_DIR_LOCK))         r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if (r_cleanup_fsm.read()==CLEANUP_DIR_LOCK)   r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if (r_xram_rsp_fsm.read()==XRAM_RSP_DIR_LOCK) r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if (r_read_fsm.read()==READ_DIR_LOCK) 	     r_alloc_dir_fsm = ALLOC_DIR_READ;
+        }
+        break;
+
+        ////////////////////
+      case ALLOC_DIR_LLSC:
+        if ( ( (r_llsc_fsm.read() != LL_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != LL_DIR_HIT )    &&
+              (r_llsc_fsm.read() != SC_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != SC_DIR_HIT )    &&
+              (r_llsc_fsm.read() != LLSC_TRT_LOCK )    )
+            || 
+            ( (r_llsc_fsm.read()      == LLSC_TRT_LOCK ) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC)    ) )
+        {
+          if      (r_cleanup_fsm.read()==CLEANUP_DIR_LOCK)   r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if (r_xram_rsp_fsm.read()==XRAM_RSP_DIR_LOCK) r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if (r_read_fsm.read()==READ_DIR_LOCK) 	     r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read()==WRITE_DIR_LOCK)       r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+        }
+        break;
+
+        ///////////////////////
+      case ALLOC_DIR_CLEANUP:
+        if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) )
+        {
+          if      (r_xram_rsp_fsm.read()==XRAM_RSP_DIR_LOCK) r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if (r_read_fsm.read()==READ_DIR_LOCK) 	     r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read()==WRITE_DIR_LOCK)       r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if ((r_llsc_fsm.read()==LL_DIR_LOCK) || 
+              (r_llsc_fsm.read()==SC_DIR_LOCK))         r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_DIR_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY) ) 
+        {
+          if      (r_read_fsm.read()==READ_DIR_LOCK) 	     r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read()==WRITE_DIR_LOCK)     r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if ((r_llsc_fsm.read()==LL_DIR_LOCK) || 
+              (r_llsc_fsm.read()==SC_DIR_LOCK))       r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if (r_cleanup_fsm.read()==CLEANUP_DIR_LOCK) r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+        }
+        break;
+
+    } // end switch alloc_dir_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_TRT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
+    // with a round robin priority between 4 user FSMs :
+    // The cyclic priority is READ > WRITE > LLSC > XRAM_RSP
+    // The ressource is always allocated.
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    switch (r_alloc_trt_fsm) {
+
+      ////////////////////
+      case ALLOC_TRT_READ:
+        if ( r_read_fsm.read() != READ_TRT_LOCK ) 
+        {
+          if      (r_write_fsm.read()==WRITE_TRT_LOCK)            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if (r_llsc_fsm.read()==LLSC_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read()==XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ((r_ixr_rsp_fsm.read()==IXR_RSP_TRT_ERASE) ||
+              (r_ixr_rsp_fsm.read()==IXR_RSP_TRT_READ))       r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+        }
+        break;
+        /////////////////////
+      case ALLOC_TRT_WRITE:
+        if ( r_write_fsm.read() != WRITE_TRT_LOCK ) 
+        {
+          if      (r_llsc_fsm.read()==LLSC_TRT_LOCK) 	          r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read()==XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ((r_ixr_rsp_fsm.read()==IXR_RSP_TRT_ERASE) ||
+              (r_ixr_rsp_fsm.read()==IXR_RSP_TRT_READ))       r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read()==READ_TRT_LOCK) 	          r_alloc_trt_fsm = ALLOC_TRT_READ;
+        }
+        break;
+        ////////////////////
+      case ALLOC_TRT_LLSC:
+        if ( r_llsc_fsm.read() != LLSC_TRT_LOCK )
+        { 
+          if      (r_xram_rsp_fsm.read()==XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ((r_ixr_rsp_fsm.read()==IXR_RSP_TRT_ERASE) ||
+              (r_ixr_rsp_fsm.read()==IXR_RSP_TRT_READ))       r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read()==READ_TRT_LOCK) 	          r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if (r_write_fsm.read()==WRITE_TRT_LOCK)            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT) ) {
+          if      ((r_ixr_rsp_fsm.read()==IXR_RSP_TRT_ERASE) ||
+              (r_ixr_rsp_fsm.read()==IXR_RSP_TRT_READ))       r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read()==READ_TRT_LOCK) 	          r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if (r_write_fsm.read()==WRITE_TRT_LOCK)            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if (r_llsc_fsm.read()==LLSC_TRT_LOCK) 	          r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_IXR_RSP:
+        if ( (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
+            (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ) ) {
+          if      (r_read_fsm.read()==READ_TRT_LOCK) 	          r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if (r_write_fsm.read()==WRITE_TRT_LOCK)            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if (r_llsc_fsm.read()==LLSC_TRT_LOCK) 	          r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read()==XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+        }
+        break;
+
+    } // end switch alloc_trt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to READ FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_read_fifo_put ) {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.put_and_get(p_vci_tgt.address.read());
+        m_cmd_read_word_fifo.put_and_get((p_vci_tgt.plen.read() == 4));
+        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+      } else {
+        m_cmd_read_addr_fifo.simple_put(p_vci_tgt.address.read());
+        m_cmd_read_word_fifo.simple_put((p_vci_tgt.plen.read() == 4));
+        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+      }
+    } else {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.simple_get();
+        m_cmd_read_word_fifo.simple_get();
+        m_cmd_read_srcid_fifo.simple_get();
+        m_cmd_read_trdid_fifo.simple_get();
+        m_cmd_read_pktid_fifo.simple_get();
+      }
+    }
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to WRITE FIFO
+    /////////////////////////////////////////////////////////////////////
+
+    if ( cmd_write_fifo_put ) {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.put_and_get(p_vci_tgt.address.read());
+        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
+      } else {
+        m_cmd_write_addr_fifo.simple_put(p_vci_tgt.address.read());
+        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
+      }
+    } else {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.simple_get();
+        m_cmd_write_eop_fifo.simple_get();
+        m_cmd_write_srcid_fifo.simple_get();
+        m_cmd_write_trdid_fifo.simple_get();
+        m_cmd_write_pktid_fifo.simple_get();
+        m_cmd_write_data_fifo.simple_get();
+        m_cmd_write_be_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to LLSC FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_llsc_fifo_put ) {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.put_and_get(p_vci_tgt.address.read());
+        m_cmd_llsc_sc_fifo.put_and_get(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
+      } else {
+        m_cmd_llsc_addr_fifo.simple_put(p_vci_tgt.address.read());
+        m_cmd_llsc_sc_fifo.simple_put(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
+      }
+    } else {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.simple_get();
+        m_cmd_llsc_sc_fifo.simple_get();
+        m_cmd_llsc_srcid_fifo.simple_get();
+        m_cmd_llsc_trdid_fifo.simple_get();
+        m_cmd_llsc_pktid_fifo.simple_get();
+        m_cmd_llsc_wdata_fifo.simple_get();
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to CLEANUP FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_cleanup_fifo_put ) {
+      if ( cmd_cleanup_fifo_get ) {
+        m_cmd_cleanup_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_cleanup_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_cleanup_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_cleanup_nline_fifo.put_and_get(p_vci_tgt.wdata.read());
+      } else {
+        m_cmd_cleanup_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_cleanup_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_cleanup_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_cleanup_nline_fifo.simple_put(p_vci_tgt.wdata.read());
+      }
+    } else {
+      if ( cmd_cleanup_fifo_get ) {
+        m_cmd_cleanup_srcid_fifo.simple_get();
+        m_cmd_cleanup_trdid_fifo.simple_get();
+        m_cmd_cleanup_pktid_fifo.simple_get();
+        m_cmd_cleanup_nline_fifo.simple_get();
+      }
+    }
+
+    m_cpt_cycles++;
+
+  } // end transition()
+
+  /////////////////////////////
+  tmpl(void)::genMoore()
+    /////////////////////////////
+  {
+    ////////////////////////////////////////////////////////////
+    // Command signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////////////
+
+
+    p_vci_ixr.be      = 0xF;
+    p_vci_ixr.pktid   = 0;
+    p_vci_ixr.srcid   = m_srcid_ixr;
+    p_vci_ixr.cons    = false;
+    p_vci_ixr.wrap    = false;
+    p_vci_ixr.contig  = true;
+    p_vci_ixr.clen    = 0;
+    p_vci_ixr.cfixed  = false;
+
+    if ( r_xram_cmd_fsm.read() == XRAM_CMD_READ_NLINE ) {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (r_read_to_xram_cmd_nline.read()*m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_read_to_xram_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    } 
+    else if ( r_xram_cmd_fsm.read() == XRAM_CMD_LLSC_NLINE ) {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (r_llsc_to_xram_cmd_nline.read()*m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_llsc_to_xram_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    } 
+    else if ( r_xram_cmd_fsm.read() == XRAM_CMD_WRITE_NLINE ) {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (r_write_to_xram_cmd_nline.read()*m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_write_to_xram_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    } 
+    else if ( r_xram_cmd_fsm.read() == XRAM_CMD_XRAM_DATA ) {
+      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = ((r_xram_rsp_to_xram_cmd_nline.read()*m_words+r_xram_cmd_cpt.read())*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = r_xram_rsp_to_xram_cmd_data[r_xram_cmd_cpt.read()].read();
+      p_vci_ixr.trdid   = r_xram_rsp_to_xram_cmd_trdid.read();
+      p_vci_ixr.eop     = (r_xram_cmd_cpt == (m_words-1));
+    } else {
+      p_vci_ixr.cmdval  = false;
+      p_vci_ixr.address = 0;
+      p_vci_ixr.plen    = 0;
+      p_vci_ixr.wdata   = 0;
+      p_vci_ixr.trdid   = 0;
+      p_vci_ixr.eop	  = false;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////
+
+    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
+          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) || 
+        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) )           p_vci_ixr.rspack = true;
+    else                                                    p_vci_ixr.rspack = false;
+
+    ////////////////////////////////////////////////////
+    // Command signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+
+    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
+      case TGT_CMD_IDLE:
+        p_vci_tgt.cmdack  = false;
+        break;
+      case TGT_CMD_READ:
+        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
+        break;
+      case TGT_CMD_READ_EOP:
+        p_vci_tgt.cmdack  = true;
+        break;
+      case TGT_CMD_WRITE:
+        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
+        break;
+      case TGT_CMD_ATOMIC:
+        p_vci_tgt.cmdack  = m_cmd_llsc_addr_fifo.wok();
+        break;
+      case TGT_CMD_CLEANUP:
+        p_vci_tgt.cmdack  = m_cmd_cleanup_nline_fifo.wok();
+        break;
+      default:
+        p_vci_tgt.cmdack = false;
+        break;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      case TGT_RSP_READ_IDLE:
+      case TGT_RSP_WRITE_IDLE:
+      case TGT_RSP_LLSC_IDLE:
+      case TGT_RSP_CLEANUP_IDLE:
+      case TGT_RSP_XRAM_IDLE:
+      case TGT_RSP_INIT_IDLE:
+      case TGT_RSP_READ_TEST:
+      case TGT_RSP_XRAM_TEST:
+
+        p_vci_tgt.rspval  = false;
+        p_vci_tgt.rsrcid  = 0;
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rpktid  = 0;
+        p_vci_tgt.rtrdid  = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = false;	
+        break;
+      case TGT_RSP_READ_LINE:
+        p_vci_tgt.rspval   = true;
+        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();
+        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = (r_tgt_rsp_cpt.read()==(m_words-1));
+        break;
+      case TGT_RSP_READ_WORD:
+        p_vci_tgt.rspval   = true;
+        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();
+        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;	
+        break;
+      case TGT_RSP_WRITE:
+        p_vci_tgt.rspval   = true;
+        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   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_CLEANUP:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_LLSC:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = r_llsc_to_tgt_rsp_data.read();
+        p_vci_tgt.rsrcid   = r_llsc_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_llsc_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_llsc_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_XRAM_LINE:
+        p_vci_tgt.rspval   = true;
+        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();
+        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = (r_tgt_rsp_cpt.read()==(m_words-1));
+        break;
+      case TGT_RSP_XRAM_WORD:
+        p_vci_tgt.rspval   = true;
+        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();
+        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_INIT:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        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;
+        p_vci_tgt.reop     = true;	
+        break;
+    } // end switch r_tgt_rsp_fsm
+
+    ///////////////////////////////////////////////////
+    // Command signals on the p_vci_ini port
+    ///////////////////////////////////////////////////
+
+    p_vci_ini.cmd     = vci_param::CMD_WRITE;
+    p_vci_ini.srcid   = m_srcid_ini;
+    p_vci_ini.pktid   = 0;
+    p_vci_ini.cons    = true;
+    p_vci_ini.wrap    = false;
+    p_vci_ini.contig  = false;
+    p_vci_ini.clen    = 0;
+    p_vci_ini.cfixed  = false;
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      case INIT_CMD_UPDT_IDLE:
+      case INIT_CMD_INVAL_IDLE:
+      case INIT_CMD_UPDT_SEL:
+      case INIT_CMD_INVAL_SEL:
+        p_vci_ini.cmdval = false;
+        p_vci_ini.address = 0;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0;
+        p_vci_ini.plen    = 0;
+        p_vci_ini.trdid   = 0;
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_INVAL_NLINE:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = m_coherence_table[r_init_cmd_target.read()];
+        p_vci_ini.wdata   = r_xram_rsp_to_init_cmd_nline.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4;
+        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+      case INIT_CMD_UPDT_NLINE:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = m_coherence_table[r_init_cmd_target.read()] + 4;
+        p_vci_ini.wdata   = r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = m_coherence_table[r_init_cmd_target.read()] + 4;
+        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = m_coherence_table[r_init_cmd_target.read()] + 4;
+        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
+          r_write_to_init_cmd_index.read()].read();
+        if(r_write_to_init_cmd_we[r_init_cmd_cpt.read() +
+            r_write_to_init_cmd_index.read()].read())  
+          p_vci_ini.be      = 0xF;
+        else			p_vci_ini.be      = 0x0;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
+        break;
+    } // end switch r_init_cmd_fsm
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_ini port
+    //////////////////////////////////////////////////////
+
+    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
+    else                                          p_vci_ini.rspack  = false;
+
+  } // end genMoore()
+
+}} // end name space
Index: trunk/modules/vci_mem_cache_v1/caba/metadata/vci_mem_cache_v1.sd
===================================================================
--- trunk/modules/vci_mem_cache_v1/caba/metadata/vci_mem_cache_v1.sd	(revision 2)
+++ trunk/modules/vci_mem_cache_v1/caba/metadata/vci_mem_cache_v1.sd	(revision 2)
@@ -0,0 +1,40 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_mem_cache_v1',
+       classname = 'soclib::caba::VciMemCacheV1',
+       tmpl_parameters = [parameter.Module('vci_param', default = 'caba:vci_param'),],
+       header_files = ['../source/include/vci_mem_cache_v1.h',
+                       '../source/include/xram_transaction_v1.h',
+                       '../source/include/mem_cache_directory_v1.h',
+                       '../source/include/atomic_tab_v1.h',
+                       '../source/include/update_tab_v1.h',],
+       implementation_files = ['../source/src/vci_mem_cache_v1.cpp',],
+       uses = [Uses('caba:base_module'),
+               Uses('common:loader'),
+               Uses('common:mapping_table'),
+               Uses('caba:generic_fifo'),
+               ],
+       ports = [Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:vci_target','p_vci_tgt_cleanup'),
+		Port('caba:vci_initiator','p_vci_ini'),
+		Port('caba:vci_initiator','p_vci_ixr'),
+                Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+                Port('caba:clock_in', 'p_clk', auto = 'clock'),],
+       instance_parameters = [
+		parameter.Module('mtp', 'common:mapping_table'),
+		parameter.Module('mtc', 'common:mapping_table'),
+		parameter.Module('mtx', 'common:mapping_table'),
+		parameter.IntTab('vci_ixr_index'),
+		parameter.IntTab('vci_ini_index'),
+		parameter.IntTab('vci_tgt_index'),
+		parameter.IntTab('vci_tgt_index_cleanup'),
+       		parameter.Int('nways'),
+		parameter.Int('nsets'),
+		parameter.Int('nwords'),
+		],
+       extensions = ['dsx:get_ident=initiator_index:p_vci_ini',],
+)
Index: trunk/modules/vci_mem_cache_v1/caba/source/include/atomic_tab_v1.h
===================================================================
--- trunk/modules/vci_mem_cache_v1/caba/source/include/atomic_tab_v1.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v1/caba/source/include/atomic_tab_v1.h	(revision 2)
@@ -0,0 +1,121 @@
+#ifndef ATOMIC_TAB_V1_H_
+#define ATOMIC_TAB_V1_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+/*                  The atomic access tab                             */
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+class AtomicTab{
+    typedef uint32_t size_t;
+    typedef sc_dt::sc_uint<40> addr_t;
+
+private:
+    size_t size_tab;                            // The size of the tab
+    std::vector<addr_t> addr_tab;               // Address entries
+    std::vector<bool>   valid_tab;              // Valid entries
+
+public:
+
+    AtomicTab()
+	: addr_tab(0),
+	  valid_tab(0)
+	{
+    	size_tab=0;
+    }
+
+    AtomicTab(size_t size_tab_i)
+	: addr_tab(size_tab_i),
+	  valid_tab(size_tab_i)
+	{
+	    size_tab=size_tab_i;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The size() function returns the size of the tab */
+    /////////////////////////////////////////////////////////////////////
+    const size_t size(){
+	    return size_tab;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The init() function initializes the transaction tab entries */
+    /////////////////////////////////////////////////////////////////////
+    void init(){
+    	for ( size_t i=0; i<size_tab; i++) {
+		    addr_tab[i]=0;
+		    valid_tab[i]=false;
+    	}
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The set() function sets an entry 
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void set(const size_t id, const addr_t addr){
+	    assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	    addr_tab[id]=addr;
+	    valid_tab[id]=true;
+	    return;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The isatomic() function tests if the SC request corresponds to an entry
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+
+       This function return true if the request corresponds
+     */
+    /////////////////////////////////////////////////////////////////////
+    bool isatomic(const size_t id, const addr_t addr){
+	    assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	    bool test=valid_tab[id];
+	    test=test && (addr == addr_tab[id]);
+	    return test;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The reset() function resets all the entries for this lock
+       Arguments :
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void reset(const addr_t addr){
+	    for(size_t i=0 ; i<size_tab ; i++){
+		    if(addr == addr_tab[i]){
+			    valid_tab[i]=false;
+		    }
+	    }
+	    return;
+    }
+
+};
+ 
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v1/caba/source/include/mem_cache_directory_v1.h
===================================================================
--- trunk/modules/vci_mem_cache_v1/caba/source/include/mem_cache_directory_v1.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v1/caba/source/include/mem_cache_directory_v1.h	(revision 2)
@@ -0,0 +1,311 @@
+#ifndef SOCLIB_CABA_MEM_CACHE_DIRECTORY_V1_H
+#define SOCLIB_CABA_MEM_CACHE_DIRECTORY_V1_H 
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+namespace soclib { namespace caba {
+
+  using namespace sc_core;
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A LRU entry 
+  ////////////////////////////////////////////////////////////////////////
+  class LruEntry {
+
+    public:
+
+      bool recent;            
+
+      void init()
+      {
+        recent=false;
+      }
+
+  }; // end class LruEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A directory entry                               
+  ////////////////////////////////////////////////////////////////////////
+  class DirectoryEntry {
+
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+    typedef uint32_t copy_t;
+
+    public:
+
+    bool    valid;                  // entry valid
+    bool    is_cnt;                 // directory entry is a counter
+    bool    dirty;                  // entry dirty
+    bool    lock;                   // entry locked
+    tag_t   tag;                    // tag of the entry
+    copy_t  d_copies;               // vector of copies for data
+    copy_t  i_copies;               // vector of copies for instructions
+    size_t  count;                  // number of copies
+
+    DirectoryEntry()
+    {
+      valid    = false;
+      is_cnt   = false;
+      dirty    = false;
+      lock     = false;
+      tag      = 0;
+      d_copies = 0;
+      i_copies = 0;
+      count    = 0;
+    }
+
+    DirectoryEntry(const DirectoryEntry &source)
+    {
+      valid    = source.valid;
+      is_cnt   = source.is_cnt;
+      dirty    = source.dirty;
+      tag      = source.tag;
+      lock     = source.lock;
+      d_copies = source.d_copies;
+      i_copies = source.i_copies;
+      count    = source.count;
+    }          
+
+    /////////////////////////////////////////////////////////////////////
+    // The init() function initializes the entry 
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      valid = false;
+      is_cnt= false;
+      dirty = false;
+      lock  = false;
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    // The copy() function copies an existing source entry to a target 
+    /////////////////////////////////////////////////////////////////////
+    void copy(const DirectoryEntry &source)
+    {
+      valid	= source.valid;
+      is_cnt    = source.is_cnt;
+      dirty	= source.dirty;
+      tag	= source.tag;
+      lock	= source.lock;
+      d_copies	= source.d_copies;
+      i_copies	= source.i_copies;
+      count     = source.count;
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // The print() function prints the entry 
+    ////////////////////////////////////////////////////////////////////
+    void print()
+    {
+      std::cout << "Valid = " << valid << " ; IS COUNT = " << is_cnt << " ; Dirty = " << dirty << " ; Lock = " 
+        << lock << " ; Tag = " << std::hex << tag << " ; d_copies = " << d_copies << " ; i_copies = " << i_copies << " ; count = " << count << std::endl;
+    }
+
+  }; // end class DirectoryEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                       The directory  
+  ////////////////////////////////////////////////////////////////////////
+  class CacheDirectory {
+
+    typedef sc_dt::sc_uint<40> addr_t;
+    typedef uint32_t data_t;
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+
+    private:
+
+    // Directory constants
+    size_t					m_ways;
+    size_t					m_sets;
+    size_t					m_words;
+    size_t					m_width;
+
+    // the directory & lru tables
+    DirectoryEntry 				**m_dir_tab;
+    LruEntry	 				**m_lru_tab;
+
+    public:
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+    CacheDirectory( size_t ways, size_t sets, size_t words, size_t address_width)	 
+    {
+      m_ways  = ways; 
+      m_sets  = sets;
+      m_words = words;
+      m_width = address_width;
+
+      m_dir_tab = new DirectoryEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_dir_tab[i] = new DirectoryEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_dir_tab[i][j].init();
+      }
+      m_lru_tab = new LruEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_lru_tab[i] = new LruEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_lru_tab[i][j].init();
+      }
+    } // end constructor
+
+    /////////////////
+    // Destructor
+    /////////////////
+    ~CacheDirectory()
+    {
+      for(size_t i=0 ; i<m_sets ; i++){
+        delete [] m_dir_tab[i];
+        delete [] m_lru_tab[i];
+      }
+      delete [] m_dir_tab;
+      delete [] m_lru_tab;
+    } // end destructor
+
+    /////////////////////////////////////////////////////////////////////
+    // The read() function reads a directory entry. In case of hit, the
+    // LRU is updated.
+    // Arguments :
+    // - address : the address of the entry 
+    // - way : (return argument) the way of the entry in case of hit
+    // The function returns a copy of a (valid or invalid) entry  
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry read(const addr_t &address,size_t &way)
+    {
+
+#define L2 soclib::common::uint32_log2
+      const size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
+      const tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
+#undef L2
+
+      bool hit       = false;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        bool equal = ( m_dir_tab[set][i].tag == tag );
+        bool valid = m_dir_tab[set][i].valid;
+        hit = equal && valid;
+        if ( hit ) {			
+          way = i;
+          break;
+        } 
+      }
+      if ( hit ) {
+        m_lru_tab[set][way].recent = true;
+        return DirectoryEntry(m_dir_tab[set][way]);
+      } else {
+        return DirectoryEntry();
+      }
+    } // end read()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write function writes a new entry, 
+    // and updates the LRU bits if necessary.
+    // Arguments :
+    // - set : the set of the entry
+    // - way : the way of the entry
+    // - entry : the entry value
+    /////////////////////////////////////////////////////////////////////
+    void write(const size_t &set, const size_t &way, const DirectoryEntry &entry)
+    {
+      assert( (set<m_sets) 
+          && "Cache Directory write : The set index is invalid");
+      assert( (way<m_ways) 
+          && "Cache Directory write : The way index is invalid");
+
+      // update Directory
+      m_dir_tab[set][way].copy(entry);
+
+      // update LRU bits
+      bool all_recent = true;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
+      }
+      if ( all_recent ) {
+        for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
+      } else {
+        m_lru_tab[set][way].recent = true;
+      }
+    } // end write()
+
+    /////////////////////////////////////////////////////////////////////
+    // The print() function prints a selected directory entry
+    // Arguments :
+    // - set : the set of the entry to print
+    // - way : the way of the entry to print
+    /////////////////////////////////////////////////////////////////////
+    void print(const size_t &set, const size_t &way)
+    {
+      std::cout << std::dec << " set : " << set << " ; way : " << way << " ; " ;
+      m_dir_tab[set][way].print();
+    } // end print()
+
+    /////////////////////////////////////////////////////////////////////
+    // The select() function selects a directory entry to evince.
+    // Arguments :
+    // - set   : (input argument) the set to modify
+    // - way   : (return argument) the way to evince
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry select(const size_t &set, size_t &way)
+    {
+      assert( (set < m_sets) 
+          && "Cache Directory : (select) The set index is invalid");
+
+      for(size_t i=0; i<m_ways; i++){
+        if(!m_dir_tab[set][way].valid){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if(!(m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( !(m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( (m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      way = 0;
+      return DirectoryEntry(m_dir_tab[set][0]);
+    } // end select()
+
+    /////////////////////////////////////////////////////////////////////
+    // 		Global initialisation function
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      for ( size_t set=0 ; set<m_sets ; set++ ) {
+        for ( size_t way=0 ; way<m_ways ; way++ ) {
+          m_dir_tab[set][way].init();
+          m_lru_tab[set][way].init();
+        }
+      }
+    } // end init()
+
+  }; // end class CacheDirectory
+
+}} // end namespaces
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v1/caba/source/include/update_tab_v1.h
===================================================================
--- trunk/modules/vci_mem_cache_v1/caba/source/include/update_tab_v1.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v1/caba/source/include/update_tab_v1.h	(revision 2)
@@ -0,0 +1,402 @@
+#ifndef UPDATE_TAB_V1_H_
+#define UPDATE_TAB_V1_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+////////////////////////////////////////////////////////////////////////
+//                  An update tab entry    
+////////////////////////////////////////////////////////////////////////
+class UpdateTabEntry {
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  public:
+  bool 	valid;                // It is a valid pending transaction
+  bool	update;               // It is an update transaction
+  bool  brdcast;              // It is a broadcast invalidate
+  bool  rsp;                  // It needs a response to the initiator
+  size_t 	srcid;        // The srcid of the initiator which wrote the data
+  size_t 	trdid;        // The trdid of the initiator which wrote the data
+  size_t 	pktid;        // The pktid of the initiator which wrote the data
+  addr_t	nline;	      // The identifier of the cache line
+  size_t 	count;        // The number of acknowledge responses to receive
+
+  UpdateTabEntry(){
+    valid	= false;
+    update  = false;
+    brdcast = false;
+    rsp     = false;
+    srcid	= 0;
+    trdid	= 0;
+    pktid	= 0;
+    nline	= 0;
+    count	= 0;
+  }
+
+  UpdateTabEntry(bool   i_valid, 
+      bool   i_update,
+      bool   i_brdcast,
+      bool   i_rsp,
+      size_t i_srcid, 
+      size_t i_trdid, 
+      size_t i_pktid, 
+      addr_t i_nline,
+      size_t i_count) 
+  {
+    valid		= i_valid;
+    update	    = i_update;
+    brdcast     = i_brdcast;
+    rsp         = i_rsp;
+    srcid		= i_srcid;
+    trdid		= i_trdid;
+    pktid		= i_pktid;
+    nline		= i_nline;
+    count		= i_count;
+  }
+
+  UpdateTabEntry(const UpdateTabEntry &source)
+  {
+    valid   = source.valid;
+    update  = source.update;
+    brdcast = source.brdcast;
+    rsp     = source.rsp;
+    srcid   = source.srcid;
+    trdid   = source.trdid;
+    pktid   = source.pktid;
+    nline   = source.nline;
+    count   = source.count;
+  }
+
+  ////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  ///////////////////////////////////////////////////
+  void init()
+  {
+    valid  = false;
+    update = false;
+    brdcast= false;
+    rsp    = false;
+    srcid  = 0;
+    trdid  = 0;
+    pktid  = 0;
+    nline  = 0;
+    count  = 0;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the update tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const UpdateTabEntry &source)
+  {
+    valid  = source.valid;
+    update = source.update;
+    brdcast= source.brdcast;
+    rsp    = source.rsp;
+    srcid  = source.srcid;
+    trdid  = source.trdid;
+    pktid  = source.pktid;
+    nline  = source.nline;
+    count  = source.count;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << std::dec << "valid  = " << valid  << std::endl;
+    std::cout << "update = " << update << std::endl;
+    std::cout << "brdcast= " << brdcast<< std::endl;
+    std::cout << "rsp    = " << rsp    << std::endl;
+    std::cout << "srcid  = " << srcid  << std::endl; 
+    std::cout << "trdid  = " << trdid  << std::endl; 
+    std::cout << "pktid  = " << pktid  << std::endl; 
+    std::cout << std::hex << "nline  = " << nline  << std::endl;
+    std::cout << std::dec << "count  = " << count  << std::endl;
+  }
+};
+
+////////////////////////////////////////////////////////////////////////
+//                        The update tab             
+////////////////////////////////////////////////////////////////////////
+class UpdateTab{
+
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  private:
+  size_t size_tab;
+  std::vector<UpdateTabEntry> tab;
+
+  public:
+
+  UpdateTab()
+    : tab(0)
+  {
+    size_tab=0;
+  }
+
+  UpdateTab(size_t size_tab_i)
+    : tab(size_tab_i)
+  {
+    size_tab=size_tab_i;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  const size_t size(){
+    return size_tab;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    for(size_t i=0; i<size_tab; i++) {
+      std::cout << "UPDATE TAB ENTRY " << std::dec << i << "--------" << std::endl;
+      tab[i].print();
+    }
+    return;
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the tab 
+  /////////////////////////////////////////////////////////////////////
+  void init(){
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The reads() function reads an entry 
+  // Arguments :
+  // - entry : the entry to read
+  // This function returns a copy of the entry.
+  /////////////////////////////////////////////////////////////////////
+  UpdateTabEntry read (size_t entry)
+  {
+    assert(entry<size_tab && "Bad Update Tab Entry");
+    return UpdateTabEntry(tab[entry]);
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // The set() function writes an entry in the Update Table
+  // Arguments :
+  // - update : transaction type (bool)
+  // - srcid : srcid of the initiator
+  // - trdid : trdid of the initiator
+  // - pktid : pktid of the initiator
+  // - count : number of expected responses
+  // - index : (return argument) index of the selected entry
+  // This function returns true if the write successed (an entry was empty).
+  ///////////////////////////////////////////////////////////////////////////
+  bool set(const bool	update,
+      const bool   brdcast,
+      const bool   rsp,
+      const size_t srcid,
+      const size_t trdid,
+      const size_t pktid,
+      const addr_t nline,
+      const size_t count,
+      size_t &index)
+  {
+    for ( size_t i=0 ; i<size_tab ; i++ ) {
+      if( !tab[i].valid ) {
+        tab[i].valid		= true;
+        tab[i].update		= update;
+        tab[i].brdcast      = brdcast;
+        tab[i].rsp          = rsp;
+        tab[i].srcid		= (size_t) srcid;
+        tab[i].trdid		= (size_t) trdid;
+        tab[i].pktid		= (size_t) pktid;
+        tab[i].nline		= (addr_t) nline;
+        tab[i].count		= (size_t) count;
+        index			    = i;
+        return true;
+      }
+    }
+    return false;
+  } // end set()
+
+  /////////////////////////////////////////////////////////////////////
+  // The decrement() function decrements the counter for a given entry.
+  // Arguments :
+  // - index   : the index of the entry
+  // - counter : (return argument) value of the counter after decrement
+  // This function returns true if the entry is valid.
+  /////////////////////////////////////////////////////////////////////
+  bool decrement( const size_t index,
+      size_t &counter ) 
+  {
+    assert((index<size_tab) && "Bad Update Tab Entry");
+    if ( tab[index].valid ) {
+      tab[index].count--;
+      counter = tab[index].count;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_full() function returns true if the table is full
+  /////////////////////////////////////////////////////////////////////
+  bool is_full()
+  {
+    for(size_t i = 0 ; i < size_tab ; i++){
+      if(!tab[i].valid){
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The need_rsp() function returns the need of a response
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool need_rsp(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].rsp;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_brdcast(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].brdcast;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_update(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].update;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The srcid() function returns the srcid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t srcid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].srcid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The trdid() function returns the trdid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t trdid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].trdid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The pktid() function returns the pktid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t pktid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].pktid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The nline() function returns the nline value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  addr_t nline(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].nline;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The search_inval() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool search_inval(const addr_t nline,size_t &index)
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        if(!tab[i].update){
+          index = i ;
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read_nline() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool read_nline(const addr_t nline,size_t &index) 
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        index = i ;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The clear() function erases an entry of the tab
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////       
+  void clear(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    tab[index].valid=false;
+    return;	
+  }
+
+};
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v1/caba/source/include/vci_mem_cache_v1.h
===================================================================
--- trunk/modules/vci_mem_cache_v1/caba/source/include/vci_mem_cache_v1.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v1/caba/source/include/vci_mem_cache_v1.h	(revision 2)
@@ -0,0 +1,622 @@
+/* -*- c++ -*-
+ * File         : vci_mem_cache_v1.h
+ * Date         : 26/10/2008
+ * Copyright    : UPMC / LIP6
+ * Authors      : Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu choichillon.christophe@gmail.com
+ */
+
+#ifndef SOCLIB_CABA_MEM_CACHE_V1_H
+#define SOCLIB_CABA_MEM_CACHE_V1_H
+
+#include <inttypes.h>
+#include <systemc>
+#include <list>
+#include <cassert>
+#include "arithmetics.h"
+#include "alloc_elems.h"
+#include "caba_base_module.h"
+#include "vci_target.h"
+#include "vci_initiator.h"
+#include "generic_fifo.h"
+#include "mapping_table.h"
+#include "int_tab.h"
+#include "mem_cache_directory_v1.h"
+#include "xram_transaction_v1.h"
+#include "update_tab_v1.h"
+#include "atomic_tab_v1.h"
+
+#define TRANSACTION_TAB_LINES 4     // Number of lines in the transaction tab
+#define UPDATE_TAB_LINES 4          // Number of lines in the update tab
+#define BROADCAST_ADDR 0x0000000003 // Address to send the broadcast invalidate
+
+namespace soclib {  namespace caba {
+  using namespace sc_core;
+
+  template<typename vci_param>
+    class VciMemCacheV1
+    : public soclib::caba::BaseModule
+    {
+      typedef sc_dt::sc_uint<40> addr_t;
+      typedef typename vci_param::fast_addr_t vci_addr_t;
+      typedef uint32_t data_t;
+      typedef uint32_t tag_t;
+      typedef uint32_t size_t;
+      typedef uint32_t be_t;
+      typedef uint32_t copy_t;
+
+      /* States of the TGT_CMD fsm */
+      enum tgt_cmd_fsm_state_e{
+        TGT_CMD_IDLE,
+        TGT_CMD_READ,
+        TGT_CMD_READ_EOP,
+        TGT_CMD_WRITE,
+        TGT_CMD_ATOMIC,
+      };
+
+      /* States of the TGT_RSP fsm */
+      enum tgt_rsp_fsm_state_e{
+        TGT_RSP_READ_IDLE,
+        TGT_RSP_WRITE_IDLE,
+        TGT_RSP_LLSC_IDLE,
+        TGT_RSP_XRAM_IDLE,
+        TGT_RSP_INIT_IDLE,
+        TGT_RSP_CLEANUP_IDLE,
+        TGT_RSP_READ_TEST,
+        TGT_RSP_READ_WORD,
+        TGT_RSP_READ_LINE,
+        TGT_RSP_WRITE,
+        TGT_RSP_LLSC,
+        TGT_RSP_XRAM_TEST,
+        TGT_RSP_XRAM_WORD,
+        TGT_RSP_XRAM_LINE,
+        TGT_RSP_INIT,
+        TGT_RSP_CLEANUP,
+      };
+
+      /* States of the INIT_CMD fsm */
+      enum init_cmd_fsm_state_e{
+        INIT_CMD_INVAL_IDLE,
+        INIT_CMD_INVAL_SEL,
+        INIT_CMD_INVAL_NLINE,
+        INIT_CMD_UPDT_IDLE,
+        INIT_CMD_UPDT_SEL,
+        INIT_CMD_BRDCAST,
+        INIT_CMD_UPDT_NLINE,
+        INIT_CMD_UPDT_INDEX,
+        INIT_CMD_UPDT_DATA,
+      };
+
+      /* States of the INIT_RSP fsm */
+      enum init_rsp_fsm_state_e{
+        INIT_RSP_IDLE,
+        INIT_RSP_UPT_LOCK,
+        INIT_RSP_UPT_CLEAR,
+        INIT_RSP_END,
+      };
+
+      /* States of the READ fsm */
+      enum read_fsm_state_e{
+        READ_IDLE,
+        READ_DIR_LOCK,
+        READ_DIR_HIT,
+        READ_RSP,
+        READ_TRT_LOCK,
+        READ_TRT_SET,
+        READ_XRAM_REQ,
+      };
+
+      /* States of the WRITE fsm */
+      enum write_fsm_state_e{
+        WRITE_IDLE,
+        WRITE_NEXT,
+        WRITE_DIR_LOCK,
+        WRITE_DIR_HIT_READ,
+        WRITE_DIR_HIT,
+        WRITE_DIR_HIT_RSP,
+        WRITE_UPT_LOCK,
+        WRITE_WAIT_UPT,
+        WRITE_UPDATE,
+        WRITE_RSP,
+        WRITE_TRT_LOCK,
+        WRITE_TRT_DATA,
+        WRITE_TRT_SET,
+        WRITE_WAIT_TRT,
+        WRITE_XRAM_REQ,
+        WRITE_TRT_WRITE_LOCK,
+        WRITE_INVAL_LOCK,
+        WRITE_DIR_INVAL,
+        WRITE_INVAL,
+        WRITE_XRAM_SEND,
+      };
+
+      /* States of the IXR_RSP fsm */
+      enum ixr_rsp_fsm_state_e{
+        IXR_RSP_IDLE,
+        IXR_RSP_ACK,
+        IXR_RSP_TRT_ERASE,
+        IXR_RSP_TRT_READ,
+      };
+
+      /* States of the XRAM_RSP fsm */
+      enum xram_rsp_fsm_state_e{
+        XRAM_RSP_IDLE,
+        XRAM_RSP_TRT_COPY,
+        XRAM_RSP_TRT_DIRTY,
+        XRAM_RSP_DIR_LOCK,
+        XRAM_RSP_DIR_UPDT,
+        XRAM_RSP_DIR_RSP,
+        XRAM_RSP_INVAL_LOCK,
+        XRAM_RSP_INVAL_WAIT,
+        XRAM_RSP_INVAL,
+        XRAM_RSP_WRITE_DIRTY,
+      };
+
+      /* States of the IXR_CMD fsm */
+      enum ixr_cmd_fsm_state_e{
+        IXR_CMD_READ_IDLE,
+        IXR_CMD_WRITE_IDLE,
+        IXR_CMD_LLSC_IDLE,
+        IXR_CMD_XRAM_IDLE,
+        IXR_CMD_READ_NLINE,
+        IXR_CMD_WRITE_NLINE,
+        IXR_CMD_LLSC_NLINE,
+        IXR_CMD_XRAM_DATA,
+      };
+
+      /* States of the LLSC fsm */
+      enum llsc_fsm_state_e{
+        LLSC_IDLE,
+        LL_DIR_LOCK,
+        LL_DIR_HIT,
+        LL_RSP,
+        SC_DIR_LOCK,
+        SC_DIR_HIT,
+        SC_RSP_FALSE,
+        SC_RSP_TRUE,
+        LLSC_TRT_LOCK,
+        LLSC_TRT_SET,
+        LLSC_XRAM_REQ,
+      };
+
+      /* States of the CLEANUP fsm */
+      enum cleanup_fsm_state_e{
+        CLEANUP_IDLE,
+        CLEANUP_DIR_LOCK,
+        CLEANUP_DIR_WRITE,
+        CLEANUP_UPT_LOCK,
+        CLEANUP_UPT_WRITE,
+        CLEANUP_WRITE_RSP,
+        CLEANUP_RSP,
+      };
+
+      /* States of the ALLOC_DIR fsm */
+      enum alloc_dir_fsm_state_e{
+        ALLOC_DIR_READ,
+        ALLOC_DIR_WRITE,
+        ALLOC_DIR_LLSC,
+        ALLOC_DIR_CLEANUP,
+        ALLOC_DIR_XRAM_RSP,
+      };
+
+      /* States of the ALLOC_TRT fsm */
+      enum alloc_trt_fsm_state_e{
+        ALLOC_TRT_READ,
+        ALLOC_TRT_WRITE,
+        ALLOC_TRT_LLSC,
+        ALLOC_TRT_XRAM_RSP,
+        ALLOC_TRT_IXR_RSP,
+      };
+
+      /* States of the ALLOC_UPT fsm */
+      enum alloc_upt_fsm_state_e{
+        ALLOC_UPT_WRITE,
+        ALLOC_UPT_XRAM_RSP,
+        ALLOC_UPT_INIT_RSP,
+        ALLOC_UPT_CLEANUP,
+      };
+
+      uint32_t	   m_cpt_cycles;            // Counter of cycles 
+      uint32_t	   m_cpt_read;              // Number of READ transactions
+      uint32_t	   m_cpt_read_miss;         // Number of MISS READ 
+      uint32_t	   m_cpt_write;             // Number of WRITE transactions
+      uint32_t	   m_cpt_write_miss;        // Number of MISS WRITE
+      uint32_t     m_cpt_write_cells;	    // Cumulated length for WRITE transactions
+      uint32_t     m_cpt_write_dirty;	    // Cumulated length for WRITE transactions
+      uint32_t	   m_cpt_update;            // Number of UPDATE transactions
+      uint32_t	   m_cpt_update_mult;       // Number of targets for UPDATE
+      uint32_t	   m_cpt_inval;             // Number of INVAL  transactions
+      uint32_t	   m_cpt_inval_mult;        // Number of targets for INVAL  
+      uint32_t	   m_cpt_inval_brdcast;     // Number of BROADCAST INVAL  
+      uint32_t	   m_cpt_cleanup;           // Number of CLEANUP transactions
+      uint32_t	   m_cpt_ll;                // Number of LL transactions
+      uint32_t	   m_cpt_sc;                // Number of SC transactions
+
+      protected:
+
+      SC_HAS_PROCESS(VciMemCacheV1);
+
+      public:
+      sc_in<bool> 			  	p_clk;
+      sc_in<bool> 			  	p_resetn;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt_cleanup;
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ini;	
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ixr;
+
+      VciMemCacheV1(
+          sc_module_name name,                              // Instance Name 
+          const soclib::common::MappingTable &mtp,          // Mapping table for primary requets
+          const soclib::common::MappingTable &mtc,          // Mapping table for coherence requets
+          const soclib::common::MappingTable &mtx,          // Mapping table for XRAM
+          const soclib::common::IntTab &vci_ixr_index,      // VCI port to XRAM (initiator)
+          const soclib::common::IntTab &vci_ini_index,      // VCI port to PROC (initiator)
+          const soclib::common::IntTab &vci_tgt_index,      // VCI port to PROC (target)
+          const soclib::common::IntTab &vci_tgt_index_cleanup,    // VCI port to PROC (target) for cleanup
+          size_t nways,                                   // Number of ways per set 
+          size_t nsets,                                   // Number of sets
+          size_t nwords);                                 // Number of words per line
+
+      ~VciMemCacheV1();
+
+      void transition();
+
+      void genMoore();
+
+      void print_stats();
+
+      private:
+
+      // Component attributes
+      const size_t              m_initiators;           // Number of initiators
+      const size_t              m_ways;                 // Number of ways in a set
+      const size_t              m_sets;                 // Number of cache sets
+      const size_t              m_words;		        // Number of words in a line
+      const size_t              m_srcid_ixr;		    // Srcid for requests to XRAM 
+      const size_t              m_srcid_ini;		    // Srcid for requests to processors
+      std::list<soclib::common::Segment>  m_seglist;    // memory cached into the cache
+      std::list<soclib::common::Segment>  m_cseglist;   // coherence segment for the cache
+      vci_addr_t        		*m_coherence_table; 	// address(srcid)
+      AtomicTab                 m_atomic_tab;           // atomic access table
+      TransactionTab      		m_transaction_tab;	    // xram transaction table
+      UpdateTab                 m_update_tab;		    // pending update & invalidate 
+      CacheDirectory			m_cache_directory;	    // data cache directory
+
+      data_t	        	       ***m_cache_data;		// data array[set][way][word]
+
+      // adress masks
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_x;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_y;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_z;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_nline; 
+
+      //////////////////////////////////////////////////
+      // Others registers
+      //////////////////////////////////////////////////
+      sc_signal<size_t>   r_copies_limit; // Limit of the number of copies for one line
+
+      //////////////////////////////////////////////////
+      // Registers controlled by the TGT_CMD fsm
+      //////////////////////////////////////////////////
+
+      // Fifo between TGT_CMD fsm and READ fsm
+      GenericFifo<uint64_t>  m_cmd_read_addr_fifo;
+      GenericFifo<bool>      m_cmd_read_word_fifo;
+      GenericFifo<size_t>    m_cmd_read_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_read_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_read_pktid_fifo;
+
+      // Fifo between TGT_CMD fsm and WRITE fsm    
+      GenericFifo<uint64_t>  m_cmd_write_addr_fifo;
+      GenericFifo<bool>      m_cmd_write_eop_fifo;
+      GenericFifo<size_t>    m_cmd_write_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_write_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_write_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_write_data_fifo;
+      GenericFifo<be_t>	     m_cmd_write_be_fifo;
+
+      // Fifo between TGT_CMD fsm and LLSC fsm
+      GenericFifo<uint64_t>  m_cmd_llsc_addr_fifo;
+      GenericFifo<bool>      m_cmd_llsc_sc_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_llsc_wdata_fifo;
+
+      sc_signal<int>         r_tgt_cmd_fsm;
+
+      sc_signal<size_t>	     r_index;
+      size_t nseg;
+      size_t ncseg;
+      soclib::common::Segment  **m_seg;
+      soclib::common::Segment  **m_cseg;
+      ///////////////////////////////////////////////////////
+      // Registers controlled by the READ fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>         r_read_fsm;        // FSM state 
+      sc_signal<copy_t>      r_read_d_copies;   // bit-vector of copies 
+      sc_signal<copy_t>      r_read_i_copies;   // bit-vector of copies 
+      sc_signal<tag_t>       r_read_tag;	    // cache line tag (in directory)
+      sc_signal<bool>        r_read_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>        r_read_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_read_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>      r_read_count;      // number of copies
+      sc_signal<data_t>     *r_read_data;       // data (one cache line)
+      sc_signal<bool>        r_read_word;       // single word read
+      sc_signal<size_t>      r_read_way;        // associative way (in cache)
+      sc_signal<size_t>      r_read_trt_index;  // Transaction Table index
+      sc_signal<bool>        r_read_pass;       // Used to adjust with VHDL model
+
+      // Buffer between READ fsm and IXR_CMD fsm (ask a missing cache line to XRAM)   
+      sc_signal<bool>        r_read_to_ixr_cmd_req;     // valid request
+      sc_signal<addr_t>      r_read_to_ixr_cmd_nline;   // cache line index
+      sc_signal<size_t>      r_read_to_ixr_cmd_trdid;   // index in Transaction Table
+
+      // Buffer between READ fsm and TGT_RSP fsm (send a hit read response to L1 cache)
+      sc_signal<bool>	   r_read_to_tgt_rsp_req;       // valid request
+      sc_signal<size_t>	   r_read_to_tgt_rsp_srcid;	    // Transaction srcid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_trdid;	    // Transaction trdid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_pktid;	    // Transaction pktid
+      sc_signal<data_t>   *r_read_to_tgt_rsp_data;	    // data (one cache line)
+      sc_signal<bool> 	  *r_read_to_tgt_rsp_val;	    // valid bit (for single_word)
+
+      ///////////////////////////////////////////////////////////////
+      // Registers controlled by the WRITE fsm
+      ///////////////////////////////////////////////////////////////
+
+      sc_signal<int>       r_write_fsm;             // FSM state
+      sc_signal<addr_t>	   r_write_address;         // first word address
+      sc_signal<size_t>    r_write_word_index;      // first word index in line
+      sc_signal<size_t>    r_write_word_count;      // number of words in line
+      sc_signal<size_t>    r_write_srcid;           // transaction srcid
+      sc_signal<size_t>    r_write_trdid;           // transaction trdid
+      sc_signal<size_t>    r_write_pktid;           // transaction pktid
+      sc_signal<data_t>	  *r_write_data;            // data (one cache line)	
+      sc_signal<be_t>     *r_write_be;              // one byte enable per word
+      sc_signal<bool>      r_write_byte;            // is it a byte write
+      sc_signal<bool>      r_write_is_cnt;          // is_cnt bit (in directory)
+      sc_signal<bool>      r_write_lock;            // lock bit (in directory)
+      sc_signal<tag_t>     r_write_tag;             // cache line tag (in directory)
+      sc_signal<copy_t>    r_write_d_copies;        // bit vector of copies
+      sc_signal<copy_t>    r_write_i_copies;        // bit vector of copies
+      sc_signal<size_t>	   r_write_count;           // number of copies
+      sc_signal<size_t>	   r_write_way;		        // way of the line
+      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_pass;            // Used to adjust with VHDL model
+
+      // 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
+
+      // Buffer between WRITE fsm and IXR_CMD fsm (ask a missing cache line to XRAM) 
+      sc_signal<bool>	   r_write_to_ixr_cmd_req;      // valid request
+      sc_signal<bool>	   r_write_to_ixr_cmd_write;    // write request
+      sc_signal<addr_t>    r_write_to_ixr_cmd_nline; 	// cache line index
+      sc_signal<data_t>	  *r_write_to_ixr_cmd_data;	    // cache line data
+      sc_signal<size_t>    r_write_to_ixr_cmd_trdid;	// index in Transaction Table
+
+      // Buffer between WRITE fsm and INIT_CMD fsm (Update L1 caches)
+      sc_signal<bool>	   r_write_to_init_cmd_req;         // valid request
+      sc_signal<bool>	   r_write_to_init_cmd_brdcast;     // brdcast request
+      sc_signal<addr_t>	   r_write_to_init_cmd_nline;	    // cache line index
+      sc_signal<size_t>	   r_write_to_init_cmd_trdid;	    // index in Update Table
+      sc_signal<copy_t>    r_write_to_init_cmd_d_copies;    // bit_vector of L1 to update
+      sc_signal<copy_t>    r_write_to_init_cmd_i_copies;    // bit_vector of L1 to update
+      sc_signal<data_t>   *r_write_to_init_cmd_data;	    // data (one cache line)
+      sc_signal<bool>     *r_write_to_init_cmd_we;	        // word enable
+      sc_signal<size_t>	   r_write_to_init_cmd_count;	    // number of words in line
+      sc_signal<size_t>	   r_write_to_init_cmd_index;	    // index of first word in line
+
+      /////////////////////////////////////////////////////////
+      // Registers controlled by INIT_RSP fsm
+      //////////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_init_rsp_fsm;        // FSM state
+      sc_signal<size_t>	   r_init_rsp_upt_index;  // index in the Update Table
+      sc_signal<size_t>	   r_init_rsp_srcid;	  // pending write srcid      
+      sc_signal<size_t>	   r_init_rsp_trdid;	  // pending write trdid      
+      sc_signal<size_t>	   r_init_rsp_pktid;	  // pending write pktid      
+      sc_signal<addr_t>	   r_init_rsp_nline;	  // pending write nline      
+
+      // Buffer between INIT_RSP fsm and TGT_RSP fsm (complete write/update transaction)
+      sc_signal<bool>	     r_init_rsp_to_tgt_rsp_req;   	// valid request
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_srcid;		// Transaction srcid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_trdid;		// Transaction trdid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_pktid;		// Transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by CLEANUP fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int> 	     r_cleanup_fsm;         // FSM state
+      sc_signal<size_t>      r_cleanup_srcid;       // transaction srcid
+      sc_signal<size_t>      r_cleanup_trdid;       // transaction trdid
+      sc_signal<size_t>      r_cleanup_pktid;       // transaction pktid
+      sc_signal<addr_t>      r_cleanup_nline;       // cache line index
+
+      sc_signal<copy_t>      r_cleanup_d_copies;    // bit-vector of copies 
+      sc_signal<copy_t>      r_cleanup_i_copies;    // bit-vector of copies 
+      sc_signal<copy_t>      r_cleanup_count;       // number of copies 
+      sc_signal<tag_t>       r_cleanup_tag;	        // cache line tag (in directory)
+      sc_signal<bool>        r_cleanup_is_cnt;      // inst bit (in directory)
+      sc_signal<bool>        r_cleanup_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_cleanup_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>      r_cleanup_way;	        // associative way (in cache)
+      sc_signal<bool>        r_cleanup_pass;        // Used to adjust with the VHDL model
+
+      sc_signal<size_t>      r_cleanup_write_srcid; // srcid of write response
+      sc_signal<size_t>      r_cleanup_write_trdid; // trdid of write rsp
+      sc_signal<size_t>      r_cleanup_write_pktid; // pktid of write rsp
+      sc_signal<bool>        r_cleanup_need_rsp;    // needs a write rsp
+
+      sc_signal<size_t>      r_cleanup_index;	    // index of the INVAL line (in the UPT)
+
+      // Buffer between CLEANUP fsm and TGT_RSP fsm (acknowledge a write command from L1)
+      sc_signal<bool>      r_cleanup_to_tgt_rsp_req;    // valid request
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_srcid;  // transaction srcid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_trdid;	// transaction trdid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_pktid;	// transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by LLSC fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>       r_llsc_fsm;          // FSM state
+      sc_signal<data_t>	   r_llsc_data;		    // read data word
+      sc_signal<copy_t>    r_llsc_i_copies;	    // bit_vector of copies
+      sc_signal<copy_t>    r_llsc_d_copies;	    // bit_vector of copies
+      sc_signal<copy_t>    r_llsc_count;	    // number of copies
+      sc_signal<bool>      r_llsc_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>      r_llsc_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>    r_llsc_way;		    // way in directory
+      sc_signal<size_t>    r_llsc_set;		    // set in directory
+      sc_signal<data_t>    r_llsc_tag;		    // cache line tag (in directory)
+      sc_signal<size_t>    r_llsc_trt_index;    // Transaction Table index
+      sc_signal<bool>      r_llsc_pass;         // Used to adjust with the VHDL model
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (XRAM read)	
+      sc_signal<bool>	   r_llsc_to_ixr_cmd_req;   // valid request
+      sc_signal<addr_t>	   r_llsc_to_ixr_cmd_nline; // cache line index
+      sc_signal<size_t>	   r_llsc_to_ixr_cmd_trdid; // index in Transaction Table
+
+      // Buffer between LLSC fsm and TGT_RSP fsm
+      sc_signal<bool>	   r_llsc_to_tgt_rsp_req;   // valid request
+      sc_signal<data_t>    r_llsc_to_tgt_rsp_data;  // read data word
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_srcid; // Transaction srcid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_trdid; // Transaction trdid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_pktid; // Transaction pktid
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_rsp_fsm;       // FSM state
+      sc_signal<size_t>	   r_ixr_rsp_trt_index;	// TRT entry index
+      sc_signal<size_t>    r_ixr_rsp_cpt;	    // word counter
+
+      // Buffer between IXR_RSP fsm and XRAM_RSP fsm  (response from the XRAM)
+      sc_signal<bool>	  *r_ixr_rsp_to_xram_rsp_rok;	// A xram response is ready
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the XRAM_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_xram_rsp_fsm;		        // FSM state
+      sc_signal<size_t>	   r_xram_rsp_trt_index;	    // TRT entry index
+      TransactionTabEntry  r_xram_rsp_trt_buf;		    // TRT entry local buffer
+      sc_signal<bool>	   r_xram_rsp_victim_inval;	    // victim line invalidate 
+      sc_signal<bool>	   r_xram_rsp_victim_is_cnt;    // victim line inst bit
+      sc_signal<bool>	   r_xram_rsp_victim_dirty;	    // victim line dirty bit
+      sc_signal<size_t>    r_xram_rsp_victim_way;	    // victim line way
+      sc_signal<size_t>    r_xram_rsp_victim_set;	    // victim line set
+      sc_signal<addr_t>    r_xram_rsp_victim_nline;     // victim line index
+      sc_signal<copy_t>    r_xram_rsp_victim_d_copies;	// victim line copies
+      sc_signal<copy_t>    r_xram_rsp_victim_i_copies;	// victim line copies
+      sc_signal<copy_t>    r_xram_rsp_victim_count;	    // victim line number of copies
+      sc_signal<data_t>	  *r_xram_rsp_victim_data;	    // victim line data
+      sc_signal<size_t>	   r_xram_rsp_upt_index;	    // UPT entry index
+      sc_signal<bool>      r_xram_rsp_pass;             // Used to adjust with VHDL model
+
+      // Buffer between XRAM_RSP fsm and TGT_RSP fsm  (response to L1 cache)
+      sc_signal<bool>	   r_xram_rsp_to_tgt_rsp_req;	// Valid request
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_srcid;	// Transaction srcid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_trdid;	// Transaction trdid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_pktid;	// Transaction pktid
+      sc_signal<data_t>   *r_xram_rsp_to_tgt_rsp_data;	// data (one cache line)
+      sc_signal<bool>     *r_xram_rsp_to_tgt_rsp_val;	// valid bit (for single word)
+
+      // Buffer between XRAM_RSP fsm and INIT_CMD fsm (Inval L1 Caches) 
+      sc_signal<bool>	   r_xram_rsp_to_init_cmd_req;    // Valid request
+      sc_signal<bool>      r_xram_rsp_to_init_cmd_brdcast;  // Broadcast request
+      sc_signal<addr_t>    r_xram_rsp_to_init_cmd_nline;    // cache line index;
+      sc_signal<size_t>	   r_xram_rsp_to_init_cmd_trdid;    // index of UPT entry
+      sc_signal<copy_t>    r_xram_rsp_to_init_cmd_d_copies; // bit_vector of copies
+      sc_signal<copy_t>    r_xram_rsp_to_init_cmd_i_copies; // bit_vector of copies
+
+      // Buffer between XRAM_RSP fsm and IXR_CMD fsm (XRAM write)
+      sc_signal<bool>	   r_xram_rsp_to_ixr_cmd_req;	// Valid request
+      sc_signal<addr_t>	   r_xram_rsp_to_ixr_cmd_nline;	// cache line index
+      sc_signal<data_t>	  *r_xram_rsp_to_ixr_cmd_data;	// cache line data
+      sc_signal<size_t>	   r_xram_rsp_to_ixr_cmd_trdid;	// index in transaction table
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_cmd_fsm;
+      sc_signal<size_t>	   r_ixr_cmd_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by TGT_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_tgt_rsp_fsm;
+      sc_signal<size_t>    r_tgt_rsp_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by INIT_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	  r_init_cmd_fsm;
+      sc_signal<size_t>   r_init_cmd_cpt;
+      sc_signal<size_t>	  r_init_cmd_target;
+      sc_signal<bool>     r_init_cmd_inst;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_DIR fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_dir_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_TRT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_trt_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_UPT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_upt_fsm;
+
+    }; // end class VciMemCacheV1
+
+}}
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v1/caba/source/include/xram_transaction_v1.h
===================================================================
--- trunk/modules/vci_mem_cache_v1/caba/source/include/xram_transaction_v1.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v1/caba/source/include/xram_transaction_v1.h	(revision 2)
@@ -0,0 +1,404 @@
+#ifndef XRAM_TRANSACTION_V1_H_
+#define XRAM_TRANSACTION_V1_H_
+ 
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+#define DEBUG_XRAM_TRANSACTION 0
+
+////////////////////////////////////////////////////////////////////////
+//                  A transaction tab entry         
+////////////////////////////////////////////////////////////////////////
+
+class TransactionTabEntry {
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ public:
+  bool 		      valid;     	    // entry valid 
+  bool 		      xram_read; 	    // read request to XRAM
+  addr_t   	      nline;    	    // index (zy) of the requested line
+  size_t 	      srcid;     	    // processor requesting the transaction
+  size_t 	      trdid;     	    // processor requesting the transaction
+  size_t 	      pktid;     	    // processor requesting the transaction
+  bool 		      proc_read;	    // read request from processor
+  bool 		      single_word;   	// single word in case of processor read 
+  size_t 	      word_index;    	// word index in case of single word read
+  std::vector<data_t> wdata;        // write buffer (one cache line)
+  std::vector<be_t>   wdata_be;    	// be for each data in the write buffer
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    valid		= false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The alloc() function initializes the vectors of an entry
+  // Its arguments are :
+  // - n_words : number of words per line in the cache
+  /////////////////////////////////////////////////////////////////////
+  void alloc(size_t n_words)
+  {
+    wdata_be.reserve( (int)n_words );
+    wdata.reserve( (int)n_words );
+    for(size_t i=0; i<n_words; i++){
+      wdata_be.push_back(false);
+      wdata.push_back(0);
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the transaction tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const TransactionTabEntry &source)
+  {
+    valid	    = source.valid;
+    xram_read 	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read 	= source.proc_read;
+    single_word = source.single_word;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry 
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << "valid       = " << valid             << std::endl;
+    std::cout << "xram_read   = " << xram_read         << std::endl;
+    std::cout << "nline       = " << std::hex << nline << std::endl;
+    std::cout << "srcid       = " << srcid             << std::endl;
+    std::cout << "trdid       = " << trdid             << std::endl;
+    std::cout << "pktid       = " << pktid             << std::endl;
+    std::cout << "proc_read   = " << proc_read         << std::endl;
+    std::cout << "single_word = " << single_word       << std::endl;
+    std::cout << "word_index  = " << word_index        << std::endl; 
+    for(size_t i=0; i<wdata_be.size() ; i++){
+      std::cout << "wdata_be [" << i << "] = " << wdata_be[i] << std::endl;
+    }
+    for(size_t i=0; i<wdata.size() ; i++){
+      std::cout << "wdata [" << i << "] = " << wdata[i] << std::endl;
+    }
+    std::cout << std::endl;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // 		Constructors
+  /////////////////////////////////////////////////////////////////////
+
+  TransactionTabEntry()
+    {
+      wdata_be.clear();
+      wdata.clear();
+      valid=false;
+    }
+
+  TransactionTabEntry(const TransactionTabEntry &source){
+    valid	    = source.valid;
+    xram_read	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read	= source.proc_read;
+    single_word = source.single_word;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+}; // end class TransactionTabEntry
+
+////////////////////////////////////////////////////////////////////////
+//                  The transaction tab                              
+////////////////////////////////////////////////////////////////////////
+class TransactionTab{
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ private:
+  size_t size_tab;                // The size of the tab
+
+  data_t be_to_mask(be_t be)
+  {
+    data_t ret = 0;
+    if ( be&0x1 ) {
+      ret = ret | 0x000000FF;
+    }
+    if ( be&0x2 ) {
+      ret = ret | 0x0000FF00;
+    }
+    if ( be&0x4 ) {
+      ret = ret | 0x00FF0000;
+    }
+    if ( be&0x8 ) {
+      ret = ret | 0xFF000000;
+    }
+    return ret;
+  }
+
+ public:
+  TransactionTabEntry *tab;       // The transaction tab
+
+  ////////////////////////////////////////////////////////////////////
+  //		Constructors
+  ////////////////////////////////////////////////////////////////////
+  TransactionTab()
+    {
+      size_tab=0;
+      tab=NULL;
+    }
+
+  TransactionTab(size_t n_entries, size_t n_words)
+    {
+      size_tab = n_entries;
+      tab = new TransactionTabEntry[size_tab];
+      for ( size_t i=0; i<size_tab; i++) {
+	tab[i].alloc(n_words);
+      }
+    }
+
+  ~TransactionTab()
+    {
+      delete [] tab;
+    }
+
+  /////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab
+  /////////////////////////////////////////////////////////////////////
+  size_t size()
+  {
+    return size_tab;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the transaction tab entries
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The print() function prints a transaction tab entry
+  // Arguments :
+  // - index : the index of the entry to print
+  /////////////////////////////////////////////////////////////////////
+  void print(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    tab[index].print();
+    return;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read() function returns a transaction tab entry.
+  // Arguments :
+  // - index : the index of the entry to read
+  /////////////////////////////////////////////////////////////////////
+  TransactionTabEntry read(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    return tab[index];
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The full() function returns the state of the transaction tab
+  // Arguments :
+  // - index : (return argument) the index of an empty entry 
+  // The function returns true if the transaction tab is full
+  /////////////////////////////////////////////////////////////////////
+  bool full(size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(!tab[i].valid){
+	    index=i;
+	    return false;	
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The hit_read() function checks if an XRAM read transaction exists 
+  // for a given cache line.
+  // Arguments :
+  // - index : (return argument) the index of the hit entry, if there is 
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a read request has already been sent
+  //////////////////////////////////////////////////////////////////////
+  bool hit_read(const addr_t nline,size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if((tab[i].valid && (nline==tab[i].nline)) && (tab[i].xram_read)) {
+	    index=i;
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  ///////////////////////////////////////////////////////////////////////
+  // The hit_write() function looks if an XRAM write transaction exists 
+  // for a given line.
+  // Arguments :
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a write request has already been sent
+  ///////////////////////////////////////////////////////////////////////
+  bool hit_write(const addr_t nline)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(tab[i].valid && (nline==tab[i].nline) && !(tab[i].xram_read)) {
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_data_mask() function writes a vector of data (a line).
+  // The data is written only if the corresponding bits are set
+  // in the be vector. 
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  // - be   : vector of be 
+  // - data : vector of data
+  /////////////////////////////////////////////////////////////////////
+  void write_data_mask(const size_t index, 
+		       const std::vector<be_t> &be, 
+		       const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    assert(be.size()==tab[index].wdata_be.size() 
+	   && "Bad data mask in write_data_mask in TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data in write_data_mask in TransactionTab");
+
+    for(size_t i=0; i<tab[index].wdata_be.size() ; i++) {
+      tab[index].wdata_be[i] = tab[index].wdata_be[i] | be[i];
+      data_t mask = be_to_mask(be[i]);
+      tab[index].wdata[i] = (tab[index].wdata[i] & ~mask) | (data[i] & mask);
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The set() function registers a transaction (read or write)
+  // to the XRAM in the transaction tab.
+  // Arguments :
+  // - index : index in the transaction tab
+  // - xram_read : transaction type (read or write a cache line)
+  // - nline : the index (zy) of the cache line
+  // - srcid : srcid of the initiator that caused the transaction
+  // - trdid : trdid of the initiator that caused the transaction
+  // - pktid : pktid of the initiator that caused the transaction
+  // - proc_read : does the initiator want a copy
+  // - single_word : single word read (in case of processor read)
+  // - word_index : index in the line (in case of single word read)
+  // - data : the data to write (in case of write)
+  // - data_be : the mask of the data to write (in case of write)
+  /////////////////////////////////////////////////////////////////////
+  void set(const size_t index,
+	   const bool xram_read,
+	   const addr_t nline,
+	   const size_t srcid,
+	   const size_t trdid,
+	   const size_t pktid,
+	   const bool proc_read,
+	   const bool single_word,
+	   const size_t word_index,
+	   const std::vector<be_t> &data_be,
+	   const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in set() Transaction Tab");
+    assert(data_be.size()==tab[index].wdata_be.size() 
+	   && "Bad data_be argument in set() TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data argument in set() TransactionTab");
+
+    tab[index].valid	        = true;
+    tab[index].xram_read        = xram_read;
+    tab[index].nline	        = nline;
+    tab[index].srcid	        = srcid;
+    tab[index].trdid	        = trdid;
+    tab[index].pktid	        = pktid;
+    tab[index].proc_read	    = proc_read;
+    tab[index].single_word	    = single_word;
+    tab[index].word_index	    = word_index;
+    for(size_t i=0; i<tab[index].wdata.size(); i++) {
+      tab[index].wdata_be[i]    = data_be[i];
+      tab[index].wdata[i]       = data[i];
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_rsp() function writes a word of the response to an 
+  // XRAM read transaction.
+  // The data is only written when the corresponding BE field is Ox0.
+  // Arguments :
+  // - index : the index of the transaction in the transaction tab
+  // - word_index : the index of the data in the line
+  // - data : the data to write
+  /////////////////////////////////////////////////////////////////////
+  void write_rsp(const size_t index,
+		 const size_t word,
+		 const data_t data)
+  {
+    assert( (index < size_tab) 
+	    && "Selected entry  out of range in write_rsp() Transaction Tab");
+    assert( (word <= tab[index].wdata_be.size()) 
+	    && "Bad word_index in write_rsp() in TransactionTab");
+    assert( tab[index].valid 
+	    && "Transaction Tab Entry invalid in write_rsp()");
+    assert( tab[index].xram_read 
+	    && "Selected entry is not an XRAM read transaction in write_rsp()");
+
+    data_t mask = be_to_mask(tab[index].wdata_be[word]);
+    tab[index].wdata[word] = (tab[index].wdata[word] & mask) | (data & ~mask);
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The erase() function erases an entry in the transaction tab.
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  /////////////////////////////////////////////////////////////////////
+  void erase(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in erase() Transaction Tab");
+    tab[index].valid	= false;
+  }
+}; // end class TransactionTab
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v1/caba/source/src/vci_mem_cache_v1.cpp
===================================================================
--- trunk/modules/vci_mem_cache_v1/caba/source/src/vci_mem_cache_v1.cpp	(revision 2)
+++ trunk/modules/vci_mem_cache_v1/caba/source/src/vci_mem_cache_v1.cpp	(revision 2)
@@ -0,0 +1,3575 @@
+/* -*- c++ -*-
+ * File 	: vci_mem_cache_v1.cpp
+ * Date 	: 30/10/2008
+ * Copyright 	: UPMC / LIP6
+ * Authors 	: Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu choichillon.christophe@gmail.com
+ */
+#include "../include/vci_mem_cache_v1.h"
+
+#define VHDL_ACCURATE
+
+//#define IDEBUG
+//#define DEBUG_VCI_MEM_CACHE 2
+
+namespace soclib { namespace caba {
+
+#ifdef DEBUG_VCI_MEM_CACHE 
+  const char *tgt_cmd_fsm_str[] = {
+    "TGT_CMD_IDLE",
+    "TGT_CMD_READ",
+    "TGT_CMD_READ_EOP",
+    "TGT_CMD_WRITE",
+    "TGT_CMD_ATOMIC",
+  };
+  const char *tgt_rsp_fsm_str[] = {
+    "TGT_RSP_READ_IDLE",
+    "TGT_RSP_WRITE_IDLE",
+    "TGT_RSP_LLSC_IDLE",
+    "TGT_RSP_XRAM_IDLE",
+    "TGT_RSP_INIT_IDLE",
+    "TGT_RSP_CLEANUP_IDLE",
+    "TGT_RSP_READ_TEST",
+    "TGT_RSP_READ_WORD",
+    "TGT_RSP_READ_LINE",
+    "TGT_RSP_WRITE",
+    "TGT_RSP_LLSC",
+    "TGT_RSP_XRAM_TEST",
+    "TGT_RSP_XRAM_WORD",
+    "TGT_RSP_XRAM_LINE",
+    "TGT_RSP_INIT",
+    "TGT_RSP_CLEANUP",
+  };
+  const char *init_cmd_fsm_str[] = {
+    "INIT_CMD_INVAL_IDLE",
+    "INIT_CMD_INVAL_SEL",
+    "INIT_CMD_INVAL_NLINE",
+    "INIT_CMD_UPDT_IDLE",
+    "INIT_CMD_UPDT_SEL",
+    "INIT_CMD_BRDCAST",
+    "INIT_CMD_UPDT_NLINE",
+    "INIT_CMD_UPDT_INDEX",
+    "INIT_CMD_UPDT_DATA",
+  };
+  const char *init_rsp_fsm_str[] = {
+    "INIT_RSP_IDLE",
+    "INIT_RSP_UPT_LOCK",
+    "INIT_RSP_UPT_CLEAR",
+    "INIT_RSP_END",
+  };
+  const char *read_fsm_str[] = {
+    "READ_IDLE",
+    "READ_DIR_LOCK",
+    "READ_DIR_HIT",
+    "READ_RSP",
+    "READ_TRT_LOCK",
+    "READ_TRT_SET",
+    "READ_XRAM_REQ",
+  };
+  const char *write_fsm_str[] = {
+    "WRITE_IDLE",
+    "WRITE_NEXT",
+    "WRITE_DIR_LOCK",
+    "WRITE_DIR_HIT_READ",
+    "WRITE_DIR_HIT",
+    "WRITE_DIR_HIT_RSP",
+    "WRITE_UPT_LOCK",
+    "WRITE_WAIT_UPT",
+    "WRITE_UPDATE",
+    "WRITE_RSP",
+    "WRITE_TRT_LOCK",
+    "WRITE_TRT_DATA",
+    "WRITE_TRT_SET",
+    "WRITE_WAIT_TRT",
+    "WRITE_XRAM_REQ",
+    "WRITE_TRT_WRITE_LOCK",
+    "WRITE_INVAL_LOCK",
+    "WRITE_DIR_INVAL",
+    "WRITE_INVAL",
+    "WRITE_XRAM_SEND",
+  };
+  const char *ixr_rsp_fsm_str[] = {
+    "IXR_RSP_IDLE",
+    "IXR_RSP_ACK",
+    "IXR_RSP_TRT_ERASE",
+    "IXR_RSP_TRT_READ",
+  };
+  const char *xram_rsp_fsm_str[] = {
+    "XRAM_RSP_IDLE",
+    "XRAM_RSP_TRT_COPY",
+    "XRAM_RSP_TRT_DIRTY",
+    "XRAM_RSP_DIR_LOCK",
+    "XRAM_RSP_DIR_UPDT",
+    "XRAM_RSP_DIR_RSP",
+    "XRAM_RSP_INVAL_LOCK",
+    "XRAM_RSP_INVAL_WAIT",
+    "XRAM_RSP_INVAL",
+    "XRAM_RSP_WRITE_DIRTY",
+  };
+  const char *ixr_cmd_fsm_str[] = {
+    "IXR_CMD_READ_IDLE",
+    "IXR_CMD_WRITE_IDLE",
+    "IXR_CMD_LLSC_IDLE",
+    "IXR_CMD_XRAM_IDLE",
+    "IXR_CMD_READ_NLINE",
+    "IXR_CMD_WRITE_NLINE",
+    "IXR_CMD_LLSC_NLINE",
+    "IXR_CMD_XRAM_DATA",
+  };
+  const char *llsc_fsm_str[] = {
+    "LLSC_IDLE",
+    "LL_DIR_LOCK",
+    "LL_DIR_HIT",
+    "LL_RSP",
+    "SC_DIR_LOCK",
+    "SC_DIR_HIT",
+    "SC_RSP_FALSE",
+    "SC_RSP_TRUE",
+    "LLSC_TRT_LOCK",
+    "LLSC_TRT_SET",
+    "LLSC_XRAM_REQ",
+  };
+  const char *cleanup_fsm_str[] = {
+    "CLEANUP_IDLE",
+    "CLEANUP_DIR_LOCK",
+    "CLEANUP_DIR_WRITE",
+    "CLEANUP_UPT_LOCK",
+    "CLEANUP_UPT_WRITE",
+    "CLEANUP_WRITE_RSP",
+    "CLEANUP_RSP",
+  };
+  const char *alloc_dir_fsm_str[] = {
+    "ALLOC_DIR_READ",
+    "ALLOC_DIR_WRITE",
+    "ALLOC_DIR_LLSC",
+    "ALLOC_DIR_CLEANUP",
+    "ALLOC_DIR_XRAM_RSP",
+  };
+  const char *alloc_trt_fsm_str[] = {
+    "ALLOC_TRT_READ",
+    "ALLOC_TRT_WRITE",
+    "ALLOC_TRT_LLSC",
+    "ALLOC_TRT_XRAM_RSP",
+    "ALLOC_TRT_IXR_RSP",
+  };
+  const char *alloc_upt_fsm_str[] = {
+    "ALLOC_UPT_WRITE",
+    "ALLOC_UPT_XRAM_RSP",
+    "ALLOC_UPT_INIT_RSP",
+    "ALLOC_UPT_CLEANUP",
+  };
+#endif
+
+#define tmpl(x) template<typename vci_param> x VciMemCacheV1<vci_param>
+
+  using soclib::common::uint32_log2;
+
+  ////////////////////////////////
+  // 	Constructor 
+  ////////////////////////////////
+
+  tmpl(/**/)::VciMemCacheV1( 
+      sc_module_name name,
+      const soclib::common::MappingTable &mtp,
+      const soclib::common::MappingTable &mtc,
+      const soclib::common::MappingTable &mtx,
+      const soclib::common::IntTab &vci_ixr_index,
+      const soclib::common::IntTab &vci_ini_index,
+      const soclib::common::IntTab &vci_tgt_index,
+      const soclib::common::IntTab &vci_tgt_index_cleanup,
+      size_t nways,
+      size_t nsets,
+      size_t nwords)
+
+    : soclib::caba::BaseModule(name),
+
+    p_clk("clk"),
+    p_resetn("resetn"),
+    p_vci_tgt("vci_tgt"),
+    p_vci_tgt_cleanup("vci_tgt_cleanup"),
+    p_vci_ini("vci_ini"),
+    p_vci_ixr("vci_ixr"),
+
+    m_initiators( 32 ),
+    m_ways( nways ),
+    m_sets( nsets ),
+    m_words( nwords ),
+    m_srcid_ixr( mtx.indexForId(vci_ixr_index) ),
+    m_srcid_ini( mtc.indexForId(vci_ini_index) ),
+    m_seglist(mtp.getSegmentList(vci_tgt_index)),
+    m_cseglist(mtc.getSegmentList(vci_tgt_index_cleanup)),
+    m_coherence_table( mtc.getCoherenceTable<vci_addr_t>() ),
+    m_atomic_tab( m_initiators ),
+    m_transaction_tab( TRANSACTION_TAB_LINES, nwords ),
+    m_update_tab( UPDATE_TAB_LINES ),
+    m_cache_directory( nways, nsets, nwords, vci_param::N ),
+#define L2 soclib::common::uint32_log2
+    m_x( L2(m_words), 2),
+    m_y( L2(m_sets), L2(m_words) + 2),
+    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
+    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
+#undef L2
+
+    //  FIFOs 
+    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
+    m_cmd_read_word_fifo("m_cmd_read_word_fifo", 4),
+    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
+    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
+    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
+
+    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
+    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
+    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
+    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
+    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
+    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
+    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
+
+    m_cmd_llsc_addr_fifo("m_cmd_llsc_addr_fifo",4),
+    m_cmd_llsc_sc_fifo("m_cmd_llsc_sc_fifo",4),
+    m_cmd_llsc_srcid_fifo("m_cmd_llsc_srcid_fifo",4),
+    m_cmd_llsc_trdid_fifo("m_cmd_llsc_trdid_fifo",4),
+    m_cmd_llsc_pktid_fifo("m_cmd_llsc_pktid_fifo",4),
+    m_cmd_llsc_wdata_fifo("m_cmd_llsc_wdata_fifo",4),
+
+    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
+    nseg(0),	
+    r_read_fsm("r_read_fsm"),
+    r_write_fsm("r_write_fsm"),
+    r_init_rsp_fsm("r_init_rsp_fsm"),
+    r_cleanup_fsm("r_cleanup_fsm"),
+    r_llsc_fsm("r_llsc_fsm"),
+    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
+    r_xram_rsp_fsm("r_xram_rsp_fsm"),
+    r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
+    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
+    r_init_cmd_fsm("r_init_cmd_fsm"),
+    r_alloc_dir_fsm("r_alloc_dir_fsm"),
+    r_alloc_trt_fsm("r_alloc_trt_fsm"),
+    r_alloc_upt_fsm("r_alloc_upt_fsm")
+    {
+      assert(IS_POW_OF_2(nsets));
+      assert(IS_POW_OF_2(nwords));
+      assert(IS_POW_OF_2(nways));
+      assert(nsets);
+      assert(nwords);
+      assert(nways);
+      assert(nsets <= 1024);
+      assert(nwords <= 32);
+      assert(nways <= 32);
+
+
+      // Get the segments associated to the MemCache 
+      std::list<soclib::common::Segment>::iterator seg;
+
+      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
+        nseg++;
+      }
+      for(seg = m_cseglist.begin(); seg != m_cseglist.end() ; seg++) {
+        ncseg++;
+      }
+
+      m_seg = new soclib::common::Segment*[nseg];
+      size_t i = 0;
+      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) { 
+        m_seg[i] = &(*seg);
+        i++;
+      }
+      m_cseg = new soclib::common::Segment*[ncseg];
+      i = 0;
+      for ( seg = m_cseglist.begin() ; seg != m_cseglist.end() ; seg++ ) { 
+          m_cseg[i] = &(*seg);
+          i++;
+      }
+
+      // Memory cache allocation & initialisation
+      m_cache_data = new data_t**[nways];
+      for ( size_t i=0 ; i<nways ; ++i ) {
+        m_cache_data[i] = new data_t*[nsets];
+      }
+      for ( size_t i=0; i<nways; ++i ) {
+        for ( size_t j=0; j<nsets; ++j ) {
+          m_cache_data[i][j] = new data_t[nwords];
+          for ( size_t k=0; k<nwords; k++){
+            m_cache_data[i][j][k]=0;
+          }	
+        }
+      }
+
+      // Allocation for IXR_RSP FSM
+      r_ixr_rsp_to_xram_rsp_rok	    = new sc_signal<bool>[TRANSACTION_TAB_LINES];
+
+      // Allocation for XRAM_RSP FSM
+      r_xram_rsp_victim_data        = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_tgt_rsp_data    = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_tgt_rsp_val     = new sc_signal<bool>[nwords];
+      r_xram_rsp_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
+
+      // Allocation for READ FSM
+      r_read_data 			        = new sc_signal<data_t>[nwords];
+      r_read_to_tgt_rsp_data 		= new sc_signal<data_t>[nwords];
+      r_read_to_tgt_rsp_val 		= new sc_signal<bool>[nwords];
+
+      // Allocation for WRITE FSM
+      r_write_data 			        = new sc_signal<data_t>[nwords];
+      r_write_be 			        = new sc_signal<be_t>[nwords];
+      r_write_to_init_cmd_data 		= new sc_signal<data_t>[nwords];
+      r_write_to_init_cmd_we		= new sc_signal<bool>[nwords];
+      r_write_to_ixr_cmd_data	    = new sc_signal<data_t>[nwords];
+
+      // Simulation
+
+      SC_METHOD(transition);
+      dont_initialize();
+      sensitive << p_clk.pos();
+
+      SC_METHOD(genMoore);
+      dont_initialize();
+      sensitive << p_clk.neg();
+
+    } // end constructor
+
+  /////////////////////////////////////////
+  // This function prints the statistics 
+  /////////////////////////////////////////
+
+  tmpl(void)::print_stats()
+  {
+    std::cout << "----------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
+      << "- READ RATE            = " << (double)m_cpt_read/m_cpt_cycles << std::endl
+      << "- READ MISS RATE       = " << (double)m_cpt_read_miss/m_cpt_read << std::endl
+      << "- WRITE RATE           = " << (double)m_cpt_write/m_cpt_cycles << std::endl
+      << "- WRITE MISS RATE      = " << (double)m_cpt_write_miss/m_cpt_write << std::endl
+      << "- WRITE BURST LENGTH   = " << (double)m_cpt_write_cells/m_cpt_write << std::endl
+      << "- UPDATE RATE          = " << (double)m_cpt_update/m_cpt_cycles << std::endl
+      << "- UPDATE ARITY         = " << (double)m_cpt_update_mult/m_cpt_update << std::endl
+      << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
+      << "- INVAL MULTICAST ARITY= " << (double)m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
+      << "- INVAL BROADCAST RATE = " << (double)m_cpt_inval_brdcast/m_cpt_cycles << std::endl
+      << "- SAVE DIRTY RATE      = " << (double)m_cpt_write_dirty/m_cpt_cycles << std::endl
+      << "- CLEANUP RATE         = " << (double)m_cpt_cleanup/m_cpt_cycles << std::endl
+      << "- LL RATE              = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
+      << "- SC RATE              = " << (double)m_cpt_sc/m_cpt_cycles << std::endl;
+  }
+
+  /////////////////////////////////
+  tmpl(/**/)::~VciMemCacheV1()
+    /////////////////////////////////
+  {
+    for(size_t i=0; i<m_ways ; i++){
+      for(size_t j=0; j<m_sets ; j++){
+        delete [] m_cache_data[i][j];
+      }
+    }
+    for(size_t i=0; i<m_ways ; i++){
+      delete [] m_cache_data[i];
+    }
+    delete [] m_cache_data;
+    delete [] m_coherence_table;
+
+    delete [] r_ixr_rsp_to_xram_rsp_rok;
+
+    delete [] r_xram_rsp_victim_data;
+    delete [] r_xram_rsp_to_tgt_rsp_data;
+    delete [] r_xram_rsp_to_tgt_rsp_val;
+    delete [] r_xram_rsp_to_ixr_cmd_data;
+
+    delete [] r_read_data;
+    delete [] r_read_to_tgt_rsp_data;
+    delete [] r_read_to_tgt_rsp_val;
+
+    delete [] r_write_data;
+    delete [] r_write_be;
+    delete [] r_write_to_init_cmd_data;
+  }
+
+  //////////////////////////////////
+  tmpl(void)::transition()
+    //////////////////////////////////
+  {
+    using soclib::common::uint32_log2;
+    //  RESET          
+    if ( ! p_resetn.read() ) {
+
+      //     Initializing FSMs
+      r_tgt_cmd_fsm 	= TGT_CMD_IDLE;
+      r_tgt_rsp_fsm 	= TGT_RSP_READ_IDLE;
+      r_init_cmd_fsm 	= INIT_CMD_INVAL_IDLE;
+      r_init_rsp_fsm 	= INIT_RSP_IDLE;
+      r_read_fsm        = READ_IDLE;
+      r_write_fsm       = WRITE_IDLE;
+      r_llsc_fsm        = LLSC_IDLE;
+      r_cleanup_fsm 	= CLEANUP_IDLE;
+      r_alloc_dir_fsm   = ALLOC_DIR_READ;
+      r_alloc_trt_fsm   = ALLOC_TRT_READ;
+      r_alloc_upt_fsm   = ALLOC_UPT_WRITE;
+      r_ixr_rsp_fsm 	= IXR_RSP_IDLE;
+      r_xram_rsp_fsm 	= XRAM_RSP_IDLE;
+      r_ixr_cmd_fsm 	= IXR_CMD_READ_IDLE;
+
+      //  Initializing Tables
+      m_cache_directory.init();
+      m_atomic_tab.init();	
+      m_transaction_tab.init();
+
+      // initializing FIFOs and communication Buffers
+
+      m_cmd_read_addr_fifo.init();
+      m_cmd_read_word_fifo.init();
+      m_cmd_read_srcid_fifo.init();
+      m_cmd_read_trdid_fifo.init();
+      m_cmd_read_pktid_fifo.init();
+
+      m_cmd_write_addr_fifo.init();
+      m_cmd_write_eop_fifo.init();
+      m_cmd_write_srcid_fifo.init();
+      m_cmd_write_trdid_fifo.init();
+      m_cmd_write_pktid_fifo.init();
+      m_cmd_write_data_fifo.init();
+
+      m_cmd_llsc_addr_fifo.init();
+      m_cmd_llsc_srcid_fifo.init();
+      m_cmd_llsc_trdid_fifo.init();
+      m_cmd_llsc_pktid_fifo.init();
+      m_cmd_llsc_wdata_fifo.init();
+      m_cmd_llsc_sc_fifo.init();
+
+      r_read_to_tgt_rsp_req	    = false;
+      r_read_to_ixr_cmd_req	    = false;
+
+      r_write_to_tgt_rsp_req	= false;
+      r_write_to_ixr_cmd_req	= false;
+      r_write_to_init_cmd_req	= false;
+
+      r_cleanup_to_tgt_rsp_req	= false;
+
+      r_init_rsp_to_tgt_rsp_req	= false;
+
+      r_llsc_to_tgt_rsp_req	    = false;
+      r_llsc_to_ixr_cmd_req	    = false;
+
+      for(size_t i=0; i<TRANSACTION_TAB_LINES ; i++){
+        r_ixr_rsp_to_xram_rsp_rok[i] = false;
+      }
+
+      r_xram_rsp_to_tgt_rsp_req	    = false;
+      r_xram_rsp_to_init_cmd_req    = false;
+      r_xram_rsp_to_ixr_cmd_req	    = false;
+      r_xram_rsp_trt_index	        = 0;
+
+      r_ixr_cmd_cpt         = 0;
+
+      r_copies_limit        = 3;
+
+      // Activity counters
+      m_cpt_cycles		    = 0;
+      m_cpt_read		    = 0;
+      m_cpt_read_miss	    = 0;
+      m_cpt_write		    = 0;
+      m_cpt_write_miss	    = 0;
+      m_cpt_write_cells	    = 0;
+      m_cpt_write_dirty	    = 0;
+      m_cpt_update		    = 0;
+      m_cpt_update_mult     = 0;
+      m_cpt_inval_brdcast 	= 0;
+      m_cpt_inval 		    = 0;
+      m_cpt_inval_mult 		= 0;
+      m_cpt_cleanup		    = 0;
+      m_cpt_ll     		    = 0;
+      m_cpt_sc     		    = 0;
+
+      return;
+    }
+
+    bool    cmd_read_fifo_put = false;
+    bool    cmd_read_fifo_get = false;
+
+    bool    cmd_write_fifo_put = false;
+    bool    cmd_write_fifo_get = false;
+
+    bool    cmd_llsc_fifo_put = false;
+    bool    cmd_llsc_fifo_get = false;
+
+#if DEBUG_VCI_MEM_CACHE == 1
+    std::cout << "---------------------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
+      << " - TGT_CMD FSM   = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
+      << " - TGT_RSP FSM   = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
+      << " - INIT_CMD FSM  = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
+      << " - INIT_RSP FSM  = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
+      << " - READ FSM      = " << read_fsm_str[r_read_fsm] << std::endl
+      << " - WRITE FSM     = " << write_fsm_str[r_write_fsm] << std::endl
+      << " - LLSC FSM      = " << llsc_fsm_str[r_llsc_fsm] << std::endl
+      << " - CLEANUP FSM   = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
+      << " - IXR_CMD FSM   = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
+      << " - IXR_RSP FSM   = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
+      << " - XRAM_RSP FSM  = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
+      << " - ALLOC_DIR FSM = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
+      << " - ALLOC_TRT FSM = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
+      << " - ALLOC_UPT FSM = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl;
+#elif DEBUG_VCI_MEM_CACHE == 2
+    std::cout << "---------------------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
+      << " - TGT_CMD FSM   = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
+      << " - TGT_RSP FSM   = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
+      << " - INIT_CMD FSM  = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
+      << " - INIT_RSP FSM  = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
+      << " - READ FSM      = " << read_fsm_str[r_read_fsm] << std::endl
+      << " - WRITE FSM     = " << write_fsm_str[r_write_fsm] << std::endl
+      << " - LLSC FSM      = " << llsc_fsm_str[r_llsc_fsm] << std::endl
+      << " - CLEANUP FSM   = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
+      << " - IXR_CMD FSM   = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
+      << " - IXR_RSP FSM   = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
+      << " - XRAM_RSP FSM  = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
+      << " - ALLOC_DIR FSM = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
+      << " - ALLOC_TRT FSM = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
+      << " - ALLOC_UPT FSM = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl;
+    std::cout << " - UPDATE/INVAL TABLE : " << std::endl;
+    m_update_tab.print();
+    std::cout << " - TRANSACTION TABLE = : " << std::endl;
+    for (unsigned int i = 0 ; i < m_transaction_tab.size() ; i++){
+      m_transaction_tab.print(i);
+    }
+#endif
+
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
+    //
+    // There is 4 types of packets for the m_mem_segment :
+    // - READ    : a READ request has a length of 1 VCI cell. It can be a single word 
+    //             or an entire cache line, depending on the PLEN value.
+    // - WRITE   : a WRITE request has a maximum length of 16 cells, and can only
+    //             concern words in a same line.
+    // - LL      : The LL request has a length of 1 cell.
+    // - SC      : The SC request has a length of 1 cell. 
+    //             The WDATA field contains the data to write.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_cmd_fsm.read() ) {
+
+      //////////////////
+      case TGT_CMD_IDLE:
+        {
+          if ( p_vci_tgt.cmdval ) {
+            assert( (p_vci_tgt.srcid.read() < m_initiators)
+                && "VCI_MEM_CACHE error in VCI_MEM_CACHE : The received SRCID is larger than 31");
+
+            bool reached = false;
+            for ( size_t index = 0 ; index < nseg && !reached ; index++) 
+            {
+//              if ( m_seg[index]->contains((addr_t)(p_vci_tgt.address.read())) ) {
+              if ( m_seg[index]->contains(p_vci_tgt.address.read()) ) {
+                reached = true;
+                r_index = index;
+              }
+            }
+
+
+            if ( !reached ) 
+            { 
+              std::cout << "VCI_MEM_CACHE Out of segment access in VCI_MEM_CACHE" << std::endl;
+              std::cout << "Faulty address = " << std::hex << (addr_t)(p_vci_tgt.address.read()) << std::endl;
+              std::cout << "Faulty initiator = " << std::dec << p_vci_tgt.srcid.read() << std::endl;
+              exit(0);
+            } 
+            else if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_READ;
+            } 
+            else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE )) //&& ( p_vci_tgt.trdid.read() == 0x0 ))
+            {  
+              r_tgt_cmd_fsm = TGT_CMD_WRITE;
+            } 
+            else if ((p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ) || 
+                (p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND) ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
+            } 
+          }
+          break;
+        }
+        //////////////////
+      case TGT_CMD_READ:
+
+        {
+          assert(((p_vci_tgt.plen.read() == 4) || (p_vci_tgt.plen.read() == m_words*4))
+              && "VCI_MEM_CACHE All read request to the MemCache must have PLEN = 4 or PLEN = 4*nwords"); 
+
+          if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) {
+            cmd_read_fifo_put = true;
+            if ( p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+            else                  r_tgt_cmd_fsm = TGT_CMD_READ_EOP;		
+          } 
+          break;
+        }
+        //////////////////////
+      case TGT_CMD_READ_EOP:
+        {
+          if ( p_vci_tgt.cmdval && p_vci_tgt.eop ){
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_CMD_WRITE:
+        {
+
+          if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() ) {
+            cmd_write_fifo_put = true;
+            if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+
+          }
+          break;
+        }
+        ////////////////////
+      case TGT_CMD_ATOMIC:
+        {
+          assert(p_vci_tgt.eop && "Memory Cache Error: LL or SC command with length > 1 ");
+
+          if ( p_vci_tgt.cmdval && m_cmd_llsc_addr_fifo.wok() ) {
+            cmd_llsc_fifo_put = true;
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+    } // end switch tgt_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////////
+    //		INIT_RSP FSM
+    /////////////////////////////////////////////////////////////////////////
+    // This FSM controls the response to the update or invalidate requests
+    // sent by the memory cache to the L1 caches :
+    //
+    // - update request initiated by the WRITE FSM.  
+    //   The FSM decrements the proper entry in the Update/Inval Table.
+    //   It sends a request to the TGT_RSP FSM to complete the pending 
+    //   write transaction (acknowledge response to the writer processor), 
+    //   and clear the UPT entry when all responses have been received.  
+    // - invalidate request initiated by the XRAM_RSP FSM.
+    //   The FSM decrements the proper entry in the Update/Inval_Table,
+    //   and clear the entry when all responses have been received.
+    //
+    // All those response packets are one word, compact
+    // packets complying with the VCI advanced format. 
+    // The index in the Table is defined in the RTRDID field, and
+    // the Transaction type is defined in the Update/Inval Table.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_rsp_fsm.read() ) {
+
+      ///////////////////
+      case INIT_RSP_IDLE:
+        {
+
+          if ( p_vci_ini.rspval ) {
+
+            assert ( ( p_vci_ini.rtrdid.read() < m_update_tab.size() )
+                && "VCI_MEM_CACHE UPT index too large in VCI response paquet received by memory cache" );
+            assert ( p_vci_ini.reop 
+                && "VCI_MEM_CACHE All response packets to update/invalidate requests must be one cell" );
+            r_init_rsp_upt_index = p_vci_ini.rtrdid.read(); 
+            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_RSP_UPT_LOCK:	// decrement the number of expected responses
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) { 
+            size_t count = 0;
+            bool valid  = m_update_tab.decrement(r_init_rsp_upt_index.read(), count);
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+#endif
+            assert ( valid 
+                && "VCI_MEM_CACHE Invalid UPT entry in VCI response paquet received by memory cache" );
+
+            if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
+            else              r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_RSP_UPT_CLEAR:	// clear the UPT entry
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) {
+            r_init_rsp_srcid = m_update_tab.srcid(r_init_rsp_upt_index.read());
+            r_init_rsp_trdid = m_update_tab.trdid(r_init_rsp_upt_index.read());
+            r_init_rsp_pktid = m_update_tab.pktid(r_init_rsp_upt_index.read());
+            r_init_rsp_nline = m_update_tab.nline(r_init_rsp_upt_index.read());
+            bool need_rsp = m_update_tab.need_rsp(r_init_rsp_upt_index.read());
+            if ( need_rsp ) r_init_rsp_fsm = INIT_RSP_END;
+            else            r_init_rsp_fsm = INIT_RSP_IDLE;
+            m_update_tab.clear(r_init_rsp_upt_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_CLEAR update table : " << std::endl;
+	m_update_tab.print();
+#endif
+          }
+          break;
+        }
+        //////////////////
+      case INIT_RSP_END:
+        {
+
+          if ( !r_init_rsp_to_tgt_rsp_req ) {
+            r_init_rsp_to_tgt_rsp_req = true;
+            r_init_rsp_to_tgt_rsp_srcid = r_init_rsp_srcid.read();
+            r_init_rsp_to_tgt_rsp_trdid = r_init_rsp_trdid.read();
+            r_init_rsp_to_tgt_rsp_pktid = r_init_rsp_pktid.read();
+            r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+    } // end switch r_init_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		READ FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The READ FSM controls the read requests sent by processors.
+    // It takes the lock protecting the cache directory to check the cache line status:
+    // - In case of HIT, the fsm copies the data (one line, or one single word)
+    //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
+    //   The requesting initiator is registered in the cache directory.
+    // - In case of MISS, the READ fsm takes the lock protecting the transaction tab.
+    //   If a read transaction to the XRAM for this line already exists,
+    //   or if the transaction tab is full, the fsm is stalled.
+    //   If a transaction entry is free, the READ fsm sends a request to the XRAM.
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_read_fsm.read() ) {
+
+      ///////////////
+      case READ_IDLE:
+        {
+          if (m_cmd_read_addr_fifo.rok()) {
+            m_cpt_read++;
+#ifdef VHDL_ACCURATE
+            r_read_pass = false;
+#endif
+            r_read_fsm = READ_DIR_LOCK;
+          }
+          break;
+        }
+        ///////////////////
+      case READ_DIR_LOCK:	// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+#ifdef VHDL_ACCURATE
+            if(!r_read_pass.read()){
+#endif
+              size_t way = 0;
+              DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
+#ifdef IDEBUG
+	   std::cout << "In READ_DIR_LOCK printing the entry of address is : " << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+              r_read_is_cnt   = entry.is_cnt;
+              r_read_dirty    = entry.dirty;
+              r_read_tag	  = entry.tag;
+              r_read_lock	  = entry.lock;
+              r_read_way	  = way;
+              r_read_word	  = m_cmd_read_word_fifo.read();
+              r_read_d_copies = entry.d_copies; 
+              r_read_i_copies = entry.i_copies; 
+              r_read_count    = entry.count;
+#ifdef VHDL_ACCURATE
+              r_read_pass     = true;
+#endif
+
+              // In case of hit, the read acces must be registered in the copies bit-vector
+              if( entry.valid )  { 
+                r_read_fsm = READ_DIR_LOCK;
+              } else {
+                r_read_fsm = READ_TRT_LOCK;
+                m_cpt_read_miss++;
+              }
+
+#ifdef VHDL_ACCURATE
+            } else {
+              r_read_pass = false;
+              r_read_fsm = READ_DIR_HIT;
+            }
+#endif
+          }
+          break;
+        }
+        //////////////////
+      case READ_DIR_HIT:	// read hit : update the memory cache
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            // signals generation
+            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
+            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
+            bool is_cnt = ((r_read_count.read() >= r_copies_limit.read()) && cached_read) || r_read_is_cnt.read();
+
+            // read data in the cache
+            size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            size_t way = r_read_way.read();
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_data[i] = m_cache_data[way][set][i];
+            }
+
+            // update the cache directory (for the copies)
+            DirectoryEntry entry;
+            entry.valid	  = true;
+            entry.is_cnt  = is_cnt; // when we reach the limit of copies
+            entry.dirty	  = r_read_dirty.read();
+            entry.tag	  = r_read_tag.read();
+            entry.lock	  = r_read_lock.read();
+            if(cached_read){  // Cached read, we update the copies vector
+              if(inst_read && !is_cnt){ // Instruction read, vector mode
+                assert(!(r_read_i_copies.read() & (0x1 << m_cmd_read_srcid_fifo.read())) && "MemCache Error : processor read on an already owned cache line");
+                entry.d_copies  = r_read_d_copies.read();
+                entry.i_copies  = r_read_i_copies.read() | (0x1 << m_cmd_read_srcid_fifo.read()); 
+                entry.count     = r_read_count.read() + 1;
+              }
+              if(!inst_read && !is_cnt){ // Data read, vector mode
+                assert(!(r_read_d_copies.read() & (0x1 << m_cmd_read_srcid_fifo.read())) && "MemCache Error : processor read on an already owned cache line");
+                entry.d_copies  = r_read_d_copies.read() | (0x1 << m_cmd_read_srcid_fifo.read()); 
+                entry.i_copies  = r_read_i_copies.read();
+                entry.count     = r_read_count.read() + 1;
+              }
+              if( is_cnt ) { // Counter mode
+                entry.count     = r_read_count.read() + 1;
+                entry.d_copies  = 0;
+                entry.i_copies  = 0;
+              } 
+            } else { // Uncached read
+              entry.d_copies = r_read_d_copies.read();
+              entry.i_copies = r_read_i_copies.read();
+              entry.count    = r_read_count.read();
+            }
+#ifdef IDEBUG
+	   std::cout << "In READ_DIR_HIT printing the entry of address is : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            m_cache_directory.write(set, way, entry);
+            r_read_fsm    = READ_RSP;
+          }
+          break;
+        }
+        //////////////
+      case READ_RSP: 		//  request the TGT_RSP FSM to return data
+        {
+          if( !r_read_to_tgt_rsp_req ) {	
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_to_tgt_rsp_data[i] = r_read_data[i];
+              if ( r_read_word ) {	// single word
+                r_read_to_tgt_rsp_val[i] = (i == m_x[(vci_addr_t)(m_cmd_read_addr_fifo.read())]);
+              } else {			// cache line
+                r_read_to_tgt_rsp_val[i] = true;
+              }
+            }
+            cmd_read_fifo_get 		= true;
+            r_read_to_tgt_rsp_req	= true;
+            r_read_to_tgt_rsp_srcid	= m_cmd_read_srcid_fifo.read();
+            r_read_to_tgt_rsp_trdid	= m_cmd_read_trdid_fifo.read();
+            r_read_to_tgt_rsp_pktid	= m_cmd_read_pktid_fifo.read();
+            r_read_fsm 			= READ_IDLE;  
+          }
+          break;
+        }
+        ///////////////////
+      case READ_TRT_LOCK:	// read miss : check the Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t index = 0;
+            bool   hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())], index);
+            bool   hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())]);
+            bool   wok = !m_transaction_tab.full(index);
+            if( hit_read || !wok || hit_write ) {  // missing line already requested or no space
+              r_read_fsm = READ_IDLE;
+            } else {			   // missing line is requested to the XRAM
+              r_read_trt_index = index;
+              r_read_fsm       = READ_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_TRT_SET:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+            m_transaction_tab.set(r_read_trt_index.read(),
+                true,
+                m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
+                m_cmd_read_srcid_fifo.read(),
+                m_cmd_read_trdid_fifo.read(),
+                m_cmd_read_pktid_fifo.read(),
+                true,
+                m_cmd_read_word_fifo.read(),
+                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));
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_read_fsm 	 = READ_XRAM_REQ;
+          }
+          break;
+        }
+        /////////////////////
+      case READ_XRAM_REQ:
+        {
+          if( !r_read_to_ixr_cmd_req ) {
+            cmd_read_fifo_get		= true;
+            r_read_to_ixr_cmd_req  	= true;
+            r_read_to_ixr_cmd_nline 	= m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            r_read_to_ixr_cmd_trdid 	= r_read_trt_index.read();
+            r_read_fsm 			          = READ_IDLE;
+          }
+          break;
+        }
+    } // end switch read_fsm
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //		WRITE FSM
+    ///////////////////////////////////////////////////////////////////////////////////
+    // The WRITE FSM handles the write bursts 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.
+    // Then the FSM takes the lock protecting the cache directory, to check
+    // if the line is in the cache.
+    //
+    // - In case of HIT, the cache is updated.
+    //   If there is no other copy, an acknowledge response is immediately
+    //   returned to the writing processor.
+    //   if the data is cached by other processoris, the FSM takes the lock
+    //   protecting the Update Table (UPT) to register this update transaction.
+    //   If the UPT is full, it releases the lock  and waits. Then, it sends 
+    //   a multi-update request to all owners of the line (but the writer), 
+    //   through the INIT_CMD FSM. In case of multi-update transaction, the WRITE FSM 
+    //   does not respond to the writing processor, as this response will be sent by 
+    //   the INIT_RSP FSM when all update responses have been received.
+    //
+    // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
+    //   table (TRT). If a read transaction to the XRAM for this line already exists, 
+    //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free, 
+    //   the WRITE FSM register a new transaction in TRT, and sends a read line request 
+    //   to the XRAM. If the TRT is full, it releases the lock, and waits.
+    //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_write_fsm.read() ) {
+
+      ////////////////
+      case WRITE_IDLE:	// copy first word of a write burst in local buffer	
+        {
+          if ( m_cmd_write_addr_fifo.rok()) {
+            m_cpt_write++;
+            m_cpt_write_cells++;
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get	= true;
+            size_t 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();
+            r_write_srcid	    = m_cmd_write_srcid_fifo.read();
+            r_write_trdid	    = m_cmd_write_trdid_fifo.read();
+            r_write_pktid	    = m_cmd_write_pktid_fifo.read();
+#ifdef VHDL_ACCURATE
+            r_write_pass        = false;
+#endif
+
+            // the be field must be set for all words 
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              if ( i == index ) r_write_be[i] = m_cmd_write_be_fifo.read();
+              else		        r_write_be[i] = 0x0;
+            }
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+                    r_write_byte=true;
+            else    r_write_byte=false;
+
+            if( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+            else                               r_write_fsm = WRITE_NEXT;
+          }
+          break;
+        }
+        ////////////////
+      case WRITE_NEXT:	// copy next word of a write burst in local buffer
+        {
+          if ( m_cmd_write_addr_fifo.rok() ) {
+            m_cpt_write_cells++;
+
+            // check that the next word is in the same cache line
+            assert( (m_nline[(vci_addr_t)(r_write_address.read())] == m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())])  
+                && "VCI_MEM_CACHE write error in vci_mem_cache : write burst over a line" );
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get=true;
+            size_t index 	        = r_write_word_index.read() + r_write_word_count.read();
+            r_write_be[index]       = m_cmd_write_be_fifo.read();
+            r_write_data[index]     = m_cmd_write_data_fifo.read();
+            r_write_word_count 	    = r_write_word_count.read() + 1;
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+              r_write_byte=true;
+            if ( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_LOCK:	// access directory to check hit/miss
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ) {
+#ifdef VHDL_ACCURATE
+            if (!r_write_pass.read()){
+#endif
+              size_t  way = 0;
+              DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
+
+              // copy directory entry in local buffers in case of hit
+              if ( entry.valid )  {	
+                r_write_is_cnt    = entry.is_cnt;
+                r_write_lock	  = entry.lock;
+                r_write_tag       = entry.tag;
+                r_write_d_copies  = entry.d_copies;
+                r_write_i_copies  = entry.i_copies;
+                r_write_count     = entry.count;
+                r_write_way  	  = way;
+                r_write_fsm  = WRITE_DIR_LOCK;
+                r_write_pass = true;
+              } else {
+                r_write_fsm = WRITE_TRT_LOCK;
+                m_cpt_write_miss++;
+              }
+#ifdef VHDL_ACCURATE
+           } else {
+             if(r_write_is_cnt.read() && r_write_count.read()){
+               r_write_fsm     = WRITE_DIR_HIT_READ;
+             } else {
+               if(r_write_byte.read())
+                 r_write_fsm   = WRITE_DIR_HIT_READ;
+               else {
+                   bool owner     = (bool) (r_write_d_copies & (0x1 << r_write_srcid.read()));
+                   bool no_update = (owner && (r_write_count == 1)) || (r_write_count==0);
+                   if( no_update ) r_write_fsm  = WRITE_DIR_HIT_RSP; 
+                   else            r_write_fsm  = WRITE_DIR_HIT;
+               }
+             }
+             r_write_pass = false;
+           }
+#endif
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_READ:	// read the cache and complete the buffer (data, when be!=0xF)
+        {
+          // update local buffer
+          size_t set	= m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	= r_write_way.read();
+          for(size_t i=0 ; i<m_words ; i++) {
+            data_t mask      = 0;
+            if  (r_write_be[i].read() & 0x1) mask = mask | 0x000000FF;
+            if  (r_write_be[i].read() & 0x2) mask = mask | 0x0000FF00;
+            if  (r_write_be[i].read() & 0x4) mask = mask | 0x00FF0000;
+            if  (r_write_be[i].read() & 0x8) mask = mask | 0xFF000000;
+            if(r_write_be[i].read()||r_write_is_cnt.read()) { // complete only if mask is not null (for energy consumption)
+              r_write_data[i]  = (r_write_data[i].read() & mask) | 
+                (m_cache_data[way][set][i] & ~mask);
+            }
+          } // end for
+
+          if(r_write_is_cnt.read() && r_write_count.read()){
+            r_write_fsm            = WRITE_TRT_WRITE_LOCK;
+          } else {
+              bool owner     = (bool) (r_write_d_copies.read() & (0x1 << r_write_srcid.read()));
+              bool no_update = (owner && (r_write_count.read() == 1)) || (r_write_count.read()==0);
+              if( no_update )   r_write_fsm    = WRITE_DIR_HIT_RSP;
+              else              r_write_fsm    = WRITE_DIR_HIT;
+          }
+           break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT:	// update the cache (data & dirty bit)
+        {
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.dirty	    = true;
+          entry.tag	        = r_write_tag.read();
+          entry.is_cnt      = r_write_is_cnt.read();
+          entry.lock	    = r_write_lock.read();
+          entry.d_copies    = r_write_d_copies.read();
+          entry.i_copies    = r_write_i_copies.read();
+          entry.count       = r_write_count.read();
+          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	    = r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          size_t nb_copies=0;
+          for(size_t i=0; i<32 ; i++) {
+            if( r_write_d_copies.read() & (1<<i) )
+                nb_copies++;
+          }
+          for(size_t i=0; i<32 ; i++) {
+            if( r_write_i_copies.read() & (1<<i) )
+                nb_copies++;
+          }
+          assert((nb_copies == r_write_count.read()) && "MemCache Error, inconsistency in the directory");
+
+          // write data in cache
+          for(size_t i=0 ; i<m_words ; i++) {
+            if  ( r_write_be[i].read() ) {
+              m_cache_data[way][set][i]  = r_write_data[i].read();
+            }
+          } // end for
+
+          // compute the actual number of copies & the modified bit vector
+          bool owner = (bool) (r_write_d_copies.read() & (0x1 << r_write_srcid.read()));
+          copy_t d_copies = r_write_d_copies.read() & ~(0x1 << r_write_srcid.read());
+          r_write_d_copies      = d_copies;
+          size_t count_signal   = r_write_count.read();
+          if(owner){
+            count_signal        = count_signal - 1;
+          }
+          r_write_count         = count_signal;
+
+          r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_RSP:	// update the cache (data & dirty bit) (no update)
+        {
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.dirty	    = true;
+          entry.tag	        = r_write_tag.read();
+          entry.is_cnt      = r_write_is_cnt.read();
+          entry.lock	    = r_write_lock.read();
+          entry.d_copies    = r_write_d_copies.read();
+          entry.i_copies    = r_write_i_copies.read();
+          entry.count       = r_write_count.read();
+          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	    = r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          size_t nb_copies=0;
+          for(size_t i=0; i<32 ; i++) {
+            if( r_write_d_copies.read() & (1<<i) )
+                nb_copies++;
+          }
+          for(size_t i=0; i<32 ; i++) {
+            if( r_write_i_copies.read() & (1<<i) )
+                nb_copies++;
+          }
+          assert((nb_copies == r_write_count.read()) && "MemCache Error, inconsistency in the directory");
+
+          // write data in cache
+          for(size_t i=0 ; i<m_words ; i++) {
+            if  ( r_write_be[i].read() ) {
+              m_cache_data[way][set][i]  = r_write_data[i].read();
+            }
+          } // end for
+
+          if ( !r_write_to_tgt_rsp_req.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_fsm 		        = WRITE_IDLE;
+          } else {
+            r_write_fsm = WRITE_RSP;
+          }
+          break;
+        }
+        /////////////////////
+      case WRITE_UPT_LOCK: 	// Try to register the request in Update Table
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool          wok        = false;
+            size_t        index      = 0;
+            size_t        srcid      = r_write_srcid.read();
+            size_t        trdid      = r_write_trdid.read();
+            size_t        pktid      = r_write_pktid.read();
+            addr_t	      nline      = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t        nb_copies  = r_write_count.read();
+
+            wok =m_update_tab.set(true,	// it's an update transaction
+                false,                  // it's not a broadcast
+                true,                   // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_write_fsm = WRITE_UPDATE;
+            else       r_write_fsm = WRITE_WAIT_UPT;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT_UPT:	// release the lock protecting UPT
+        {
+          r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        //////////////////
+      case WRITE_UPDATE:	// send a multi-update request to INIT_CMD fsm
+        {
+
+          if ( !r_write_to_init_cmd_req ) {
+            r_write_to_init_cmd_req      = true;
+            r_write_to_init_cmd_brdcast  = false;
+            r_write_to_init_cmd_trdid    = r_write_upt_index.read();
+            r_write_to_init_cmd_nline    = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index    = r_write_word_index.read();
+            r_write_to_init_cmd_count    = r_write_word_count.read();
+            r_write_to_init_cmd_d_copies = r_write_d_copies.read();
+            r_write_to_init_cmd_i_copies = r_write_i_copies.read();
+
+            for(size_t i=0; i<m_words ; i++){
+              if(r_write_be[i].read())  r_write_to_init_cmd_we[i]=true;
+              else                      r_write_to_init_cmd_we[i]=false;
+            }
+
+            size_t min = r_write_word_index.read();
+            size_t max = r_write_word_index.read() + r_write_word_count.read();
+            for (size_t i=min ; i<max ; i++) {
+              r_write_to_init_cmd_data[i] = r_write_data[i];
+            }
+            r_write_fsm = WRITE_IDLE; // Response will be sent after receiving
+            // all update responses
+          }
+          break;
+        }
+        ///////////////
+      case WRITE_RSP:		// send a request to TGT_RSP FSM to acknowledge the write
+        {
+          if ( !r_write_to_tgt_rsp_req.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_fsm 		        = WRITE_IDLE;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_LOCK:	// Miss : check Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t hit_index = 0;
+            size_t wok_index = 0;
+            bool hit_read  = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(r_write_address.read())],hit_index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(r_write_address.read())]);
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( hit_read ) {	// register the modified data in TRT 
+              r_write_trt_index = hit_index;
+              r_write_fsm       = WRITE_TRT_DATA;
+            } else if ( wok && !hit_write ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_TRT_SET;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT_TRT;
+            }
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT_TRT:	// release the lock protecting TRT
+        { 
+          r_write_fsm = WRITE_DIR_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_TRT_SET:	// register a new transaction in TRT (Write Buffer)
+        {  
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) 
+          {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) 
+            {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.set(r_write_trt_index.read(),
+                true,				// read request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                r_write_srcid.read(),
+                r_write_trdid.read(),
+                r_write_pktid.read(),
+                false,				// not a processor read
+                false,				// not a single word 
+                0,			        	// word index
+                be_vector,
+                data_vector);
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_write_fsm = WRITE_XRAM_REQ;
+          }
+          break;
+        }  
+        ///////////////////
+      case WRITE_TRT_DATA:	// update an entry in TRT (Write Buffer)
+        { 
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.write_data_mask(r_write_trt_index.read(),
+                be_vector,
+                data_vector);
+            r_write_fsm = WRITE_RSP;
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_DATA transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_REQ:	// send a request to IXR_CMD FSM
+        {  
+
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req   = true;
+            r_write_to_ixr_cmd_write = false;
+            r_write_to_ixr_cmd_nline = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
+            r_write_fsm              = WRITE_RSP;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_WRITE_LOCK:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            size_t wok_index = 0;
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( wok ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_INVAL_LOCK;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT_TRT;
+            }
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool        wok       = false;
+            size_t      index     = 0;
+            size_t      srcid     = r_write_srcid.read();
+            size_t      trdid     = r_write_trdid.read();
+            size_t      pktid     = r_write_pktid.read();
+            addr_t	    nline     = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t      nb_copies = r_write_count.read();
+
+            wok =m_update_tab.set(false,	// it's an inval transaction
+                true,                       // it's a broadcast
+                true,                       // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_INVAL_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_write_fsm = WRITE_DIR_INVAL;
+            else       r_write_fsm = WRITE_WAIT_TRT;
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_INVAL:
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) ||
+              (r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) )
+          {
+            m_transaction_tab.set(r_write_trt_index.read(),
+                false,				// write request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                0,
+                0,
+                0,
+                false,				// not a processor read
+                false,				// not a single word 
+                0,			        	// word index
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_DIR_INVAL transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            // invalidate directory entry
+            DirectoryEntry entry;
+            entry.valid	   = false;
+            entry.dirty	   = false;
+            entry.tag	   = 0;
+            entry.is_cnt   = false;
+            entry.lock	   = false;
+            entry.d_copies = 0;
+            entry.i_copies = 0;
+            entry.count    = 0;
+            size_t set	   = m_y[(vci_addr_t)(r_write_address.read())];
+            size_t way	   = r_write_way.read();
+            m_cache_directory.write(set, way, entry);
+
+            r_write_fsm = WRITE_INVAL;
+          } else {
+            assert(false && "LOCK ERROR in WRITE_FSM, STATE = WRITE_DIR_INVAL");
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_INVAL:
+        {
+          if ( !r_write_to_init_cmd_req ) {
+            r_write_to_init_cmd_req      = true;
+            r_write_to_init_cmd_brdcast  = true;
+            r_write_to_init_cmd_trdid    = r_write_upt_index.read();
+            r_write_to_init_cmd_nline    = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index    = 0;
+            r_write_to_init_cmd_count    = 0;
+            r_write_to_init_cmd_d_copies = 0;
+            r_write_to_init_cmd_i_copies = 0;
+
+            for(size_t i=0; i<m_words ; i++){
+              r_write_to_init_cmd_we[i]=false;
+              r_write_to_init_cmd_data[i] = 0;
+            }
+            r_write_fsm = WRITE_XRAM_SEND;
+            // all update responses
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_SEND:
+        {
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req     = true;
+            r_write_to_ixr_cmd_write   = true;
+            r_write_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
+            for(size_t i=0; i<m_words; i++){
+              r_write_to_ixr_cmd_data[i] = r_write_data[i];
+            }
+            r_write_fsm                 = WRITE_IDLE;
+          }
+          break;
+        }
+    } // end switch r_write_fsm
+
+    ///////////////////////////////////////////////////////////////////////
+    //		IXR_CMD FSM
+    ///////////////////////////////////////////////////////////////////////
+    // The IXR_CMD fsm controls the command packets to the XRAM :
+    // - It sends a single cell VCI read to the XRAM in case of MISS request
+    // posted by the READ, WRITE or LLSC FSMs : the TRDID field contains 
+    // the Transaction Tab index.
+    // The VCI response is a multi-cell packet : the N cells contain
+    // the N data words.
+    // - It sends a multi-cell VCI write when the XRAM_RSP FSM request 
+    // to save a dirty line to the XRAM. 
+    // The VCI response is a single cell packet.
+    // This FSM handles requests from the READ, WRITE, LLSC & XRAM_RSP FSMs 
+    // with a round-robin priority.
+    ////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_cmd_fsm.read() ) {
+      //////////////////////// 
+      case IXR_CMD_READ_IDLE:
+        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_WRITE_IDLE:
+        if      ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_LLSC_IDLE:
+        if      ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_XRAM_IDLE:
+        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        break;
+        /////////////////////////
+      case IXR_CMD_READ_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;		
+          r_read_to_ixr_cmd_req = false;
+        }
+        break;
+        //////////////////////////
+      case IXR_CMD_WRITE_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          if( r_write_to_ixr_cmd_write.read()){
+            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+              r_ixr_cmd_cpt = 0;
+              r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
+              r_write_to_ixr_cmd_req = false;
+            } else {
+              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+            }
+          } else {
+            r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;		
+            r_write_to_ixr_cmd_req = false;
+          }
+        }
+        break;
+        /////////////////////////
+      case IXR_CMD_LLSC_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;		
+          r_llsc_to_ixr_cmd_req = false;
+        }
+        break;
+        ////////////////////////
+      case IXR_CMD_XRAM_DATA:
+        if ( p_vci_ixr.cmdack ) {
+          if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+            r_ixr_cmd_cpt = 0;
+            r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
+            r_xram_rsp_to_ixr_cmd_req = false;
+          } else {
+            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+          }
+        }
+        break;
+
+    } // end switch r_ixr_cmd_fsm
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                IXR_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The IXR_RSP FSM receives the response packets from the XRAM,
+    // for both write transaction, and read transaction.
+    //
+    // - A response to a write request is a single-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The FSM takes the lock protecting the TRT, and the corresponding
+    // entry is erased.
+    //	
+    // - A response to a read request is a multi-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The N cells contain the N words of the cache line in the RDATA field.
+    // The FSM takes the lock protecting the TRT to store the line in the TRT
+    // (taking into account the write requests already stored in the TRT).
+    // When the line is completely written, the corresponding rok signal is set.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_rsp_fsm.read() ) {
+
+      ///////////////////
+      case IXR_RSP_IDLE:	// test if it's a read or a write transaction
+        {
+          if ( p_vci_ixr.rspval ) {
+            r_ixr_rsp_cpt   = 0;
+            r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
+            if ( p_vci_ixr.reop )  r_ixr_rsp_fsm = IXR_RSP_ACK;
+            else                   r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
+          }
+          break;  
+        }
+        ////////////////////////
+      case IXR_RSP_ACK:        // Acknowledge the vci response
+        r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
+        break;
+        ////////////////////////
+      case IXR_RSP_TRT_ERASE: 	// erase the entry in the TRT
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP ) {
+            m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
+            r_ixr_rsp_fsm = IXR_RSP_IDLE;
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_ERASE transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ///////////////////////
+      case IXR_RSP_TRT_READ:		// write data in the TRT
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval ) {
+            bool   eop  	= p_vci_ixr.reop.read();
+            data_t data 	= p_vci_ixr.rdata.read();
+            size_t index        = r_ixr_rsp_trt_index.read();
+            assert( eop == (r_ixr_rsp_cpt.read() == (m_words-1)) 
+                && "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
+            m_transaction_tab.write_rsp(index, r_ixr_rsp_cpt.read(), data);
+            r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
+            if ( eop ) {
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_READ transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+              r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
+              r_ixr_rsp_fsm = IXR_RSP_IDLE;
+            }
+          }
+          break;
+        }
+    } // end swich r_ixr_rsp_fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                XRAM_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
+    // The cache line has been written in the TRT buffer by the IXR_FSM.
+    //
+    // When a response is available, the corresponding TRT entry 
+    // is copied in a local buffer to be written in the cache. 
+    // Then, the FSM releases the lock protecting the TRT, and takes the lock 
+    // protecting the cache directory.
+    // It selects a cache slot and writes the line in the cache.
+    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
+    // FSM to return the cache line to the registered processor.
+    // If there is no empty slot, a victim line is evicted, and
+    // invalidate requests are sent to the L1 caches containing copies.
+    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD 
+    // FSM to save the victim line to the XRAM, and register the write transaction
+    // in the TRT (using the entry previously used by the read transaction).
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_xram_rsp_fsm.read() ) {
+
+      ///////////////////
+      case XRAM_RSP_IDLE:	// test if there is a response with a round robin priority
+        {
+          size_t ptr   = r_xram_rsp_trt_index.read();
+          size_t lines = TRANSACTION_TAB_LINES;
+          for(size_t i=0; i<lines; i++){
+            size_t index=(i+ptr+1)%lines;
+            if(r_ixr_rsp_to_xram_rsp_rok[index]){
+              r_xram_rsp_trt_index=index;
+              r_ixr_rsp_to_xram_rsp_rok[index]=false;
+              r_xram_rsp_fsm           = XRAM_RSP_DIR_LOCK;
+              break;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_IDLE state" << std::endl;
+#endif
+            }
+          }
+          break;  
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_LOCK: 	// Take the lock on the directory
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) {
+#ifdef VHDL_ACCURATE
+            r_xram_rsp_pass          = false;
+#endif
+            r_xram_rsp_fsm           = XRAM_RSP_TRT_COPY;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_LOCK state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_TRT_COPY:		// Copy the TRT entry in the local buffer and eviction of a cache line
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) ) {
+#ifdef VHDL_ACCURATE
+            if (!r_xram_rsp_pass.read()){
+#endif
+              size_t index = r_xram_rsp_trt_index.read();
+              TransactionTabEntry    trt_entry(m_transaction_tab.read(index));	
+
+              r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
+
+              // selects & extracts a victim line from cache
+              size_t way = 0;
+              size_t set = m_y[(vci_addr_t)(trt_entry.nline * m_words * 4)];
+              DirectoryEntry victim(m_cache_directory.select(set, way));
+
+              for (size_t i=0 ; i<m_words ; i++) r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
+
+              bool inval = (victim.count && victim.valid) ;
+
+              r_xram_rsp_victim_d_copies = victim.d_copies;
+              r_xram_rsp_victim_i_copies = victim.i_copies;
+              r_xram_rsp_victim_count    = victim.count;
+              r_xram_rsp_victim_way      = way;
+              r_xram_rsp_victim_set      = set;
+              r_xram_rsp_victim_nline    = victim.tag*m_sets + set;
+              r_xram_rsp_victim_is_cnt   = victim.is_cnt;
+              r_xram_rsp_victim_inval    = inval ;
+              r_xram_rsp_victim_dirty    = victim.dirty;
+
+#ifdef VHDL_ACCURATE
+              r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
+#else
+              r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
+#endif
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_TRT_COPY state" << std::endl;
+	std::cout << "Victim way : " << std::hex << way << " set " << std::hex << set << std::endl;
+	victim.print();
+#endif
+#ifdef VHDL_ACCURATE
+                r_xram_rsp_pass = true;
+              }else{
+                r_xram_rsp_pass = false;
+                r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
+              }
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP ) {
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state" << std::endl;
+#endif
+            size_t index;
+            if(m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index)){
+              r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+
+            }
+	    else if(m_update_tab.is_full() && r_xram_rsp_victim_inval.read()){
+	      r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+	    }
+            else {
+              r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_DIR_UPDT state" << std::endl;
+#endif
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_WAIT:
+        {
+          r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
+          break;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_UPDT:		// updates the cache (both data & directory)
+        {
+          // signals generation
+          bool inst_read = (r_xram_rsp_trt_buf.trdid & 0x2) && r_xram_rsp_trt_buf.proc_read; // It is an instruction read
+          bool cached_read = (r_xram_rsp_trt_buf.trdid & 0x1) && r_xram_rsp_trt_buf.proc_read ;
+          // update data
+          size_t set   = r_xram_rsp_victim_set.read();
+          size_t way   = r_xram_rsp_victim_way.read();
+          for(size_t i=0; i<m_words ; i++){
+            m_cache_data[way][set][i] = r_xram_rsp_trt_buf.wdata[i];
+          }
+          // compute dirty 
+          bool dirty = false;
+          for(size_t i=0; i<m_words;i++){
+            dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
+          }
+
+          // update directory
+          DirectoryEntry entry;
+          entry.valid	  = true;
+          entry.is_cnt    = false;
+          entry.lock	  = false;
+          entry.dirty	  = dirty;
+          entry.tag	    = r_xram_rsp_trt_buf.nline / m_sets;
+          if(cached_read) {
+            if(inst_read) {
+              entry.i_copies = 0x1 << r_xram_rsp_trt_buf.srcid;
+              entry.d_copies = 0x0;
+              entry.count    = 1;
+            } else {
+              entry.i_copies = 0x0;
+              entry.d_copies = 0x1 << r_xram_rsp_trt_buf.srcid;
+              entry.count    = 1;
+            }
+          } else {
+            entry.d_copies = 0;
+            entry.i_copies = 0;
+            entry.count    = 0;
+          }
+          m_cache_directory.write(set, way, entry);
+#ifdef IDEBUG
+	   std::cout << "printing the entry : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_DIR_UPDT transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          if(r_xram_rsp_victim_inval.read()){
+            bool    brdcast = r_xram_rsp_victim_is_cnt.read();
+            size_t index;
+            size_t count_copies = r_xram_rsp_victim_count.read();
+
+            bool	 wok = m_update_tab.set(false,	// it's an inval transaction
+                brdcast,                          // set brdcast bit
+                false,  // it does not need a response
+                0,
+                0,
+                0,
+                r_xram_rsp_victim_nline.read(),
+                count_copies,
+                index);
+
+#ifdef IDEBUG
+            std::cout << "xram_rsp : record invalidation, time = " << std::dec << m_cpt_cycles << std::endl;
+            m_update_tab.print();
+#endif
+            r_xram_rsp_upt_index = index;
+            if(!wok) {
+              assert(false && "mem_cache error : xram_rsp_dir_upt, an update_tab entry was free but write unsuccessful");
+            }
+          }
+          // If the victim is not dirty, we erase the entry in the TRT
+          if      (!r_xram_rsp_victim_dirty.read()){
+	  m_transaction_tab.erase(r_xram_rsp_trt_index.read());
+
+	  }
+          // Next state
+          if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
+          else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+          else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+          else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          break;
+        }
+        ////////////////////////
+      case XRAM_RSP_TRT_DIRTY:		// set the TRT entry (write line to XRAM) if the victim is dirty
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP ) {
+            m_transaction_tab.set(r_xram_rsp_trt_index.read(),
+                false,				// write to XRAM
+                r_xram_rsp_victim_nline.read(), // line index
+                0,
+                0,
+                0,
+                false,
+                false,
+                0,
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0) );
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_TRT_DIRTY transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+          }
+          break;
+        }
+        //////////////////////
+      case XRAM_RSP_DIR_RSP:     // send a request to TGT_RSP FSM in case of read
+        {
+          if ( !r_xram_rsp_to_tgt_rsp_req ) {
+            r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
+            r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
+            r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
+            for (size_t i=0; i < m_words; i++) {
+              r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
+              if( r_xram_rsp_trt_buf.single_word ) {
+                r_xram_rsp_to_tgt_rsp_val[i] = (r_xram_rsp_trt_buf.word_index == i);
+              } else {
+                r_xram_rsp_to_tgt_rsp_val[i] = true;
+              }
+            } 
+            r_xram_rsp_to_tgt_rsp_req   = true;
+
+            if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY; 
+            else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_RSP state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ////////////////////
+      case XRAM_RSP_INVAL:	// send invalidate request to INIT_CMD FSM
+        {
+          if( !r_xram_rsp_to_init_cmd_req ) {	      
+            r_xram_rsp_to_init_cmd_req      = true; 
+            r_xram_rsp_to_init_cmd_brdcast  = r_xram_rsp_victim_is_cnt.read();
+            r_xram_rsp_to_init_cmd_nline    = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_init_cmd_trdid    = r_xram_rsp_upt_index;
+            r_xram_rsp_to_init_cmd_d_copies = r_xram_rsp_victim_d_copies ;
+            r_xram_rsp_to_init_cmd_i_copies = r_xram_rsp_victim_i_copies ;
+            if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+            else		                    r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL state" << std::endl;
+#endif
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_WRITE_DIRTY:	// send a write request to IXR_CMD FSM
+        {
+          if ( !r_xram_rsp_to_ixr_cmd_req ) {
+            r_xram_rsp_to_ixr_cmd_req = true;
+            r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
+            for(size_t i=0; i<m_words ; i++) {
+              r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
+            }
+            m_cpt_write_dirty++;
+            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_WRITE_DIRTY state" << std::endl;
+#endif
+          }
+          break;
+        }
+    } // end swich r_xram_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		CLEANUP FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The CLEANUP FSM handles the cleanup request from L1 caches.
+    // It accesses the cache directory to update the list of copies.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+    switch ( r_cleanup_fsm.read() ) {
+
+      ///////////////////
+      case CLEANUP_IDLE:
+        {
+
+          if ( p_vci_tgt_cleanup.cmdval.read() ) {
+            assert( (p_vci_tgt_cleanup.srcid.read() < m_initiators) &&
+                "VCI_MEM_CACHE error in VCI_MEM_CACHE in the CLEANUP network : The received SRCID is larger than 31");
+            bool reached = false;
+            for ( size_t index = 0 ; index < ncseg && !reached ; index++ ){
+              if ( m_cseg[index]->contains((addr_t)(p_vci_tgt_cleanup.address.read())) ){
+                reached = true;
+              }
+            }
+            if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
+                (((addr_t)(p_vci_tgt_cleanup.address.read())) != BROADCAST_ADDR) &&
+                reached) {
+
+              m_cpt_cleanup++;
+
+              r_cleanup_nline      = (addr_t)(m_nline[(vci_addr_t)(p_vci_tgt_cleanup.address.read())]) ;
+              r_cleanup_srcid      = p_vci_tgt_cleanup.srcid.read();
+              r_cleanup_trdid      = p_vci_tgt_cleanup.trdid.read();
+              r_cleanup_pktid      = p_vci_tgt_cleanup.pktid.read();
+
+#ifdef VHDL_ACCURATE
+              r_cleanup_pass       = false;
+#endif
+              r_cleanup_fsm        = CLEANUP_DIR_LOCK;
+            }
+          }
+          break;
+        }
+        //////////////////////
+      case CLEANUP_DIR_LOCK:
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) {
+#ifdef VHDL_ACCURATE
+            if (!r_cleanup_pass.read()){
+#endif
+              // Read the directory
+              size_t way = 0;
+	          addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
+              DirectoryEntry entry = m_cache_directory.read(cleanup_address , way);
+#ifdef IDEBUG
+	   std::cout << "In CLEANUP_DIR_LOCK printing the entry of address is : " << std::hex << cleanup_address << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+              r_cleanup_is_cnt    = entry.is_cnt;
+              r_cleanup_dirty	    = entry.dirty;
+              r_cleanup_tag	    = entry.tag;
+              r_cleanup_lock	    = entry.lock;
+              r_cleanup_way	    = way;
+              r_cleanup_d_copies  = entry.d_copies;
+              r_cleanup_i_copies  = entry.i_copies;
+              r_cleanup_count     = entry.count;
+
+              // In case of hit, the copy must be cleaned in the copies bit-vector
+              if( entry.valid )  { 
+                r_cleanup_fsm = CLEANUP_DIR_LOCK;
+              } else {
+                r_cleanup_fsm = CLEANUP_UPT_LOCK;
+              }
+#ifdef VHDL_ACCURATE
+              r_cleanup_pass = true;
+            }else{
+              r_cleanup_pass = false;
+              r_cleanup_fsm  = CLEANUP_DIR_WRITE;
+            }
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case CLEANUP_DIR_WRITE:
+        {
+          size_t way      = r_cleanup_way.read();
+#define L2 soclib::common::uint32_log2
+          size_t set      = m_y[(vci_addr_t)(r_cleanup_nline.read() << (L2(m_words) +2))];
+#undef L2
+          bool cleanup_inst  = r_cleanup_trdid.read() & 0x1; 
+
+          // update the cache directory (for the copies)
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.is_cnt  = r_cleanup_is_cnt.read();
+          entry.dirty	= r_cleanup_dirty.read();
+          entry.tag	= r_cleanup_tag.read();
+          entry.lock	= r_cleanup_lock.read();
+          if(r_cleanup_is_cnt.read()) { // Directory is a counter
+            entry.count  = r_cleanup_count.read() -1;
+            entry.i_copies = 0;
+            entry.d_copies = 0;
+            // response to the cache 
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          else{                         // Directory is a vector
+            if(cleanup_inst){           // Cleanup from a ICACHE
+              if(r_cleanup_i_copies.read() & (0x1 << r_cleanup_srcid.read())){ // hit
+                entry.count  = r_cleanup_count.read() -1;
+                r_cleanup_fsm = CLEANUP_RSP;
+              } else { // miss
+                assert(false && "MemCache ERROR : Cleanup instruction hit but the line is not shared");
+              }
+              entry.i_copies  = r_cleanup_i_copies.read() & ~(0x1 << r_cleanup_srcid.read());
+              entry.d_copies  = r_cleanup_d_copies.read();
+            } else {                    // Cleanup from a DCACHE
+              if(r_cleanup_d_copies.read() & (0x1 << r_cleanup_srcid.read())){ // hit
+                entry.count  = r_cleanup_count.read() -1;
+                r_cleanup_fsm = CLEANUP_RSP; 
+              } else { // miss
+                assert(false && "MemCache ERROR : Cleanup data hit but the line is not shared");
+              }
+              entry.i_copies  = r_cleanup_i_copies.read();
+              entry.d_copies  = r_cleanup_d_copies.read() & ~(0x1 << r_cleanup_srcid.read());
+            }
+          }
+          m_cache_directory.write(set, way, entry);  
+
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_LOCK:
+        {
+          if( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
+          {
+            size_t index=0;
+            bool hit_inval;
+            hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
+            if(!hit_inval) {
+#ifdef DEBUG_VCI_MEM_CACHE
+              std::cout << "MEM_CACHE WARNING: cleanup with no corresponding entry at address : " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::dec << std::endl;
+#endif
+              r_cleanup_fsm = CLEANUP_RSP;
+            } else {
+              r_cleanup_write_srcid = m_update_tab.srcid(index);
+              r_cleanup_write_trdid = m_update_tab.trdid(index);
+              r_cleanup_write_pktid = m_update_tab.pktid(index);
+              r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
+              r_cleanup_fsm = CLEANUP_UPT_WRITE;
+            }
+            r_cleanup_index.write(index) ; 
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_WRITE:
+        {
+          size_t count = 0;
+          m_update_tab.decrement(r_cleanup_index.read(), count); // &count
+          if(count == 0){
+            m_update_tab.clear(r_cleanup_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " CLEANUP_UPT_WRITE update table : " << std::endl;
+	m_update_tab.print();
+#endif
+
+            if(r_cleanup_need_rsp.read()){
+              r_cleanup_fsm = CLEANUP_WRITE_RSP ;
+            } else {
+              r_cleanup_fsm = CLEANUP_RSP;
+            }
+          } else {
+            r_cleanup_fsm = CLEANUP_RSP ;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_WRITE_RSP:
+        {
+          if( !r_cleanup_to_tgt_rsp_req.read()) {
+            r_cleanup_to_tgt_rsp_req     = true;
+            r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
+            r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
+            r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_RSP:
+        {
+          if(p_vci_tgt_cleanup.rspack)
+            r_cleanup_fsm = CLEANUP_IDLE;
+          break;
+        }
+    } // end switch cleanup fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		LLSC FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The LLSC FSM handles the LL & SC atomic access.
+    //
+    // For a LL :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the LL request is registered in the Atomic Table and the
+    // response is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state.
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the LL request is not consumed in the FIFO.
+    //
+    // For a SC :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the Atomic Table is checked and the proper response
+    // (true or false is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state. 
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the SC request is not consumed in the FIFO.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_llsc_fsm.read() ) {
+
+      ///////////////
+      case LLSC_IDLE:		// test LL / SC
+        {
+          if( m_cmd_llsc_addr_fifo.rok() ) {
+#ifdef VHDL_ACCURATE
+            r_llsc_pass = false;
+#endif
+            if(m_cmd_llsc_sc_fifo.read()){
+              m_cpt_sc++;
+              r_llsc_fsm = SC_DIR_LOCK;
+            }
+            else{
+              m_cpt_ll++;
+              r_llsc_fsm = LL_DIR_LOCK;
+            }
+          }	
+          break;
+        }
+        /////////////////
+      case LL_DIR_LOCK:		// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+#ifdef VHDL_ACCURATE
+            if (!r_llsc_pass.read()){
+#endif
+              size_t way = 0;
+              DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+              r_llsc_is_cnt     = entry.is_cnt;
+              r_llsc_dirty      = entry.dirty;
+              r_llsc_tag        = entry.tag;
+              r_llsc_way        = way;
+              r_llsc_d_copies   = entry.d_copies;
+              r_llsc_i_copies   = entry.i_copies ;
+              r_llsc_count      = entry.count ;
+
+              if ( entry.valid )  r_llsc_fsm = LL_DIR_LOCK;
+              else                r_llsc_fsm = LLSC_TRT_LOCK;
+#ifdef VHDL_ACCURATE
+              r_llsc_pass        = true;
+            }else{
+              r_llsc_pass        = false;
+              r_llsc_fsm         = LL_DIR_HIT;
+            }
+#endif
+          }
+          break;
+        }
+        ////////////////
+      case LL_DIR_HIT:		// read hit : update the memory cache
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+
+          // update directory (lock bit & copies)
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.is_cnt      = r_llsc_is_cnt.read();
+          entry.dirty	    = r_llsc_dirty.read();
+          entry.lock	    = true;
+          entry.tag	        = r_llsc_tag.read();
+          entry.d_copies    = r_llsc_d_copies.read();
+          entry.i_copies    = r_llsc_i_copies.read();
+          entry.count       = r_llsc_count.read();
+          m_cache_directory.write(set, way, entry);
+
+          // read data in cache
+          r_llsc_data	= m_cache_data[way][set][word];
+
+          // set Atomic Table
+          m_atomic_tab.set(m_cmd_llsc_srcid_fifo.read(), m_cmd_llsc_addr_fifo.read());
+
+          r_llsc_fsm 	= LL_RSP;
+          break;
+        }
+        ////////////
+      case LL_RSP:		// request the TGT_RSP FSM to return data
+        {
+          if ( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_data	= r_llsc_data.read();
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_fsm = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_DIR_LOCK:
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+#ifdef VHDL_ACCURATE
+            if(!r_llsc_pass.read()){
+#endif
+              size_t way = 0;
+              DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+              bool ok = m_atomic_tab.isatomic(m_cmd_llsc_srcid_fifo.read(),m_cmd_llsc_addr_fifo.read());
+              if( ok ) {
+                r_llsc_is_cnt   = entry.is_cnt;
+                r_llsc_dirty    = entry.dirty;
+                r_llsc_tag      = entry.tag;
+                r_llsc_way      = way;
+                r_llsc_d_copies = entry.d_copies;
+                r_llsc_i_copies = entry.i_copies;
+                r_llsc_count    = entry.count;
+                if ( entry.valid )  r_llsc_fsm = SC_DIR_LOCK;
+                else                r_llsc_fsm = LLSC_TRT_LOCK;
+              } else {
+                r_llsc_fsm = SC_RSP_FALSE;
+              }
+#ifdef VHDL_ACCURATE
+              r_llsc_pass       = true;
+            }else{
+              r_llsc_pass       = false;
+              r_llsc_fsm        = SC_DIR_HIT;
+            }
+#endif
+          }
+          break;
+        }
+        ////////////////
+      case SC_DIR_HIT:
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+
+          // update directory (lock & dirty bits
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.is_cnt      = r_llsc_is_cnt.read();
+          entry.dirty	    = true;
+          entry.lock	    = true;
+          entry.tag	        = r_llsc_tag.read();
+          entry.d_copies    = r_llsc_d_copies.read();
+          entry.i_copies    = r_llsc_i_copies.read();
+          entry.count       = r_llsc_count.read();
+          m_cache_directory.write(set, way, entry);
+
+          // write data in cache
+          m_cache_data[way][set][word] = m_cmd_llsc_wdata_fifo.read();
+
+          // reset Atomic Table
+          m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+
+          r_llsc_fsm = SC_RSP_TRUE;
+          break;
+        }
+        //////////////////
+      case SC_RSP_FALSE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 1;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_RSP_TRUE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get	    = true;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 0;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_TRT_LOCK:         // read or write miss : check the Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            size_t   index = 0;
+            bool hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]);
+            bool wok = !m_transaction_tab.full(index);
+
+            if ( hit_read || !wok || hit_write ) {  // missing line already requested or no space in TRT
+              r_llsc_fsm = LLSC_IDLE;
+            } else {
+              r_llsc_trt_index = index;
+              r_llsc_fsm       = LLSC_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case LLSC_TRT_SET:	// register the XRAM transaction in Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            bool proc_read = !m_cmd_llsc_sc_fifo.read();
+            if(proc_read){
+              m_transaction_tab.set(r_llsc_trt_index.read(),
+                  true,
+                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
+                  m_cmd_llsc_srcid_fifo.read(),
+                  m_cmd_llsc_trdid_fifo.read(),
+                  m_cmd_llsc_pktid_fifo.read(),
+                  true,
+                  true,
+                  m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())],
+                  std::vector<be_t>(m_words,0),
+                  std::vector<data_t>(m_words,0));
+            }else{
+              m_transaction_tab.set(r_llsc_trt_index.read(),
+                  true,
+                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
+                  m_cmd_llsc_srcid_fifo.read(),
+                  m_cmd_llsc_trdid_fifo.read(),
+                  m_cmd_llsc_pktid_fifo.read(),
+                  false,
+                  false,
+                  0,
+                  std::vector<be_t>(m_words,0),
+                  std::vector<data_t>(m_words,0));
+            }
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " LLSC_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_llsc_fsm = LLSC_XRAM_REQ;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_XRAM_REQ:	// request the IXR_CMD FSM to fetch the missing line
+        {
+          if ( !r_llsc_to_ixr_cmd_req ) {
+            r_llsc_to_ixr_cmd_req        = true;
+            r_llsc_to_ixr_cmd_trdid      = r_llsc_trt_index.read();
+            r_llsc_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()];
+            if( m_cmd_llsc_sc_fifo.read() ) {
+              r_llsc_fsm                 = SC_RSP_FALSE;
+            } else {
+              cmd_llsc_fifo_get          = true;
+              r_llsc_fsm                 = LLSC_IDLE;
+            }
+          }
+          break;
+        }
+    } // end switch r_llsc_fsm
+
+
+    //////////////////////////////////////////////////////////////////////////////
+    //		INIT_CMD FSM
+    //////////////////////////////////////////////////////////////////////////////
+    // The INIT_CMD fsm controls the VCI CMD initiator port, used to update
+    // or invalidate cache lines in L1 caches.
+    // It implements a round-robin priority between the two following requests:
+    // - r_write_to_init_cmd_req : update request from WRITE FSM 
+    // - r_xram_rsp_to_init_cmd_req : invalidate request from XRAM_RSP FSM 
+    // The inval request is a single cell VCI write command containing the 
+    // index of the line to be invalidated.
+    // The update request is a multi-cells VCI write command : The first cell 
+    // contains the index of the cache line to be updated. The second cell contains 
+    // the index of the first modified word in the line. The following cells
+    // contain the data.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      //////////////////////// 
+      case INIT_CMD_UPDT_IDLE:	// Invalidate requests have highest priority
+        {
+
+          if ( r_xram_rsp_to_init_cmd_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          } else if ( r_write_to_init_cmd_req.read() ) {
+            if(r_write_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+              m_cpt_update++;
+            }
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_INVAL_IDLE:	// Update requests have highest priority
+        {
+          if ( r_write_to_init_cmd_req.read() ) {
+            if(r_write_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+              m_cpt_update++;
+            }
+          } else if ( r_xram_rsp_to_init_cmd_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_INVAL_SEL:	// selects L1 caches
+        {
+          if(r_xram_rsp_to_init_cmd_brdcast.read()){
+            m_cpt_inval_brdcast++;
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            break;
+          }
+          if ((r_xram_rsp_to_init_cmd_d_copies.read() == 0) &&
+              (r_xram_rsp_to_init_cmd_i_copies.read() == 0)) {	// no more copies
+            r_xram_rsp_to_init_cmd_req = false;
+            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+            break;
+          }
+          m_cpt_inval_mult++;
+          copy_t copies;
+          bool inst = false;
+          if(r_xram_rsp_to_init_cmd_i_copies.read()){
+            copies = r_xram_rsp_to_init_cmd_i_copies.read();
+            inst = true;
+          } else {
+            copies = r_xram_rsp_to_init_cmd_d_copies.read();
+          }
+          copy_t mask   = 0x1;
+          for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+            if ( copies & mask ) {
+              r_init_cmd_target = i;
+              break;
+            }
+            mask = mask << 1;
+          } // end for 
+          r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+          r_init_cmd_inst = inst;
+          if(inst){
+            r_xram_rsp_to_init_cmd_i_copies = copies & ~mask;
+          } else {
+            r_xram_rsp_to_init_cmd_d_copies = copies & ~mask;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_INVAL_NLINE:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ) {
+            if ( r_xram_rsp_to_init_cmd_brdcast.read() ) {
+              r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+              r_xram_rsp_to_init_cmd_req = false;
+            }
+            else r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+          }
+          break;
+        }
+        ///////////////////////
+     case INIT_CMD_UPDT_SEL:	// selects the next L1 cache
+       {
+         if ((r_write_to_init_cmd_i_copies.read() == 0) &&
+             (r_write_to_init_cmd_d_copies.read() == 0)) {	// no more copies
+           r_write_to_init_cmd_req = false;
+           r_init_cmd_fsm    = INIT_CMD_UPDT_IDLE;
+         } else {						// select the first target
+           copy_t copies;
+           bool inst = false;
+           if(r_write_to_init_cmd_i_copies.read()){
+             inst   = true;
+             copies = r_write_to_init_cmd_i_copies.read();
+           } else {
+             copies = r_write_to_init_cmd_d_copies.read();
+           } 
+           copy_t mask   = 0x1;
+           for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+             if ( copies & mask ) {
+               r_init_cmd_target = i;
+               break;
+             }
+             mask = mask << 1;
+           } // end for 
+           r_init_cmd_fsm    = INIT_CMD_UPDT_NLINE;
+           r_init_cmd_inst = inst;
+           if(inst){
+             r_write_to_init_cmd_i_copies = copies & ~mask;
+           } else {
+             r_write_to_init_cmd_d_copies = copies & ~mask;
+           }
+           r_init_cmd_cpt    = 0;
+           m_cpt_update_mult++;
+         }
+         break;
+       }
+       /////////////////////////
+      case INIT_CMD_BRDCAST:
+        {
+          if( p_vci_ini.cmdack ) {
+            r_write_to_init_cmd_req = false;
+            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+     case INIT_CMD_UPDT_NLINE:	// send the cache line index
+       {
+         if ( p_vci_ini.cmdack ){
+             r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
+         }
+         break;
+       }
+        /////////////////////////
+      case INIT_CMD_UPDT_INDEX:	// send the first word index
+        {
+
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) ) {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+            } else {
+              r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+    } // end switch r_init_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_RSP FSM
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_RSP fsm sends the responses on the VCI target port
+    // with a round robin priority between six requests :
+    // - r_read_to_tgt_rsp_req
+    // - r_write_to_tgt_rsp_req
+    // - r_llsc_to_tgt_rsp_req
+    // - r_cleanup_to_tgt_rsp_req
+    // - r_init_rsp_to_tgt_rsp_req
+    // - r_xram_rsp_to_tgt_rsp_req
+    // The  ordering is :  read > write > llsc > cleanup > xram > init
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      ///////////////////////
+      case TGT_RSP_READ_IDLE:		// write requests have the highest priority
+        {
+
+          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          break;
+        }
+        ////////////////////////
+      case TGT_RSP_WRITE_IDLE:		// llsc requests have the highest priority
+        {
+
+          if      ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_LLSC_IDLE:		// cleanup requests have the highest priority
+        {
+
+          if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          break;
+        }
+      case TGT_RSP_XRAM_IDLE:		// init requests have the highest priority
+        {
+
+          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_INIT_IDLE:		// cleanup requests have the highest priority
+        {
+          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_CLEANUP_IDLE:		// read requests have the highest priority
+        {
+          if      ( r_read_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_READ_TEST;
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_XRAM_TEST;
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ_TEST:		// test if word or cache line
+        {
+          bool 		line = true;
+          size_t	index;
+          for ( size_t i=0; i< m_words ; i++ ) {
+            line = line && r_read_to_tgt_rsp_val[i];
+            if ( r_read_to_tgt_rsp_val[i] ) index = i;
+          }
+          if ( line ) {
+            r_tgt_rsp_cpt = 0;
+            r_tgt_rsp_fsm = TGT_RSP_READ_LINE;
+          } else {
+            r_tgt_rsp_cpt = index;
+            r_tgt_rsp_fsm = TGT_RSP_READ_WORD;
+          } 
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ_WORD:		// send one word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
+            r_read_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ_LINE:		// send one complete cache line
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (m_words-1) ) {
+              r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
+              r_read_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_WRITE:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
+            r_write_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_CLEANUP:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
+            r_cleanup_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        //////////////////
+      case TGT_RSP_LLSC:		// send one atomic word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_LLSC_IDLE;
+            r_llsc_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+
+      case TGT_RSP_XRAM_TEST:		// test if word or cache line
+        {
+          bool 	line = true;
+          size_t	index;
+          for ( size_t i=0; i< m_words ; i++ ) {
+            line = line && r_xram_rsp_to_tgt_rsp_val[i];
+            if ( r_xram_rsp_to_tgt_rsp_val[i] ) index = i;
+          }
+          if ( line ) {
+            r_tgt_rsp_cpt = 0;
+            r_tgt_rsp_fsm = TGT_RSP_XRAM_LINE;
+          } else {
+            r_tgt_rsp_cpt = index;
+            r_tgt_rsp_fsm = TGT_RSP_XRAM_WORD;
+          } 
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_XRAM_WORD:		// send one word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
+            r_xram_rsp_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_XRAM_LINE:		// send one complete cache line
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (m_words-1) ) {
+              r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
+              r_xram_rsp_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_INIT:		// send the pending write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
+            r_init_rsp_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+    } // end switch tgt_rsp_fsm
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		NEW ALLOC_UPT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
+    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP 
+    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
+    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
+    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
+    // - The CLEANUP  FSM decrement an entry in UPT.
+    // The resource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_upt_fsm.read() ) {
+
+      ////////////////////////
+      case ALLOC_UPT_INIT_RSP:
+        if ( (r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK) && 
+             (r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR) ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_UPT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_UPT_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+        }
+        break;
+
+        ////////////////////////
+      case ALLOC_UPT_XRAM_RSP:
+        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK) 
+        { 
+          if       (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)   r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK) r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))    r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+        }
+        break;
+
+        //////////////////////////
+      case ALLOC_UPT_CLEANUP:
+        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK)
+        {
+          if 	   (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+        }
+        break;
+
+    } // end switch r_alloc_upt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_DIR FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_DIR FSM allocates the access to the directory and
+    // the data cache with a round robin priority between 5 user FSMs :
+    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
+    // The ressource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_dir_fsm.read() ) {
+
+      ////////////////////
+      case ALLOC_DIR_READ:
+        if ( ( (r_read_fsm.read() != READ_DIR_LOCK) &&
+              (r_read_fsm.read() != READ_TRT_LOCK)     )
+            ||
+            ( (r_read_fsm.read()      == READ_TRT_LOCK)  &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)    )  ) 
+        {
+          if        (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_DIR_WRITE:
+        if ( ( (r_write_fsm.read() != WRITE_DIR_LOCK)     &&
+              (r_write_fsm.read() != WRITE_TRT_LOCK)     &&
+              (r_write_fsm.read() != WRITE_DIR_HIT_READ) &&
+              (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+              (r_write_fsm.read() != WRITE_INVAL_LOCK) )
+            ||
+            ( (r_write_fsm.read()     == WRITE_TRT_LOCK) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
+        {
+          if        ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+        }
+        break;
+
+        ////////////////////
+      case ALLOC_DIR_LLSC:
+        if ( ( (r_llsc_fsm.read() != LL_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != LL_DIR_HIT )    &&
+              (r_llsc_fsm.read() != SC_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != SC_DIR_HIT )    &&
+              (r_llsc_fsm.read() != LLSC_TRT_LOCK )    )
+            || 
+            ( (r_llsc_fsm.read()      == LLSC_TRT_LOCK ) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC)    ) )
+        {
+          if      (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)  r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+        }
+        break;
+
+        ///////////////////////
+      case ALLOC_DIR_CLEANUP:
+        if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
+            (r_cleanup_fsm.read() != CLEANUP_DIR_WRITE) )
+        {
+          if        (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if   (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_DIR_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)   && 
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
+        {
+          if      (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if ( (r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))         r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+        }
+        break;
+
+    } // end switch alloc_dir_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_TRT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
+    // with a round robin priority between 4 user FSMs :
+    // The cyclic priority is READ > WRITE > LLSC > XRAM_RSP
+    // The ressource is always allocated.
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    switch (r_alloc_trt_fsm) {
+
+      ////////////////////
+      case ALLOC_TRT_READ:
+        if ( r_read_fsm.read() != READ_TRT_LOCK ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if (r_llsc_fsm.read() == LLSC_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ) )    r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+        }
+        break;
+        /////////////////////
+      case ALLOC_TRT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_TRT_LOCK) &&
+             (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      (r_llsc_fsm.read() == LLSC_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+        }
+        break;
+        ////////////////////
+      case ALLOC_TRT_LLSC:
+        if ( r_llsc_fsm.read() != LLSC_TRT_LOCK )
+        { 
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)     ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT)   &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)) {
+          if      ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)    ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if (r_llsc_fsm.read() == LLSC_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_IXR_RSP:
+        if ( (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
+            (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ) ) {
+          if      (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if (r_llsc_fsm.read() == LLSC_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+        }
+        break;
+
+    } // end switch alloc_trt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to READ FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_read_fifo_put ) {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_word_fifo.put_and_get((p_vci_tgt.plen.read() == 4));
+        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+      } else {
+        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_word_fifo.simple_put((p_vci_tgt.plen.read() == 4));
+        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+      }
+    } else {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.simple_get();
+        m_cmd_read_word_fifo.simple_get();
+        m_cmd_read_srcid_fifo.simple_get();
+        m_cmd_read_trdid_fifo.simple_get();
+        m_cmd_read_pktid_fifo.simple_get();
+      }
+    }
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to WRITE FIFO
+    /////////////////////////////////////////////////////////////////////
+
+    if ( cmd_write_fifo_put ) {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
+      } else {
+        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
+      }
+    } else {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.simple_get();
+        m_cmd_write_eop_fifo.simple_get();
+        m_cmd_write_srcid_fifo.simple_get();
+        m_cmd_write_trdid_fifo.simple_get();
+        m_cmd_write_pktid_fifo.simple_get();
+        m_cmd_write_data_fifo.simple_get();
+        m_cmd_write_be_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to LLSC FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_llsc_fifo_put ) {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_sc_fifo.put_and_get(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
+      } else {
+        m_cmd_llsc_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_sc_fifo.simple_put(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
+      }
+    } else {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.simple_get();
+        m_cmd_llsc_sc_fifo.simple_get();
+        m_cmd_llsc_srcid_fifo.simple_get();
+        m_cmd_llsc_trdid_fifo.simple_get();
+        m_cmd_llsc_pktid_fifo.simple_get();
+        m_cmd_llsc_wdata_fifo.simple_get();
+      }
+    }
+
+  //////////////////////////////////////////////////////////////
+    m_cpt_cycles++;
+
+  } // end transition()
+
+  /////////////////////////////
+  tmpl(void)::genMoore()
+    /////////////////////////////
+  {
+    ////////////////////////////////////////////////////////////
+    // Command signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////////////
+
+
+    p_vci_ixr.be      = 0xF;
+    p_vci_ixr.pktid   = 0;
+    p_vci_ixr.srcid   = m_srcid_ixr;
+    p_vci_ixr.cons    = false;
+    p_vci_ixr.wrap    = false;
+    p_vci_ixr.contig  = true;
+    p_vci_ixr.clen    = 0;
+    p_vci_ixr.cfixed  = false;
+
+    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_LLSC_NLINE ) {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)(r_llsc_to_ixr_cmd_nline.read()*m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
+      if(r_write_to_ixr_cmd_write.read()){
+        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+      } else {
+        p_vci_ixr.cmd     = vci_param::CMD_READ;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = 0x00000000;
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = true;
+      }
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
+      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+    } else {
+      p_vci_ixr.cmdval  = false;
+      p_vci_ixr.address = 0;
+      p_vci_ixr.plen    = 0;
+      p_vci_ixr.wdata   = 0;
+      p_vci_ixr.trdid   = 0;
+      p_vci_ixr.eop	= false;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////
+
+    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
+          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) || 
+        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
+    else                                        p_vci_ixr.rspack = false;
+
+    ////////////////////////////////////////////////////
+    // Command signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+
+    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
+      case TGT_CMD_IDLE:
+        p_vci_tgt.cmdack  = false;
+        break;
+      case TGT_CMD_READ:
+        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
+        break;
+      case TGT_CMD_READ_EOP:
+        p_vci_tgt.cmdack  = true;
+        break;
+      case TGT_CMD_WRITE:
+        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
+        break;
+      case TGT_CMD_ATOMIC:
+        p_vci_tgt.cmdack  = m_cmd_llsc_addr_fifo.wok();
+        break;
+      default:
+        p_vci_tgt.cmdack = false;
+        break;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      case TGT_RSP_READ_IDLE:
+      case TGT_RSP_WRITE_IDLE:
+      case TGT_RSP_LLSC_IDLE:
+      case TGT_RSP_XRAM_IDLE:
+      case TGT_RSP_INIT_IDLE:
+      case TGT_RSP_CLEANUP_IDLE:
+      case TGT_RSP_READ_TEST:
+      case TGT_RSP_XRAM_TEST:
+
+        p_vci_tgt.rspval  = false;
+        p_vci_tgt.rsrcid  = 0;
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rpktid  = 0;
+        p_vci_tgt.rtrdid  = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = false;	
+        break;
+      case TGT_RSP_READ_LINE:
+        p_vci_tgt.rspval   = true;
+        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();
+        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = (r_tgt_rsp_cpt.read() == (m_words-1));
+        break;
+      case TGT_RSP_READ_WORD:
+        p_vci_tgt.rspval   = true;
+        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();
+        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;	
+        break;
+      case TGT_RSP_WRITE:
+        p_vci_tgt.rspval   = true;
+        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   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_CLEANUP:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_LLSC:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = r_llsc_to_tgt_rsp_data.read();
+        p_vci_tgt.rsrcid   = r_llsc_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_llsc_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_llsc_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_XRAM_LINE:
+        p_vci_tgt.rspval   = true;
+        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();
+        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = (r_tgt_rsp_cpt.read() == (m_words-1));
+        break;
+      case TGT_RSP_XRAM_WORD:
+        p_vci_tgt.rspval   = true;
+        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();
+        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_INIT:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        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;
+        p_vci_tgt.reop     = true;	
+        break;
+    } // end switch r_tgt_rsp_fsm
+
+    ///////////////////////////////////////////////////
+    // Command signals on the p_vci_ini port
+    ///////////////////////////////////////////////////
+
+    p_vci_ini.cmd     = vci_param::CMD_WRITE;
+    p_vci_ini.srcid   = m_srcid_ini;
+    p_vci_ini.pktid   = 0;
+    p_vci_ini.cons    = true;
+    p_vci_ini.wrap    = false;
+    p_vci_ini.contig  = false;
+    p_vci_ini.clen    = 0;
+    p_vci_ini.cfixed  = false;
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      case INIT_CMD_UPDT_IDLE:
+      case INIT_CMD_INVAL_IDLE:
+      case INIT_CMD_UPDT_SEL:
+      case INIT_CMD_INVAL_SEL:
+        p_vci_ini.cmdval  = false;
+        p_vci_ini.address = 0;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0;
+        p_vci_ini.plen    = 0;
+        p_vci_ini.trdid   = 0;
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_INVAL_NLINE:
+        p_vci_ini.cmdval  = true;
+        if(r_xram_rsp_to_init_cmd_brdcast.read())
+          p_vci_ini.address = BROADCAST_ADDR;
+        else {
+          if(r_init_cmd_inst.read()) {
+            p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()]+8);
+          } else {
+            p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()]);
+          }
+        }
+        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4;
+        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+      case INIT_CMD_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4 ;
+        p_vci_ini.eop     = true;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_NLINE:
+        p_vci_ini.cmdval  = true;
+        if(r_init_cmd_inst.read()){
+          p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 12);
+        } else {
+          p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        }
+        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.eop     = false;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        if(r_init_cmd_inst.read()){
+          p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 12);
+        } else {
+          p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        }
+        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        if(r_init_cmd_inst.read()){
+          p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 12);
+        } else {
+          p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        }
+        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
+          r_write_to_init_cmd_index.read()].read();
+        if(r_write_to_init_cmd_we[r_init_cmd_cpt.read() +
+            r_write_to_init_cmd_index.read()].read())  
+          p_vci_ini.be      = 0xF;
+        else			p_vci_ini.be      = 0x0;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
+        break;
+    } // end switch r_init_cmd_fsm
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_ini port
+    //////////////////////////////////////////////////////
+
+    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
+    else                                          p_vci_ini.rspack  = false;
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt_cleanup port
+    //////////////////////////////////////////////////////
+    p_vci_tgt_cleanup.rspval = false;
+    p_vci_tgt_cleanup.rsrcid = 0;
+    p_vci_tgt_cleanup.rdata  = 0;
+    p_vci_tgt_cleanup.rpktid = 0;
+    p_vci_tgt_cleanup.rtrdid = 0;
+    p_vci_tgt_cleanup.rerror = 0;
+    p_vci_tgt_cleanup.reop   = false;
+
+    switch(r_cleanup_fsm.read()){
+      case CLEANUP_IDLE:
+        {
+          p_vci_tgt_cleanup.cmdack = true ;
+          break;
+        }
+      case CLEANUP_DIR_LOCK:
+        {
+          p_vci_tgt_cleanup.cmdack = false ;
+          break;
+        }
+      case CLEANUP_RSP:
+        {
+          p_vci_tgt_cleanup.rspval = true;
+          p_vci_tgt_cleanup.rdata  = 0;
+          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
+          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
+          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
+          p_vci_tgt_cleanup.rerror = 0;
+          p_vci_tgt_cleanup.reop   = 1;
+          break;
+        }
+
+    }
+
+  } // end genMoore()
+
+}} // end name space
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v2/caba/metadata/vci_mem_cache_v2.sd
===================================================================
--- trunk/modules/vci_mem_cache_v2/caba/metadata/vci_mem_cache_v2.sd	(revision 2)
+++ trunk/modules/vci_mem_cache_v2/caba/metadata/vci_mem_cache_v2.sd	(revision 2)
@@ -0,0 +1,40 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_mem_cache_v2',
+       classname = 'soclib::caba::VciMemCacheV2',
+       tmpl_parameters = [parameter.Module('vci_param', default = 'caba:vci_param'),],
+       header_files = ['../source/include/vci_mem_cache_v2.h',
+                       '../source/include/xram_transaction_v2.h',
+                       '../source/include/mem_cache_directory_v2.h',
+                       '../source/include/atomic_tab_v2.h',
+                       '../source/include/update_tab_v2.h',],
+       implementation_files = ['../source/src/vci_mem_cache_v2.cpp',],
+       uses = [Uses('caba:base_module'),
+               Uses('common:loader'),
+               Uses('common:mapping_table'),
+               Uses('caba:generic_fifo'),
+               ],
+       ports = [Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:vci_target','p_vci_tgt_cleanup'),
+		Port('caba:vci_initiator','p_vci_ini'),
+		Port('caba:vci_initiator','p_vci_ixr'),
+                Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+                Port('caba:clock_in', 'p_clk', auto = 'clock'),],
+       instance_parameters = [
+		parameter.Module('mtp', 'common:mapping_table'),
+		parameter.Module('mtc', 'common:mapping_table'),
+		parameter.Module('mtx', 'common:mapping_table'),
+		parameter.IntTab('vci_ixr_index'),
+		parameter.IntTab('vci_ini_index'),
+		parameter.IntTab('vci_tgt_index'),
+		parameter.IntTab('vci_tgt_index_cleanup'),
+       		parameter.Int('nways'),
+		parameter.Int('nsets'),
+		parameter.Int('nwords'),
+		],
+       extensions = ['dsx:get_ident=initiator_index:p_vci_ini',],
+)
Index: trunk/modules/vci_mem_cache_v2/caba/source/include/atomic_tab_v2.h
===================================================================
--- trunk/modules/vci_mem_cache_v2/caba/source/include/atomic_tab_v2.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v2/caba/source/include/atomic_tab_v2.h	(revision 2)
@@ -0,0 +1,121 @@
+#ifndef ATOMIC_TAB_V2_H_
+#define ATOMIC_TAB_V2_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+/*                  The atomic access tab                             */
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+class AtomicTab{
+    typedef uint32_t size_t;
+    typedef sc_dt::sc_uint<40> addr_t;
+
+private:
+    size_t size_tab;                            // The size of the tab
+    std::vector<addr_t> addr_tab;               // Address entries
+    std::vector<bool>   valid_tab;              // Valid entries
+
+public:
+
+    AtomicTab()
+	: addr_tab(0),
+	  valid_tab(0)
+	{
+    	size_tab=0;
+    }
+
+    AtomicTab(size_t size_tab_i)
+	: addr_tab(size_tab_i),
+	  valid_tab(size_tab_i)
+	{
+	    size_tab=size_tab_i;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The size() function returns the size of the tab */
+    /////////////////////////////////////////////////////////////////////
+    const size_t size(){
+	    return size_tab;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The init() function initializes the transaction tab entries */
+    /////////////////////////////////////////////////////////////////////
+    void init(){
+    	for ( size_t i=0; i<size_tab; i++) {
+		    addr_tab[i]=0;
+		    valid_tab[i]=false;
+    	}
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The set() function sets an entry 
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void set(const size_t id, const addr_t addr){
+	    assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	    addr_tab[id]=addr;
+	    valid_tab[id]=true;
+	    return;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The isatomic() function tests if the SC request corresponds to an entry
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+
+       This function return true if the request corresponds
+     */
+    /////////////////////////////////////////////////////////////////////
+    bool isatomic(const size_t id, const addr_t addr){
+	    assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	    bool test=valid_tab[id];
+	    test=test && (addr == addr_tab[id]);
+	    return test;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The reset() function resets all the entries for this lock
+       Arguments :
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void reset(const addr_t addr){
+	    for(size_t i=0 ; i<size_tab ; i++){
+		    if(addr == addr_tab[i]){
+			    valid_tab[i]=false;
+		    }
+	    }
+	    return;
+    }
+
+};
+ 
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v2/caba/source/include/mem_cache_directory_v2.h
===================================================================
--- trunk/modules/vci_mem_cache_v2/caba/source/include/mem_cache_directory_v2.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v2/caba/source/include/mem_cache_directory_v2.h	(revision 2)
@@ -0,0 +1,311 @@
+#ifndef SOCLIB_CABA_MEM_CACHE_DIRECTORY_V2_H
+#define SOCLIB_CABA_MEM_CACHE_DIRECTORY_V2_H 
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+namespace soclib { namespace caba {
+
+  using namespace sc_core;
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A LRU entry 
+  ////////////////////////////////////////////////////////////////////////
+  class LruEntry {
+
+    public:
+
+      bool recent;            
+
+      void init()
+      {
+        recent=false;
+      }
+
+  }; // end class LruEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A directory entry                               
+  ////////////////////////////////////////////////////////////////////////
+  class DirectoryEntry {
+
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+    typedef uint32_t copy_t;
+
+    public:
+
+    bool    valid;                  // entry valid
+    bool    is_cnt;                 // directory entry is a counter
+    bool    dirty;                  // entry dirty
+    bool    lock;                   // entry locked
+    tag_t   tag;                    // tag of the entry
+    copy_t  d_copies;               // vector of copies for data
+    copy_t  i_copies;               // vector of copies for instructions
+    size_t  count;                  // number of copies
+
+    DirectoryEntry()
+    {
+      valid    = false;
+      is_cnt   = false;
+      dirty    = false;
+      lock     = false;
+      tag      = 0;
+      d_copies = 0;
+      i_copies = 0;
+      count    = 0;
+    }
+
+    DirectoryEntry(const DirectoryEntry &source)
+    {
+      valid    = source.valid;
+      is_cnt   = source.is_cnt;
+      dirty    = source.dirty;
+      tag      = source.tag;
+      lock     = source.lock;
+      d_copies = source.d_copies;
+      i_copies = source.i_copies;
+      count    = source.count;
+    }          
+
+    /////////////////////////////////////////////////////////////////////
+    // The init() function initializes the entry 
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      valid = false;
+      is_cnt= false;
+      dirty = false;
+      lock  = false;
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    // The copy() function copies an existing source entry to a target 
+    /////////////////////////////////////////////////////////////////////
+    void copy(const DirectoryEntry &source)
+    {
+      valid	= source.valid;
+      is_cnt    = source.is_cnt;
+      dirty	= source.dirty;
+      tag	= source.tag;
+      lock	= source.lock;
+      d_copies	= source.d_copies;
+      i_copies	= source.i_copies;
+      count     = source.count;
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // The print() function prints the entry 
+    ////////////////////////////////////////////////////////////////////
+    void print()
+    {
+      std::cout << "Valid = " << valid << " ; IS COUNT = " << is_cnt << " ; Dirty = " << dirty << " ; Lock = " 
+        << lock << " ; Tag = " << std::hex << tag << " ; d_copies = " << d_copies << " ; i_copies = " << i_copies << " ; count = " << count << std::endl;
+    }
+
+  }; // end class DirectoryEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                       The directory  
+  ////////////////////////////////////////////////////////////////////////
+  class CacheDirectory {
+
+    typedef sc_dt::sc_uint<40> addr_t;
+    typedef uint32_t data_t;
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+
+    private:
+
+    // Directory constants
+    size_t					m_ways;
+    size_t					m_sets;
+    size_t					m_words;
+    size_t					m_width;
+
+    // the directory & lru tables
+    DirectoryEntry 				**m_dir_tab;
+    LruEntry	 				**m_lru_tab;
+
+    public:
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+    CacheDirectory( size_t ways, size_t sets, size_t words, size_t address_width)	 
+    {
+      m_ways  = ways; 
+      m_sets  = sets;
+      m_words = words;
+      m_width = address_width;
+
+      m_dir_tab = new DirectoryEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_dir_tab[i] = new DirectoryEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_dir_tab[i][j].init();
+      }
+      m_lru_tab = new LruEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_lru_tab[i] = new LruEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_lru_tab[i][j].init();
+      }
+    } // end constructor
+
+    /////////////////
+    // Destructor
+    /////////////////
+    ~CacheDirectory()
+    {
+      for(size_t i=0 ; i<m_sets ; i++){
+        delete [] m_dir_tab[i];
+        delete [] m_lru_tab[i];
+      }
+      delete [] m_dir_tab;
+      delete [] m_lru_tab;
+    } // end destructor
+
+    /////////////////////////////////////////////////////////////////////
+    // The read() function reads a directory entry. In case of hit, the
+    // LRU is updated.
+    // Arguments :
+    // - address : the address of the entry 
+    // - way : (return argument) the way of the entry in case of hit
+    // The function returns a copy of a (valid or invalid) entry  
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry read(const addr_t &address,size_t &way)
+    {
+
+#define L2 soclib::common::uint32_log2
+      const size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
+      const tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
+#undef L2
+
+      bool hit       = false;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        bool equal = ( m_dir_tab[set][i].tag == tag );
+        bool valid = m_dir_tab[set][i].valid;
+        hit = equal && valid;
+        if ( hit ) {			
+          way = i;
+          break;
+        } 
+      }
+      if ( hit ) {
+        m_lru_tab[set][way].recent = true;
+        return DirectoryEntry(m_dir_tab[set][way]);
+      } else {
+        return DirectoryEntry();
+      }
+    } // end read()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write function writes a new entry, 
+    // and updates the LRU bits if necessary.
+    // Arguments :
+    // - set : the set of the entry
+    // - way : the way of the entry
+    // - entry : the entry value
+    /////////////////////////////////////////////////////////////////////
+    void write(const size_t &set, const size_t &way, const DirectoryEntry &entry)
+    {
+      assert( (set<m_sets) 
+          && "Cache Directory write : The set index is invalid");
+      assert( (way<m_ways) 
+          && "Cache Directory write : The way index is invalid");
+
+      // update Directory
+      m_dir_tab[set][way].copy(entry);
+
+      // update LRU bits
+      bool all_recent = true;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
+      }
+      if ( all_recent ) {
+        for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
+      } else {
+        m_lru_tab[set][way].recent = true;
+      }
+    } // end write()
+
+    /////////////////////////////////////////////////////////////////////
+    // The print() function prints a selected directory entry
+    // Arguments :
+    // - set : the set of the entry to print
+    // - way : the way of the entry to print
+    /////////////////////////////////////////////////////////////////////
+    void print(const size_t &set, const size_t &way)
+    {
+      std::cout << std::dec << " set : " << set << " ; way : " << way << " ; " ;
+      m_dir_tab[set][way].print();
+    } // end print()
+
+    /////////////////////////////////////////////////////////////////////
+    // The select() function selects a directory entry to evince.
+    // Arguments :
+    // - set   : (input argument) the set to modify
+    // - way   : (return argument) the way to evince
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry select(const size_t &set, size_t &way)
+    {
+      assert( (set < m_sets) 
+          && "Cache Directory : (select) The set index is invalid");
+
+      for(size_t i=0; i<m_ways; i++){
+        if(!m_dir_tab[set][way].valid){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if(!(m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( !(m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( (m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      way = 0;
+      return DirectoryEntry(m_dir_tab[set][0]);
+    } // end select()
+
+    /////////////////////////////////////////////////////////////////////
+    // 		Global initialisation function
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      for ( size_t set=0 ; set<m_sets ; set++ ) {
+        for ( size_t way=0 ; way<m_ways ; way++ ) {
+          m_dir_tab[set][way].init();
+          m_lru_tab[set][way].init();
+        }
+      }
+    } // end init()
+
+  }; // end class CacheDirectory
+
+}} // end namespaces
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v2/caba/source/include/update_tab_v2.h
===================================================================
--- trunk/modules/vci_mem_cache_v2/caba/source/include/update_tab_v2.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v2/caba/source/include/update_tab_v2.h	(revision 2)
@@ -0,0 +1,402 @@
+#ifndef UPDATE_TAB_V2_H_
+#define UPDATE_TAB_V2_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+////////////////////////////////////////////////////////////////////////
+//                  An update tab entry    
+////////////////////////////////////////////////////////////////////////
+class UpdateTabEntry {
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  public:
+  bool 	valid;                // It is a valid pending transaction
+  bool	update;               // It is an update transaction
+  bool  brdcast;              // It is a broadcast invalidate
+  bool  rsp;                  // It needs a response to the initiator
+  size_t 	srcid;        // The srcid of the initiator which wrote the data
+  size_t 	trdid;        // The trdid of the initiator which wrote the data
+  size_t 	pktid;        // The pktid of the initiator which wrote the data
+  addr_t	nline;	      // The identifier of the cache line
+  size_t 	count;        // The number of acknowledge responses to receive
+
+  UpdateTabEntry(){
+    valid	= false;
+    update  = false;
+    brdcast = false;
+    rsp     = false;
+    srcid	= 0;
+    trdid	= 0;
+    pktid	= 0;
+    nline	= 0;
+    count	= 0;
+  }
+
+  UpdateTabEntry(bool   i_valid, 
+      bool   i_update,
+      bool   i_brdcast,
+      bool   i_rsp,
+      size_t i_srcid, 
+      size_t i_trdid, 
+      size_t i_pktid, 
+      addr_t i_nline,
+      size_t i_count) 
+  {
+    valid		= i_valid;
+    update	    = i_update;
+    brdcast     = i_brdcast;
+    rsp         = i_rsp;
+    srcid		= i_srcid;
+    trdid		= i_trdid;
+    pktid		= i_pktid;
+    nline		= i_nline;
+    count		= i_count;
+  }
+
+  UpdateTabEntry(const UpdateTabEntry &source)
+  {
+    valid   = source.valid;
+    update  = source.update;
+    brdcast = source.brdcast;
+    rsp     = source.rsp;
+    srcid   = source.srcid;
+    trdid   = source.trdid;
+    pktid   = source.pktid;
+    nline   = source.nline;
+    count   = source.count;
+  }
+
+  ////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  ///////////////////////////////////////////////////
+  void init()
+  {
+    valid  = false;
+    update = false;
+    brdcast= false;
+    rsp    = false;
+    srcid  = 0;
+    trdid  = 0;
+    pktid  = 0;
+    nline  = 0;
+    count  = 0;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the update tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const UpdateTabEntry &source)
+  {
+    valid  = source.valid;
+    update = source.update;
+    brdcast= source.brdcast;
+    rsp    = source.rsp;
+    srcid  = source.srcid;
+    trdid  = source.trdid;
+    pktid  = source.pktid;
+    nline  = source.nline;
+    count  = source.count;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << std::dec << "valid  = " << valid  << std::endl;
+    std::cout << "update = " << update << std::endl;
+    std::cout << "brdcast= " << brdcast<< std::endl;
+    std::cout << "rsp    = " << rsp    << std::endl;
+    std::cout << "srcid  = " << srcid  << std::endl; 
+    std::cout << "trdid  = " << trdid  << std::endl; 
+    std::cout << "pktid  = " << pktid  << std::endl; 
+    std::cout << std::hex << "nline  = " << nline  << std::endl;
+    std::cout << std::dec << "count  = " << count  << std::endl;
+  }
+};
+
+////////////////////////////////////////////////////////////////////////
+//                        The update tab             
+////////////////////////////////////////////////////////////////////////
+class UpdateTab{
+
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  private:
+  size_t size_tab;
+  std::vector<UpdateTabEntry> tab;
+
+  public:
+
+  UpdateTab()
+    : tab(0)
+  {
+    size_tab=0;
+  }
+
+  UpdateTab(size_t size_tab_i)
+    : tab(size_tab_i)
+  {
+    size_tab=size_tab_i;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  const size_t size(){
+    return size_tab;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    for(size_t i=0; i<size_tab; i++) {
+      std::cout << "UPDATE TAB ENTRY " << std::dec << i << "--------" << std::endl;
+      tab[i].print();
+    }
+    return;
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the tab 
+  /////////////////////////////////////////////////////////////////////
+  void init(){
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The reads() function reads an entry 
+  // Arguments :
+  // - entry : the entry to read
+  // This function returns a copy of the entry.
+  /////////////////////////////////////////////////////////////////////
+  UpdateTabEntry read (size_t entry)
+  {
+    assert(entry<size_tab && "Bad Update Tab Entry");
+    return UpdateTabEntry(tab[entry]);
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // The set() function writes an entry in the Update Table
+  // Arguments :
+  // - update : transaction type (bool)
+  // - srcid : srcid of the initiator
+  // - trdid : trdid of the initiator
+  // - pktid : pktid of the initiator
+  // - count : number of expected responses
+  // - index : (return argument) index of the selected entry
+  // This function returns true if the write successed (an entry was empty).
+  ///////////////////////////////////////////////////////////////////////////
+  bool set(const bool	update,
+      const bool   brdcast,
+      const bool   rsp,
+      const size_t srcid,
+      const size_t trdid,
+      const size_t pktid,
+      const addr_t nline,
+      const size_t count,
+      size_t &index)
+  {
+    for ( size_t i=0 ; i<size_tab ; i++ ) {
+      if( !tab[i].valid ) {
+        tab[i].valid		= true;
+        tab[i].update		= update;
+        tab[i].brdcast      = brdcast;
+        tab[i].rsp          = rsp;
+        tab[i].srcid		= (size_t) srcid;
+        tab[i].trdid		= (size_t) trdid;
+        tab[i].pktid		= (size_t) pktid;
+        tab[i].nline		= (addr_t) nline;
+        tab[i].count		= (size_t) count;
+        index			    = i;
+        return true;
+      }
+    }
+    return false;
+  } // end set()
+
+  /////////////////////////////////////////////////////////////////////
+  // The decrement() function decrements the counter for a given entry.
+  // Arguments :
+  // - index   : the index of the entry
+  // - counter : (return argument) value of the counter after decrement
+  // This function returns true if the entry is valid.
+  /////////////////////////////////////////////////////////////////////
+  bool decrement( const size_t index,
+      size_t &counter ) 
+  {
+    assert((index<size_tab) && "Bad Update Tab Entry");
+    if ( tab[index].valid ) {
+      tab[index].count--;
+      counter = tab[index].count;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_full() function returns true if the table is full
+  /////////////////////////////////////////////////////////////////////
+  bool is_full()
+  {
+    for(size_t i = 0 ; i < size_tab ; i++){
+      if(!tab[i].valid){
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The need_rsp() function returns the need of a response
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool need_rsp(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].rsp;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_brdcast(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].brdcast;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_update(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].update;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The srcid() function returns the srcid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t srcid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].srcid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The trdid() function returns the trdid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t trdid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].trdid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The pktid() function returns the pktid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t pktid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].pktid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The nline() function returns the nline value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  addr_t nline(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].nline;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The search_inval() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool search_inval(const addr_t nline,size_t &index)
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        if(!tab[i].update){
+          index = i ;
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read_nline() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool read_nline(const addr_t nline,size_t &index) 
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        index = i ;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The clear() function erases an entry of the tab
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////       
+  void clear(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    tab[index].valid=false;
+    return;	
+  }
+
+};
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v2/caba/source/include/vci_mem_cache_v2.h
===================================================================
--- trunk/modules/vci_mem_cache_v2/caba/source/include/vci_mem_cache_v2.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v2/caba/source/include/vci_mem_cache_v2.h	(revision 2)
@@ -0,0 +1,653 @@
+/* -*- c++ -*-
+ * File         : vci_mem_cache_v2.h
+ * Date         : 26/10/2008
+ * Copyright    : UPMC / LIP6
+ * Authors      : Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+/*
+ *
+ * Modifications done by Christophe Choichillon on the 7/04/2009:
+ * - Adding new states in the CLEANUP FSM : CLEANUP_UPT_LOCK and CLEANUP_UPT_WRITE
+ * - Adding a new VCI target port for the CLEANUP network
+ * - Adding new state in the ALLOC_UPT_FSM : ALLOC_UPT_CLEANUP
+ * 
+ * Modifications to do :
+ * - Adding new variables used by the CLEANUP FSM
+ *
+ */
+
+#ifndef SOCLIB_CABA_MEM_CACHE_V2_H
+#define SOCLIB_CABA_MEM_CACHE_V2_H
+
+#include <inttypes.h>
+#include <systemc>
+#include <list>
+#include <cassert>
+#include "arithmetics.h"
+#include "alloc_elems.h"
+#include "caba_base_module.h"
+#include "vci_target.h"
+#include "vci_initiator.h"
+#include "generic_fifo.h"
+#include "mapping_table.h"
+#include "int_tab.h"
+#include "mem_cache_directory_v2.h"
+#include "xram_transaction_v2.h"
+#include "update_tab_v2.h"
+#include "atomic_tab_v2.h"
+
+#define TRANSACTION_TAB_LINES 4     // Number of lines in the transaction tab
+#define UPDATE_TAB_LINES 4          // Number of lines in the update tab
+#define BROADCAST_ADDR 0x0000000003 // Address to send the broadcast invalidate
+
+namespace soclib {  namespace caba {
+  using namespace sc_core;
+
+  template<typename vci_param>
+    class VciMemCacheV2
+    : public soclib::caba::BaseModule
+    {
+      typedef sc_dt::sc_uint<40> addr_t;
+      typedef typename vci_param::fast_addr_t vci_addr_t;
+      typedef uint32_t data_t;
+      typedef uint32_t tag_t;
+      typedef uint32_t size_t;
+      typedef uint32_t be_t;
+      typedef uint32_t copy_t;
+
+      /* States of the TGT_CMD fsm */
+      enum tgt_cmd_fsm_state_e{
+        TGT_CMD_IDLE,
+        TGT_CMD_READ,
+        TGT_CMD_READ_EOP,
+        TGT_CMD_WRITE,
+        TGT_CMD_ATOMIC,
+      };
+
+      /* States of the TGT_RSP fsm */
+      enum tgt_rsp_fsm_state_e{
+        TGT_RSP_READ_IDLE,
+        TGT_RSP_WRITE_IDLE,
+        TGT_RSP_LLSC_IDLE,
+        TGT_RSP_XRAM_IDLE,
+        TGT_RSP_INIT_IDLE,
+        TGT_RSP_CLEANUP_IDLE,
+        TGT_RSP_READ,
+        TGT_RSP_WRITE,
+        TGT_RSP_LLSC,
+        TGT_RSP_XRAM,
+        TGT_RSP_INIT,
+        TGT_RSP_CLEANUP,
+      };
+
+      /* States of the INIT_CMD fsm */
+      enum init_cmd_fsm_state_e{
+        INIT_CMD_INVAL_IDLE,
+        INIT_CMD_INVAL_SEL,
+        INIT_CMD_INVAL_NLINE,
+        INIT_CMD_UPDT_IDLE,
+        INIT_CMD_UPDT_SEL,
+        INIT_CMD_BRDCAST,
+        INIT_CMD_UPDT_NLINE,
+        INIT_CMD_UPDT_INDEX,
+        INIT_CMD_UPDT_DATA,
+        INIT_CMD_SC_UPDT_IDLE,
+        INIT_CMD_SC_UPDT_SEL,
+        INIT_CMD_SC_BRDCAST,
+        INIT_CMD_SC_UPDT_NLINE,
+        INIT_CMD_SC_UPDT_INDEX,
+        INIT_CMD_SC_UPDT_DATA,
+      };
+
+      /* States of the INIT_RSP fsm */
+      enum init_rsp_fsm_state_e{
+        INIT_RSP_IDLE,
+        INIT_RSP_UPT_LOCK,
+        INIT_RSP_UPT_CLEAR,
+        INIT_RSP_END,
+      };
+
+      /* States of the READ fsm */
+      enum read_fsm_state_e{
+        READ_IDLE,
+        READ_DIR_LOCK,
+        READ_DIR_HIT,
+        READ_RSP,
+        READ_TRT_LOCK,
+        READ_TRT_SET,
+        READ_XRAM_REQ,
+      };
+
+      /* States of the WRITE fsm */
+      enum write_fsm_state_e{
+        WRITE_IDLE,
+        WRITE_NEXT,
+        WRITE_DIR_LOCK,
+        WRITE_DIR_HIT_READ,
+        WRITE_DIR_HIT,
+        WRITE_DIR_HIT_RSP,
+        WRITE_UPT_LOCK,
+        WRITE_WAIT_UPT,
+        WRITE_UPDATE,
+        WRITE_RSP,
+        WRITE_TRT_LOCK,
+        WRITE_TRT_DATA,
+        WRITE_TRT_SET,
+        WRITE_WAIT_TRT,
+        WRITE_XRAM_REQ,
+        WRITE_TRT_WRITE_LOCK,
+        WRITE_INVAL_LOCK,
+        WRITE_DIR_INVAL,
+        WRITE_INVAL,
+        WRITE_XRAM_SEND,
+      };
+
+      /* States of the IXR_RSP fsm */
+      enum ixr_rsp_fsm_state_e{
+        IXR_RSP_IDLE,
+        IXR_RSP_ACK,
+        IXR_RSP_TRT_ERASE,
+        IXR_RSP_TRT_READ,
+      };
+
+      /* States of the XRAM_RSP fsm */
+      enum xram_rsp_fsm_state_e{
+        XRAM_RSP_IDLE,
+        XRAM_RSP_TRT_COPY,
+        XRAM_RSP_TRT_DIRTY,
+        XRAM_RSP_DIR_LOCK,
+        XRAM_RSP_DIR_UPDT,
+        XRAM_RSP_DIR_RSP,
+        XRAM_RSP_INVAL_LOCK,
+        XRAM_RSP_INVAL_WAIT,
+        XRAM_RSP_INVAL,
+        XRAM_RSP_WRITE_DIRTY,
+      };
+
+      /* States of the IXR_CMD fsm */
+      enum ixr_cmd_fsm_state_e{
+        IXR_CMD_READ_IDLE,
+        IXR_CMD_WRITE_IDLE,
+        IXR_CMD_LLSC_IDLE,
+        IXR_CMD_XRAM_IDLE,
+        IXR_CMD_READ_NLINE,
+        IXR_CMD_WRITE_NLINE,
+        IXR_CMD_LLSC_NLINE,
+        IXR_CMD_XRAM_DATA,
+      };
+
+      /* States of the LLSC fsm */
+      enum llsc_fsm_state_e{
+        LLSC_IDLE,
+        LL_DIR_LOCK,
+        LL_DIR_HIT,
+        LL_RSP,
+        SC_DIR_LOCK,
+        SC_DIR_HIT,
+        SC_UPT_LOCK,
+        SC_WAIT_UPT,
+        SC_UPDATE,
+        SC_TRT_LOCK,
+        SC_INVAL_LOCK,
+        SC_DIR_INVAL,
+        SC_INVAL,
+        SC_XRAM_SEND,
+        SC_RSP_FALSE,
+        SC_RSP_TRUE,
+        LLSC_TRT_LOCK,
+        LLSC_TRT_SET,
+        LLSC_XRAM_REQ,
+      };
+
+      /* States of the CLEANUP fsm */
+      enum cleanup_fsm_state_e{
+        CLEANUP_IDLE,
+        CLEANUP_DIR_LOCK,
+        CLEANUP_DIR_WRITE,
+        CLEANUP_UPT_LOCK,
+        CLEANUP_UPT_WRITE,
+        CLEANUP_WRITE_RSP,
+        CLEANUP_RSP,
+      };
+
+      /* States of the ALLOC_DIR fsm */
+      enum alloc_dir_fsm_state_e{
+        ALLOC_DIR_READ,
+        ALLOC_DIR_WRITE,
+        ALLOC_DIR_LLSC,
+        ALLOC_DIR_CLEANUP,
+        ALLOC_DIR_XRAM_RSP,
+      };
+
+      /* States of the ALLOC_TRT fsm */
+      enum alloc_trt_fsm_state_e{
+        ALLOC_TRT_READ,
+        ALLOC_TRT_WRITE,
+        ALLOC_TRT_LLSC,
+        ALLOC_TRT_XRAM_RSP,
+        ALLOC_TRT_IXR_RSP,
+      };
+
+      /* States of the ALLOC_UPT fsm */
+      enum alloc_upt_fsm_state_e{
+        ALLOC_UPT_WRITE,
+        ALLOC_UPT_XRAM_RSP,
+        ALLOC_UPT_INIT_RSP,
+        ALLOC_UPT_CLEANUP,
+        ALLOC_UPT_LLSC,
+      };
+
+      uint32_t	   m_cpt_cycles;            // Counter of cycles 
+      uint32_t	   m_cpt_read;              // Number of READ transactions
+      uint32_t	   m_cpt_read_miss;         // Number of MISS READ 
+      uint32_t	   m_cpt_write;             // Number of WRITE transactions
+      uint32_t	   m_cpt_write_miss;        // Number of MISS WRITE
+      uint32_t     m_cpt_write_cells;	    // Cumulated length for WRITE transactions
+      uint32_t     m_cpt_write_dirty;	    // Cumulated length for WRITE transactions
+      uint32_t	   m_cpt_update;            // Number of UPDATE transactions
+      uint32_t	   m_cpt_update_mult;       // Number of targets for UPDATE
+      uint32_t	   m_cpt_inval;             // Number of INVAL  transactions
+      uint32_t	   m_cpt_inval_mult;        // Number of targets for INVAL  
+      uint32_t	   m_cpt_inval_brdcast;     // Number of BROADCAST INVAL  
+      uint32_t	   m_cpt_cleanup;           // Number of CLEANUP transactions
+      uint32_t	   m_cpt_ll;                // Number of LL transactions
+      uint32_t	   m_cpt_sc;                // Number of SC transactions
+
+      protected:
+
+      SC_HAS_PROCESS(VciMemCacheV2);
+
+      public:
+      sc_in<bool> 			  	p_clk;
+      sc_in<bool> 			  	p_resetn;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt_cleanup;
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ini;	
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ixr;
+
+      VciMemCacheV2(
+          sc_module_name name,                              // Instance Name 
+          const soclib::common::MappingTable &mtp,          // Mapping table for primary requets
+          const soclib::common::MappingTable &mtc,          // Mapping table for coherence requets
+          const soclib::common::MappingTable &mtx,          // Mapping table for XRAM
+          const soclib::common::IntTab &vci_ixr_index,      // VCI port to XRAM (initiator)
+          const soclib::common::IntTab &vci_ini_index,      // VCI port to PROC (initiator)
+          const soclib::common::IntTab &vci_tgt_index,      // VCI port to PROC (target)
+          const soclib::common::IntTab &vci_tgt_index_cleanup,    // VCI port to PROC (target) for cleanup
+          size_t nways,                                   // Number of ways per set 
+          size_t nsets,                                   // Number of sets
+          size_t nwords);                                 // Number of words per line
+
+      ~VciMemCacheV2();
+
+      void transition();
+
+      void genMoore();
+
+      void print_stats();
+
+      private:
+
+      // Component attributes
+      const size_t              m_initiators;           // Number of initiators
+      const size_t              m_ways;                 // Number of ways in a set
+      const size_t              m_sets;                 // Number of cache sets
+      const size_t              m_words;		        // Number of words in a line
+      const size_t              m_srcid_ixr;		    // Srcid for requests to XRAM 
+      const size_t              m_srcid_ini;		    // Srcid for requests to processors
+      std::list<soclib::common::Segment>  m_seglist;    // memory cached into the cache
+      std::list<soclib::common::Segment>  m_cseglist;   // coherence segment for the cache
+      vci_addr_t        		*m_coherence_table; 	// address(srcid)
+      AtomicTab                 m_atomic_tab;           // atomic access table
+      TransactionTab      		m_transaction_tab;	    // xram transaction table
+      UpdateTab                 m_update_tab;		    // pending update & invalidate 
+      CacheDirectory			m_cache_directory;	    // data cache directory
+
+      data_t	        	       ***m_cache_data;		// data array[set][way][word]
+
+      // adress masks
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_x;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_y;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_z;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_nline; 
+
+      //////////////////////////////////////////////////
+      // Others registers
+      //////////////////////////////////////////////////
+      sc_signal<size_t>   r_copies_limit; // Limit of the number of copies for one line
+
+      //////////////////////////////////////////////////
+      // Registers controlled by the TGT_CMD fsm
+      //////////////////////////////////////////////////
+
+      // Fifo between TGT_CMD fsm and READ fsm
+      GenericFifo<uint64_t>  m_cmd_read_addr_fifo;
+      GenericFifo<size_t>    m_cmd_read_length_fifo;
+      GenericFifo<size_t>    m_cmd_read_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_read_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_read_pktid_fifo;
+
+      // Fifo between TGT_CMD fsm and WRITE fsm    
+      GenericFifo<uint64_t>  m_cmd_write_addr_fifo;
+      GenericFifo<bool>      m_cmd_write_eop_fifo;
+      GenericFifo<size_t>    m_cmd_write_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_write_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_write_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_write_data_fifo;
+      GenericFifo<be_t>	     m_cmd_write_be_fifo;
+
+      // Fifo between TGT_CMD fsm and LLSC fsm
+      GenericFifo<uint64_t>  m_cmd_llsc_addr_fifo;
+      GenericFifo<bool>      m_cmd_llsc_sc_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_llsc_wdata_fifo;
+
+      sc_signal<int>         r_tgt_cmd_fsm;
+
+      sc_signal<size_t>	     r_index;
+      size_t nseg;
+      size_t ncseg;
+      soclib::common::Segment  **m_seg;
+      soclib::common::Segment  **m_cseg;
+      ///////////////////////////////////////////////////////
+      // Registers controlled by the READ fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>         r_read_fsm;        // FSM state 
+      sc_signal<copy_t>      r_read_d_copies;   // bit-vector of copies 
+      sc_signal<copy_t>      r_read_i_copies;   // bit-vector of copies 
+      sc_signal<tag_t>       r_read_tag;	    // cache line tag (in directory)
+      sc_signal<bool>        r_read_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>        r_read_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_read_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>      r_read_count;      // number of copies
+      sc_signal<data_t>     *r_read_data;       // data (one cache line)
+      sc_signal<size_t>      r_read_way;        // associative way (in cache)
+      sc_signal<size_t>      r_read_trt_index;  // Transaction Table index
+
+      // Buffer between READ fsm and IXR_CMD fsm (ask a missing cache line to XRAM)   
+      sc_signal<bool>        r_read_to_ixr_cmd_req;     // valid request
+      sc_signal<addr_t>      r_read_to_ixr_cmd_nline;   // cache line index
+      sc_signal<size_t>      r_read_to_ixr_cmd_trdid;   // index in Transaction Table
+
+      // Buffer between READ fsm and TGT_RSP fsm (send a hit read response to L1 cache)
+      sc_signal<bool>	   r_read_to_tgt_rsp_req;       // valid request
+      sc_signal<size_t>	   r_read_to_tgt_rsp_srcid;	    // Transaction srcid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_trdid;	    // Transaction trdid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_pktid;	    // Transaction pktid
+      sc_signal<data_t>   *r_read_to_tgt_rsp_data;	    // data (one cache line)
+      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
+
+      ///////////////////////////////////////////////////////////////
+      // Registers controlled by the WRITE fsm
+      ///////////////////////////////////////////////////////////////
+
+      sc_signal<int>       r_write_fsm;             // FSM state
+      sc_signal<addr_t>	   r_write_address;         // first word address
+      sc_signal<size_t>    r_write_word_index;      // first word index in line
+      sc_signal<size_t>    r_write_word_count;      // number of words in line
+      sc_signal<size_t>    r_write_srcid;           // transaction srcid
+      sc_signal<size_t>    r_write_trdid;           // transaction trdid
+      sc_signal<size_t>    r_write_pktid;           // transaction pktid
+      sc_signal<data_t>	  *r_write_data;            // data (one cache line)	
+      sc_signal<be_t>     *r_write_be;              // one byte enable per word
+      sc_signal<bool>      r_write_byte;            // is it a byte write
+      sc_signal<bool>      r_write_is_cnt;          // is_cnt bit (in directory)
+      sc_signal<bool>      r_write_lock;            // lock bit (in directory)
+      sc_signal<tag_t>     r_write_tag;             // cache line tag (in directory)
+      sc_signal<copy_t>    r_write_d_copies;        // bit vector of copies
+      sc_signal<copy_t>    r_write_i_copies;        // bit vector of copies
+      sc_signal<size_t>	   r_write_count;           // number of copies
+      sc_signal<size_t>	   r_write_way;		        // way of the line
+      sc_signal<size_t>    r_write_trt_index;	    // index in Transaction Table
+      sc_signal<size_t>    r_write_upt_index;	    // index in Update Table
+
+      // 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
+
+      // Buffer between WRITE fsm and IXR_CMD fsm (ask a missing cache line to XRAM) 
+      sc_signal<bool>	   r_write_to_ixr_cmd_req;      // valid request
+      sc_signal<bool>	   r_write_to_ixr_cmd_write;    // write request
+      sc_signal<addr_t>    r_write_to_ixr_cmd_nline; 	// cache line index
+      sc_signal<data_t>	  *r_write_to_ixr_cmd_data;	    // cache line data
+      sc_signal<size_t>    r_write_to_ixr_cmd_trdid;	// index in Transaction Table
+
+      // Buffer between WRITE fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>	   r_write_to_init_cmd_req;         // valid request
+      sc_signal<bool>	   r_write_to_init_cmd_brdcast;     // brdcast request
+      sc_signal<addr_t>	   r_write_to_init_cmd_nline;	    // cache line index
+      sc_signal<size_t>	   r_write_to_init_cmd_trdid;	    // index in Update Table
+      sc_signal<copy_t>    r_write_to_init_cmd_d_copies;    // bit_vector of L1 to update
+      sc_signal<data_t>   *r_write_to_init_cmd_data;	    // data (one cache line)
+      sc_signal<bool>     *r_write_to_init_cmd_we;	        // word enable
+      sc_signal<size_t>	   r_write_to_init_cmd_count;	    // number of words in line
+      sc_signal<size_t>	   r_write_to_init_cmd_index;	    // index of first word in line
+
+      /////////////////////////////////////////////////////////
+      // Registers controlled by INIT_RSP fsm
+      //////////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_init_rsp_fsm;        // FSM state
+      sc_signal<size_t>	   r_init_rsp_upt_index;  // index in the Update Table
+      sc_signal<size_t>	   r_init_rsp_srcid;	  // pending write srcid      
+      sc_signal<size_t>	   r_init_rsp_trdid;	  // pending write trdid      
+      sc_signal<size_t>	   r_init_rsp_pktid;	  // pending write pktid      
+      sc_signal<addr_t>	   r_init_rsp_nline;	  // pending write nline      
+
+      // Buffer between INIT_RSP fsm and TGT_RSP fsm (complete write/update transaction)
+      sc_signal<bool>	     r_init_rsp_to_tgt_rsp_req;   	// valid request
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_srcid;		// Transaction srcid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_trdid;		// Transaction trdid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_pktid;		// Transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by CLEANUP fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int> 	     r_cleanup_fsm;         // FSM state
+      sc_signal<size_t>      r_cleanup_srcid;       // transaction srcid
+      sc_signal<size_t>      r_cleanup_trdid;       // transaction trdid
+      sc_signal<size_t>      r_cleanup_pktid;       // transaction pktid
+      sc_signal<addr_t>      r_cleanup_nline;       // cache line index
+
+      sc_signal<copy_t>      r_cleanup_d_copies;    // bit-vector of copies 
+      sc_signal<copy_t>      r_cleanup_i_copies;    // bit-vector of copies 
+      sc_signal<copy_t>      r_cleanup_count;       // number of copies 
+      sc_signal<tag_t>       r_cleanup_tag;	        // cache line tag (in directory)
+      sc_signal<bool>        r_cleanup_is_cnt;      // inst bit (in directory)
+      sc_signal<bool>        r_cleanup_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_cleanup_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>      r_cleanup_way;	        // associative way (in cache)
+
+      sc_signal<size_t>      r_cleanup_write_srcid; // srcid of write response
+      sc_signal<size_t>      r_cleanup_write_trdid; // trdid of write rsp
+      sc_signal<size_t>      r_cleanup_write_pktid; // pktid of write rsp
+      sc_signal<bool>        r_cleanup_need_rsp;    // needs a write rsp
+
+      sc_signal<size_t>      r_cleanup_index;	    // index of the INVAL line (in the UPT)
+
+      // Buffer between CLEANUP fsm and TGT_RSP fsm (acknowledge a write command from L1)
+      sc_signal<bool>      r_cleanup_to_tgt_rsp_req;    // valid request
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_srcid;  // transaction srcid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_trdid;	// transaction trdid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_pktid;	// transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by LLSC fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>       r_llsc_fsm;          // FSM state
+      sc_signal<data_t>	   r_llsc_data;		    // read data word
+      sc_signal<uint32_t>  r_llsc_lfsr;         // lfsr for random introducing
+      sc_signal<copy_t>    r_llsc_i_copies;	    // bit_vector of copies
+      sc_signal<copy_t>    r_llsc_d_copies;	    // bit_vector of copies
+      sc_signal<copy_t>    r_llsc_count;	    // number of copies
+      sc_signal<bool>      r_llsc_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>      r_llsc_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>    r_llsc_way;		    // way in directory
+      sc_signal<size_t>    r_llsc_set;		    // set in directory
+      sc_signal<data_t>    r_llsc_tag;		    // cache line tag (in directory)
+      sc_signal<size_t>    r_llsc_trt_index;    // Transaction Table index
+      sc_signal<size_t>    r_llsc_upt_index;    // Update Table index
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (XRAM read)	
+      sc_signal<bool>	   r_llsc_to_ixr_cmd_req;   // valid request
+      sc_signal<addr_t>	   r_llsc_to_ixr_cmd_nline; // cache line index
+      sc_signal<size_t>	   r_llsc_to_ixr_cmd_trdid; // index in Transaction Table
+      sc_signal<bool>	   r_llsc_to_ixr_cmd_write; // write request
+      sc_signal<data_t>	  *r_llsc_to_ixr_cmd_data;  // cache line data
+
+
+      // Buffer between LLSC fsm and TGT_RSP fsm
+      sc_signal<bool>	   r_llsc_to_tgt_rsp_req;   // valid request
+      sc_signal<data_t>    r_llsc_to_tgt_rsp_data;  // read data word
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_srcid; // Transaction srcid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_trdid; // Transaction trdid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_pktid; // Transaction pktid
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>	   r_llsc_to_init_cmd_req;          // valid request
+      sc_signal<bool>	   r_llsc_to_init_cmd_brdcast;      // brdcast request
+      sc_signal<addr_t>	   r_llsc_to_init_cmd_nline;	    // cache line index
+      sc_signal<size_t>	   r_llsc_to_init_cmd_trdid;	    // index in Update Table
+      sc_signal<copy_t>    r_llsc_to_init_cmd_d_copies;     // bit_vector of L1 to update
+      sc_signal<data_t>    r_llsc_to_init_cmd_wdata;        // data (one word)
+      sc_signal<size_t>	   r_llsc_to_init_cmd_index;	    // index of the word in line
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_rsp_fsm;       // FSM state
+      sc_signal<size_t>	   r_ixr_rsp_trt_index;	// TRT entry index
+      sc_signal<size_t>    r_ixr_rsp_cpt;	    // word counter
+
+      // Buffer between IXR_RSP fsm and XRAM_RSP fsm  (response from the XRAM)
+      sc_signal<bool>	  *r_ixr_rsp_to_xram_rsp_rok;	// A xram response is ready
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the XRAM_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_xram_rsp_fsm;		        // FSM state
+      sc_signal<size_t>	   r_xram_rsp_trt_index;	    // TRT entry index
+      TransactionTabEntry  r_xram_rsp_trt_buf;		    // TRT entry local buffer
+      sc_signal<bool>	   r_xram_rsp_victim_inval;	    // victim line invalidate 
+      sc_signal<bool>	   r_xram_rsp_victim_is_cnt;    // victim line inst bit
+      sc_signal<bool>	   r_xram_rsp_victim_dirty;	    // victim line dirty bit
+      sc_signal<size_t>    r_xram_rsp_victim_way;	    // victim line way
+      sc_signal<size_t>    r_xram_rsp_victim_set;	    // victim line set
+      sc_signal<addr_t>    r_xram_rsp_victim_nline;     // victim line index
+      sc_signal<copy_t>    r_xram_rsp_victim_d_copies;	// victim line copies
+      sc_signal<copy_t>    r_xram_rsp_victim_i_copies;	// victim line copies
+      sc_signal<copy_t>    r_xram_rsp_victim_count;	    // victim line number of copies
+      sc_signal<data_t>	  *r_xram_rsp_victim_data;	    // victim line data
+      sc_signal<size_t>	   r_xram_rsp_upt_index;	    // UPT entry index
+
+      // Buffer between XRAM_RSP fsm and TGT_RSP fsm  (response to L1 cache)
+      sc_signal<bool>	   r_xram_rsp_to_tgt_rsp_req;	// Valid request
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_srcid;	// Transaction srcid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_trdid;	// Transaction trdid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_pktid;	// Transaction pktid
+      sc_signal<data_t>   *r_xram_rsp_to_tgt_rsp_data;	// data (one cache line)
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_word;  // first word index
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_length;// length of the response
+
+      // Buffer between XRAM_RSP fsm and INIT_CMD fsm (Inval L1 Caches) 
+      sc_signal<bool>	     r_xram_rsp_to_init_cmd_req;    // Valid request
+      sc_signal<bool>      r_xram_rsp_to_init_cmd_brdcast;  // Broadcast request
+      sc_signal<addr_t>    r_xram_rsp_to_init_cmd_nline;    // cache line index;
+      sc_signal<size_t>	   r_xram_rsp_to_init_cmd_trdid;    // index of UPT entry
+      sc_signal<copy_t>    r_xram_rsp_to_init_cmd_d_copies; // bit_vector of copies
+      sc_signal<copy_t>    r_xram_rsp_to_init_cmd_i_copies; // bit_vector of copies
+
+      // Buffer between XRAM_RSP fsm and IXR_CMD fsm (XRAM write)
+      sc_signal<bool>	   r_xram_rsp_to_ixr_cmd_req;	// Valid request
+      sc_signal<addr_t>	   r_xram_rsp_to_ixr_cmd_nline;	// cache line index
+      sc_signal<data_t>	  *r_xram_rsp_to_ixr_cmd_data;	// cache line data
+      sc_signal<size_t>	   r_xram_rsp_to_ixr_cmd_trdid;	// index in transaction table
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_cmd_fsm;
+      sc_signal<size_t>	   r_ixr_cmd_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by TGT_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_tgt_rsp_fsm;
+      sc_signal<size_t>    r_tgt_rsp_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by INIT_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	  r_init_cmd_fsm;
+      sc_signal<size_t>   r_init_cmd_cpt;
+      sc_signal<size_t>	  r_init_cmd_target;
+      sc_signal<bool>     r_init_cmd_inst;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_DIR fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_dir_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_TRT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_trt_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_UPT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_upt_fsm;
+
+    }; // end class VciMemCacheV2
+
+}}
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v2/caba/source/include/xram_transaction_v2.h
===================================================================
--- trunk/modules/vci_mem_cache_v2/caba/source/include/xram_transaction_v2.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v2/caba/source/include/xram_transaction_v2.h	(revision 2)
@@ -0,0 +1,404 @@
+#ifndef XRAM_TRANSACTION_V2_H_
+#define XRAM_TRANSACTION_V2_H_
+ 
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+#define DEBUG_XRAM_TRANSACTION 0
+
+////////////////////////////////////////////////////////////////////////
+//                  A transaction tab entry         
+////////////////////////////////////////////////////////////////////////
+
+class TransactionTabEntry {
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ public:
+  bool 		      valid;     	    // entry valid 
+  bool 		      xram_read; 	    // read request to XRAM
+  addr_t   	      nline;    	    // index (zy) of the requested line
+  size_t 	      srcid;     	    // processor requesting the transaction
+  size_t 	      trdid;     	    // processor requesting the transaction
+  size_t 	      pktid;     	    // processor requesting the transaction
+  bool 		      proc_read;	    // read request from processor
+  size_t 		  read_length;      // length of the read (for the response)
+  size_t 	      word_index;    	// index of the first read word (for the response)
+  std::vector<data_t> wdata;        // write buffer (one cache line)
+  std::vector<be_t>   wdata_be;    	// be for each data in the write buffer
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    valid		= false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The alloc() function initializes the vectors of an entry
+  // Its arguments are :
+  // - n_words : number of words per line in the cache
+  /////////////////////////////////////////////////////////////////////
+  void alloc(size_t n_words)
+  {
+    wdata_be.reserve( (int)n_words );
+    wdata.reserve( (int)n_words );
+    for(size_t i=0; i<n_words; i++){
+      wdata_be.push_back(false);
+      wdata.push_back(0);
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the transaction tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const TransactionTabEntry &source)
+  {
+    valid	    = source.valid;
+    xram_read 	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read 	= source.proc_read;
+    read_length = source.read_length;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry 
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << "valid       = " << valid        << std::endl;
+    std::cout << "xram_read   = " << xram_read    << std::endl;
+    std::cout << "nline       = " << std::hex << nline << std::endl;
+    std::cout << "srcid       = " << srcid        << std::endl;
+    std::cout << "trdid       = " << trdid        << std::endl;
+    std::cout << "pktid       = " << pktid        << std::endl;
+    std::cout << "proc_read   = " << proc_read    << std::endl;
+    std::cout << "read_length = " << read_length  << std::endl;
+    std::cout << "word_index  = " << word_index   << std::endl; 
+    for(size_t i=0; i<wdata_be.size() ; i++){
+      std::cout << "wdata_be [" << i <<"] = " << wdata_be[i] << std::endl;
+    }
+    for(size_t i=0; i<wdata.size() ; i++){
+      std::cout << "wdata [" << i <<"] = " << wdata[i] << std::endl;
+    }
+    std::cout << std::endl;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // 		Constructors
+  /////////////////////////////////////////////////////////////////////
+
+  TransactionTabEntry()
+    {
+      wdata_be.clear();
+      wdata.clear();
+      valid=false;
+    }
+
+  TransactionTabEntry(const TransactionTabEntry &source){
+    valid	    = source.valid;
+    xram_read	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read	= source.proc_read;
+    read_length = source.read_length;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+}; // end class TransactionTabEntry
+
+////////////////////////////////////////////////////////////////////////
+//                  The transaction tab                              
+////////////////////////////////////////////////////////////////////////
+class TransactionTab{
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ private:
+  size_t size_tab;                // The size of the tab
+
+  data_t be_to_mask(be_t be)
+  {
+    data_t ret = 0;
+    if ( be&0x1 ) {
+      ret = ret | 0x000000FF;
+    }
+    if ( be&0x2 ) {
+      ret = ret | 0x0000FF00;
+    }
+    if ( be&0x4 ) {
+      ret = ret | 0x00FF0000;
+    }
+    if ( be&0x8 ) {
+      ret = ret | 0xFF000000;
+    }
+    return ret;
+  }
+
+ public:
+  TransactionTabEntry *tab;       // The transaction tab
+
+  ////////////////////////////////////////////////////////////////////
+  //		Constructors
+  ////////////////////////////////////////////////////////////////////
+  TransactionTab()
+    {
+      size_tab=0;
+      tab=NULL;
+    }
+
+  TransactionTab(size_t n_entries, size_t n_words)
+    {
+      size_tab = n_entries;
+      tab = new TransactionTabEntry[size_tab];
+      for ( size_t i=0; i<size_tab; i++) {
+	tab[i].alloc(n_words);
+      }
+    }
+
+  ~TransactionTab()
+    {
+      delete [] tab;
+    }
+
+  /////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab
+  /////////////////////////////////////////////////////////////////////
+  size_t size()
+  {
+    return size_tab;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the transaction tab entries
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The print() function prints a transaction tab entry
+  // Arguments :
+  // - index : the index of the entry to print
+  /////////////////////////////////////////////////////////////////////
+  void print(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    tab[index].print();
+    return;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read() function returns a transaction tab entry.
+  // Arguments :
+  // - index : the index of the entry to read
+  /////////////////////////////////////////////////////////////////////
+  TransactionTabEntry read(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    return tab[index];
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The full() function returns the state of the transaction tab
+  // Arguments :
+  // - index : (return argument) the index of an empty entry 
+  // The function returns true if the transaction tab is full
+  /////////////////////////////////////////////////////////////////////
+  bool full(size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(!tab[i].valid){
+	    index=i;
+	    return false;	
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The hit_read() function checks if an XRAM read transaction exists 
+  // for a given cache line.
+  // Arguments :
+  // - index : (return argument) the index of the hit entry, if there is 
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a read request has already been sent
+  //////////////////////////////////////////////////////////////////////
+  bool hit_read(const addr_t nline,size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if((tab[i].valid && (nline==tab[i].nline)) && (tab[i].xram_read)) {
+	    index=i;
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  ///////////////////////////////////////////////////////////////////////
+  // The hit_write() function looks if an XRAM write transaction exists 
+  // for a given line.
+  // Arguments :
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a write request has already been sent
+  ///////////////////////////////////////////////////////////////////////
+  bool hit_write(const addr_t nline)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(tab[i].valid && (nline==tab[i].nline) && !(tab[i].xram_read)) {
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_data_mask() function writes a vector of data (a line).
+  // The data is written only if the corresponding bits are set
+  // in the be vector. 
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  // - be   : vector of be 
+  // - data : vector of data
+  /////////////////////////////////////////////////////////////////////
+  void write_data_mask(const size_t index, 
+		       const std::vector<be_t> &be, 
+		       const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    assert(be.size()==tab[index].wdata_be.size() 
+	   && "Bad data mask in write_data_mask in TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data in write_data_mask in TransactionTab");
+
+    for(size_t i=0; i<tab[index].wdata_be.size() ; i++) {
+      tab[index].wdata_be[i] = tab[index].wdata_be[i] | be[i];
+      data_t mask = be_to_mask(be[i]);
+      tab[index].wdata[i] = (tab[index].wdata[i] & ~mask) | (data[i] & mask);
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The set() function registers a transaction (read or write)
+  // to the XRAM in the transaction tab.
+  // Arguments :
+  // - index : index in the transaction tab
+  // - xram_read : transaction type (read or write a cache line)
+  // - nline : the index (zy) of the cache line
+  // - srcid : srcid of the initiator that caused the transaction
+  // - trdid : trdid of the initiator that caused the transaction
+  // - pktid : pktid of the initiator that caused the transaction
+  // - proc_read : does the initiator want a copy
+  // - read_length : length of read (in case of processor read)
+  // - word_index : index in the line (in case of single word read)
+  // - data : the data to write (in case of write)
+  // - data_be : the mask of the data to write (in case of write)
+  /////////////////////////////////////////////////////////////////////
+  void set(const size_t index,
+	   const bool xram_read,
+	   const addr_t nline,
+	   const size_t srcid,
+	   const size_t trdid,
+	   const size_t pktid,
+	   const bool proc_read,
+	   const size_t read_length,
+	   const size_t word_index,
+	   const std::vector<be_t> &data_be,
+	   const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in set() Transaction Tab");
+    assert(data_be.size()==tab[index].wdata_be.size() 
+	   && "Bad data_be argument in set() TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data argument in set() TransactionTab");
+
+    tab[index].valid	        = true;
+    tab[index].xram_read        = xram_read;
+    tab[index].nline	        = nline;
+    tab[index].srcid	        = srcid;
+    tab[index].trdid	        = trdid;
+    tab[index].pktid	        = pktid;
+    tab[index].proc_read	    = proc_read;
+    tab[index].read_length	    = read_length;
+    tab[index].word_index	    = word_index;
+    for(size_t i=0; i<tab[index].wdata.size(); i++) {
+      tab[index].wdata_be[i]    = data_be[i];
+      tab[index].wdata[i]       = data[i];
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_rsp() function writes a word of the response to an 
+  // XRAM read transaction.
+  // The data is only written when the corresponding BE field is Ox0.
+  // Arguments :
+  // - index : the index of the transaction in the transaction tab
+  // - word_index : the index of the data in the line
+  // - data : the data to write
+  /////////////////////////////////////////////////////////////////////
+  void write_rsp(const size_t index,
+		 const size_t word,
+		 const data_t data)
+  {
+    assert( (index < size_tab) 
+	    && "Selected entry  out of range in write_rsp() Transaction Tab");
+    assert( (word <= tab[index].wdata_be.size()) 
+	    && "Bad word_index in write_rsp() in TransactionTab");
+    assert( tab[index].valid 
+	    && "Transaction Tab Entry invalid in write_rsp()");
+    assert( tab[index].xram_read 
+	    && "Selected entry is not an XRAM read transaction in write_rsp()");
+
+    data_t mask = be_to_mask(tab[index].wdata_be[word]);
+    tab[index].wdata[word] = (tab[index].wdata[word] & mask) | (data & ~mask);
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The erase() function erases an entry in the transaction tab.
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  /////////////////////////////////////////////////////////////////////
+  void erase(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in erase() Transaction Tab");
+    tab[index].valid	= false;
+  }
+}; // end class TransactionTab
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v2/caba/source/src/vci_mem_cache_v2.cpp
===================================================================
--- trunk/modules/vci_mem_cache_v2/caba/source/src/vci_mem_cache_v2.cpp	(revision 2)
+++ trunk/modules/vci_mem_cache_v2/caba/source/src/vci_mem_cache_v2.cpp	(revision 2)
@@ -0,0 +1,3831 @@
+/* -*- c++ -*-
+ * File 	: vci_mem_cache_v2.cpp
+ * Date 	: 30/10/2008
+ * Copyright 	: UPMC / LIP6
+ * Authors 	: Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+#include "../include/vci_mem_cache_v2.h"
+
+//#define TDEBUG // Transaction tab debug
+//#define IDEBUG // Update tab debug
+//#define DDEBUG // Directory debug
+//#define DEBUG_VCI_MEM_CACHE 1
+#define RANDOMIZE_SC
+
+namespace soclib { namespace caba {
+
+#ifdef DEBUG_VCI_MEM_CACHE 
+  const char *tgt_cmd_fsm_str[] = {
+    "TGT_CMD_IDLE",
+    "TGT_CMD_READ",
+    "TGT_CMD_READ_EOP",
+    "TGT_CMD_WRITE",
+    "TGT_CMD_ATOMIC",
+  };
+  const char *tgt_rsp_fsm_str[] = {
+    "TGT_RSP_READ_IDLE",
+    "TGT_RSP_WRITE_IDLE",
+    "TGT_RSP_LLSC_IDLE",
+    "TGT_RSP_XRAM_IDLE",
+    "TGT_RSP_INIT_IDLE",
+    "TGT_RSP_CLEANUP_IDLE",
+    "TGT_RSP_READ",
+    "TGT_RSP_WRITE",
+    "TGT_RSP_LLSC",
+    "TGT_RSP_XRAM",
+    "TGT_RSP_INIT",
+    "TGT_RSP_CLEANUP",
+  };
+  const char *init_cmd_fsm_str[] = {
+    "INIT_CMD_INVAL_IDLE",
+    "INIT_CMD_INVAL_SEL",
+    "INIT_CMD_INVAL_NLINE",
+    "INIT_CMD_UPDT_IDLE",
+    "INIT_CMD_UPDT_SEL",
+    "INIT_CMD_BRDCAST",
+    "INIT_CMD_UPDT_NLINE",
+    "INIT_CMD_UPDT_INDEX",
+    "INIT_CMD_UPDT_DATA",
+    "INIT_CMD_SC_UPDT_IDLE",
+    "INIT_CMD_SC_UPDT_SEL",
+    "INIT_CMD_SC_BRDCAST",
+    "INIT_CMD_SC_UPDT_NLINE",
+    "INIT_CMD_SC_UPDT_INDEX",
+    "INIT_CMD_SC_UPDT_DATA",
+  };
+  const char *init_rsp_fsm_str[] = {
+    "INIT_RSP_IDLE",
+    "INIT_RSP_UPT_LOCK",
+    "INIT_RSP_UPT_CLEAR",
+    "INIT_RSP_END",
+  };
+  const char *read_fsm_str[] = {
+    "READ_IDLE",
+    "READ_DIR_LOCK",
+    "READ_DIR_HIT",
+    "READ_RSP",
+    "READ_TRT_LOCK",
+    "READ_TRT_SET",
+    "READ_XRAM_REQ",
+  };
+  const char *write_fsm_str[] = {
+    "WRITE_IDLE",
+    "WRITE_NEXT",
+    "WRITE_DIR_LOCK",
+    "WRITE_DIR_HIT_READ",
+    "WRITE_DIR_HIT",
+    "WRITE_DIR_HIT_RSP",
+    "WRITE_UPT_LOCK",
+    "WRITE_WAIT_UPT",
+    "WRITE_UPDATE",
+    "WRITE_RSP",
+    "WRITE_TRT_LOCK",
+    "WRITE_TRT_DATA",
+    "WRITE_TRT_SET",
+    "WRITE_WAIT_TRT",
+    "WRITE_XRAM_REQ",
+    "WRITE_TRT_WRITE_LOCK",
+    "WRITE_INVAL_LOCK",
+    "WRITE_DIR_INVAL",
+    "WRITE_INVAL",
+    "WRITE_XRAM_SEND",
+  };
+  const char *ixr_rsp_fsm_str[] = {
+    "IXR_RSP_IDLE",
+    "IXR_RSP_ACK",
+    "IXR_RSP_TRT_ERASE",
+    "IXR_RSP_TRT_READ",
+  };
+  const char *xram_rsp_fsm_str[] = {
+    "XRAM_RSP_IDLE",
+    "XRAM_RSP_TRT_COPY",
+    "XRAM_RSP_TRT_DIRTY",
+    "XRAM_RSP_DIR_LOCK",
+    "XRAM_RSP_DIR_UPDT",
+    "XRAM_RSP_DIR_RSP",
+    "XRAM_RSP_INVAL_LOCK",
+    "XRAM_RSP_INVAL_WAIT",
+    "XRAM_RSP_INVAL",
+    "XRAM_RSP_WRITE_DIRTY",
+  };
+  const char *ixr_cmd_fsm_str[] = {
+    "IXR_CMD_READ_IDLE",
+    "IXR_CMD_WRITE_IDLE",
+    "IXR_CMD_LLSC_IDLE",
+    "IXR_CMD_XRAM_IDLE",
+    "IXR_CMD_READ_NLINE",
+    "IXR_CMD_WRITE_NLINE",
+    "IXR_CMD_LLSC_NLINE",
+    "IXR_CMD_XRAM_DATA",
+  };
+  const char *llsc_fsm_str[] = {
+    "LLSC_IDLE",
+    "LL_DIR_LOCK",
+    "LL_DIR_HIT",
+    "LL_RSP",
+    "SC_DIR_LOCK",
+    "SC_DIR_HIT",
+    "SC_UPT_LOCK",
+    "SC_WAIT_UPT",
+    "SC_UPDATE",
+    "SC_TRT_LOCK",
+    "SC_INVAL_LOCK",
+    "SC_DIR_INVAL",
+    "SC_INVAL",
+    "SC_XRAM_SEND",
+    "SC_RSP_FALSE",
+    "SC_RSP_TRUE",
+    "LLSC_TRT_LOCK",
+    "LLSC_TRT_SET",
+    "LLSC_XRAM_REQ",
+  };
+  const char *cleanup_fsm_str[] = {
+    "CLEANUP_IDLE",
+    "CLEANUP_DIR_LOCK",
+    "CLEANUP_DIR_WRITE",
+    "CLEANUP_UPT_LOCK",
+    "CLEANUP_UPT_WRITE",
+    "CLEANUP_WRITE_RSP",
+    "CLEANUP_RSP",
+  };
+  const char *alloc_dir_fsm_str[] = {
+    "ALLOC_DIR_READ",
+    "ALLOC_DIR_WRITE",
+    "ALLOC_DIR_LLSC",
+    "ALLOC_DIR_CLEANUP",
+    "ALLOC_DIR_XRAM_RSP",
+  };
+  const char *alloc_trt_fsm_str[] = {
+    "ALLOC_TRT_READ",
+    "ALLOC_TRT_WRITE",
+    "ALLOC_TRT_LLSC",
+    "ALLOC_TRT_XRAM_RSP",
+    "ALLOC_TRT_IXR_RSP",
+  };
+  const char *alloc_upt_fsm_str[] = {
+    "ALLOC_UPT_WRITE",
+    "ALLOC_UPT_XRAM_RSP",
+    "ALLOC_UPT_INIT_RSP",
+    "ALLOC_UPT_CLEANUP",
+  };
+#endif
+
+#define tmpl(x) template<typename vci_param> x VciMemCacheV2<vci_param>
+
+  using soclib::common::uint32_log2;
+
+  ////////////////////////////////
+  // 	Constructor 
+  ////////////////////////////////
+
+  tmpl(/**/)::VciMemCacheV2( 
+      sc_module_name name,
+      const soclib::common::MappingTable &mtp,
+      const soclib::common::MappingTable &mtc,
+      const soclib::common::MappingTable &mtx,
+      const soclib::common::IntTab &vci_ixr_index,
+      const soclib::common::IntTab &vci_ini_index,
+      const soclib::common::IntTab &vci_tgt_index,
+      const soclib::common::IntTab &vci_tgt_index_cleanup,
+      size_t nways,
+      size_t nsets,
+      size_t nwords)
+
+    : soclib::caba::BaseModule(name),
+
+    p_clk("clk"),
+    p_resetn("resetn"),
+    p_vci_tgt("vci_tgt"),
+    p_vci_tgt_cleanup("vci_tgt_cleanup"),
+    p_vci_ini("vci_ini"),
+    p_vci_ixr("vci_ixr"),
+
+    m_initiators( 32 ),
+    m_ways( nways ),
+    m_sets( nsets ),
+    m_words( nwords ),
+    m_srcid_ixr( mtx.indexForId(vci_ixr_index) ),
+    m_srcid_ini( mtc.indexForId(vci_ini_index) ),
+    m_seglist(mtp.getSegmentList(vci_tgt_index)),
+    m_cseglist(mtc.getSegmentList(vci_tgt_index_cleanup)),
+    m_coherence_table( mtc.getCoherenceTable<vci_addr_t>() ),
+    m_atomic_tab( m_initiators ),
+    m_transaction_tab( TRANSACTION_TAB_LINES, nwords ),
+    m_update_tab( UPDATE_TAB_LINES ),
+    m_cache_directory( nways, nsets, nwords, vci_param::N ),
+#define L2 soclib::common::uint32_log2
+    m_x( L2(m_words), 2),
+    m_y( L2(m_sets), L2(m_words) + 2),
+    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
+    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
+#undef L2
+
+    //  FIFOs 
+    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
+    m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
+    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
+    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
+    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
+
+    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
+    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
+    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
+    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
+    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
+    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
+    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
+
+    m_cmd_llsc_addr_fifo("m_cmd_llsc_addr_fifo",4),
+    m_cmd_llsc_sc_fifo("m_cmd_llsc_sc_fifo",4),
+    m_cmd_llsc_srcid_fifo("m_cmd_llsc_srcid_fifo",4),
+    m_cmd_llsc_trdid_fifo("m_cmd_llsc_trdid_fifo",4),
+    m_cmd_llsc_pktid_fifo("m_cmd_llsc_pktid_fifo",4),
+    m_cmd_llsc_wdata_fifo("m_cmd_llsc_wdata_fifo",4),
+
+    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
+    
+    nseg(0),	
+    ncseg(0),	
+
+    r_read_fsm("r_read_fsm"),
+    r_write_fsm("r_write_fsm"),
+    r_init_rsp_fsm("r_init_rsp_fsm"),
+    r_cleanup_fsm("r_cleanup_fsm"),
+    r_llsc_fsm("r_llsc_fsm"),
+    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
+    r_xram_rsp_fsm("r_xram_rsp_fsm"),
+    r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
+    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
+    r_init_cmd_fsm("r_init_cmd_fsm"),
+    r_alloc_dir_fsm("r_alloc_dir_fsm"),
+    r_alloc_trt_fsm("r_alloc_trt_fsm"),
+    r_alloc_upt_fsm("r_alloc_upt_fsm")
+    {
+      assert(IS_POW_OF_2(nsets));
+      assert(IS_POW_OF_2(nwords));
+      assert(IS_POW_OF_2(nways));
+      assert(nsets);
+      assert(nwords);
+      assert(nways);
+      assert(nsets <= 1024);
+      assert(nwords <= 32);
+      assert(nways <= 32);
+
+
+      // Get the segments associated to the MemCache 
+      std::list<soclib::common::Segment>::iterator seg;
+
+      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
+        nseg++;
+      }
+      for(seg = m_cseglist.begin(); seg != m_cseglist.end() ; seg++) {
+        ncseg++;
+      }
+
+      m_seg = new soclib::common::Segment*[nseg];
+      size_t i = 0;
+      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) { 
+        m_seg[i] = &(*seg);
+        i++;
+      }
+      m_cseg = new soclib::common::Segment*[ncseg];
+      i = 0;
+      for ( seg = m_cseglist.begin() ; seg != m_cseglist.end() ; seg++ ) { 
+          m_cseg[i] = &(*seg);
+          i++;
+      }
+
+      // Memory cache allocation & initialisation
+      m_cache_data = new data_t**[nways];
+      for ( size_t i=0 ; i<nways ; ++i ) {
+        m_cache_data[i] = new data_t*[nsets];
+      }
+      for ( size_t i=0; i<nways; ++i ) {
+        for ( size_t j=0; j<nsets; ++j ) {
+          m_cache_data[i][j] = new data_t[nwords];
+          for ( size_t k=0; k<nwords; k++){
+            m_cache_data[i][j][k]=0;
+          }	
+        }
+      }
+
+      // Allocation for IXR_RSP FSM
+      r_ixr_rsp_to_xram_rsp_rok	    = new sc_signal<bool>[TRANSACTION_TAB_LINES];
+
+      // Allocation for XRAM_RSP FSM
+      r_xram_rsp_victim_data        = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_tgt_rsp_data    = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
+
+      // Allocation for READ FSM
+      r_read_data 			        = new sc_signal<data_t>[nwords];
+      r_read_to_tgt_rsp_data 		= new sc_signal<data_t>[nwords];
+
+      // Allocation for WRITE FSM
+      r_write_data 			        = new sc_signal<data_t>[nwords];
+      r_write_be 			        = new sc_signal<be_t>[nwords];
+      r_write_to_init_cmd_data 		= new sc_signal<data_t>[nwords];
+      r_write_to_init_cmd_we		= new sc_signal<bool>[nwords];
+      r_write_to_ixr_cmd_data	    = new sc_signal<data_t>[nwords];
+
+      // Allocation for LLSC FSM
+      r_llsc_to_ixr_cmd_data	    = new sc_signal<data_t>[nwords];
+
+
+      // Simulation
+
+      SC_METHOD(transition);
+      dont_initialize();
+      sensitive << p_clk.pos();
+
+      SC_METHOD(genMoore);
+      dont_initialize();
+      sensitive << p_clk.neg();
+
+    } // end constructor
+
+  /////////////////////////////////////////
+  // This function prints the statistics 
+  /////////////////////////////////////////
+
+  tmpl(void)::print_stats()
+  {
+    std::cout << "----------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
+      << "- READ RATE            = " << (double)m_cpt_read/m_cpt_cycles << std::endl
+      << "- READ MISS RATE       = " << (double)m_cpt_read_miss/m_cpt_read << std::endl
+      << "- WRITE RATE           = " << (double)m_cpt_write/m_cpt_cycles << std::endl
+      << "- WRITE MISS RATE      = " << (double)m_cpt_write_miss/m_cpt_write << std::endl
+      << "- WRITE BURST LENGTH   = " << (double)m_cpt_write_cells/m_cpt_write << std::endl
+      << "- UPDATE RATE          = " << (double)m_cpt_update/m_cpt_cycles << std::endl
+      << "- UPDATE ARITY         = " << (double)m_cpt_update_mult/m_cpt_update << std::endl
+      << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
+      << "- INVAL MULTICAST ARITY= " << (double)m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
+      << "- INVAL BROADCAST RATE = " << (double)m_cpt_inval_brdcast/m_cpt_cycles << std::endl
+      << "- SAVE DIRTY RATE      = " << (double)m_cpt_write_dirty/m_cpt_cycles << std::endl
+      << "- CLEANUP RATE         = " << (double)m_cpt_cleanup/m_cpt_cycles << std::endl
+      << "- LL RATE              = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
+      << "- SC RATE              = " << (double)m_cpt_sc/m_cpt_cycles << std::endl;
+  }
+
+  /////////////////////////////////
+  tmpl(/**/)::~VciMemCacheV2()
+    /////////////////////////////////
+  {
+    for(size_t i=0; i<m_ways ; i++){
+      for(size_t j=0; j<m_sets ; j++){
+        delete [] m_cache_data[i][j];
+      }
+    }
+    for(size_t i=0; i<m_ways ; i++){
+      delete [] m_cache_data[i];
+    }
+    delete [] m_cache_data;
+    delete [] m_coherence_table;
+
+    delete [] r_ixr_rsp_to_xram_rsp_rok;
+
+    delete [] r_xram_rsp_victim_data;
+    delete [] r_xram_rsp_to_tgt_rsp_data;
+    delete [] r_xram_rsp_to_ixr_cmd_data;
+
+    delete [] r_read_data;
+    delete [] r_read_to_tgt_rsp_data;
+
+    delete [] r_write_data;
+    delete [] r_write_be;
+    delete [] r_write_to_init_cmd_data;
+  }
+
+  //////////////////////////////////
+  tmpl(void)::transition()
+    //////////////////////////////////
+  {
+    using soclib::common::uint32_log2;
+    //  RESET          
+    if ( ! p_resetn.read() ) {
+
+      //     Initializing FSMs
+      r_tgt_cmd_fsm 	= TGT_CMD_IDLE;
+      r_tgt_rsp_fsm 	= TGT_RSP_READ_IDLE;
+      r_init_cmd_fsm 	= INIT_CMD_INVAL_IDLE;
+      r_init_rsp_fsm 	= INIT_RSP_IDLE;
+      r_read_fsm 	= READ_IDLE;
+      r_write_fsm 	= WRITE_IDLE;
+      r_llsc_fsm 	= LLSC_IDLE;
+      r_cleanup_fsm 	= CLEANUP_IDLE;
+      r_alloc_dir_fsm   = ALLOC_DIR_READ;
+      r_alloc_trt_fsm   = ALLOC_TRT_READ;
+      r_alloc_upt_fsm   = ALLOC_UPT_WRITE;
+      r_ixr_rsp_fsm 	= IXR_RSP_IDLE;
+      r_xram_rsp_fsm 	= XRAM_RSP_IDLE;
+      r_ixr_cmd_fsm 	= IXR_CMD_READ_IDLE;
+
+      //  Initializing Tables
+      m_cache_directory.init();
+      m_atomic_tab.init();	
+      m_transaction_tab.init();
+
+      // initializing FIFOs and communication Buffers
+
+      m_cmd_read_addr_fifo.init();
+      m_cmd_read_length_fifo.init();
+      m_cmd_read_srcid_fifo.init();
+      m_cmd_read_trdid_fifo.init();
+      m_cmd_read_pktid_fifo.init();
+
+      m_cmd_write_addr_fifo.init();
+      m_cmd_write_eop_fifo.init();
+      m_cmd_write_srcid_fifo.init();
+      m_cmd_write_trdid_fifo.init();
+      m_cmd_write_pktid_fifo.init();
+      m_cmd_write_data_fifo.init();
+
+      m_cmd_llsc_addr_fifo.init();
+      m_cmd_llsc_srcid_fifo.init();
+      m_cmd_llsc_trdid_fifo.init();
+      m_cmd_llsc_pktid_fifo.init();
+      m_cmd_llsc_wdata_fifo.init();
+      m_cmd_llsc_sc_fifo.init();
+
+      r_read_to_tgt_rsp_req	    = false;
+      r_read_to_ixr_cmd_req	    = false;
+
+      r_write_to_tgt_rsp_req	= false;
+      r_write_to_ixr_cmd_req	= false;
+      r_write_to_init_cmd_req	= false;
+
+      r_cleanup_to_tgt_rsp_req	= false;
+
+      r_init_rsp_to_tgt_rsp_req	= false;
+
+      r_llsc_lfsr                       = -1;
+      r_llsc_to_tgt_rsp_req	    = false;
+      r_llsc_to_ixr_cmd_req	    = false;
+      r_llsc_to_init_cmd_req	= false;
+
+      for(size_t i=0; i<TRANSACTION_TAB_LINES ; i++){
+        r_ixr_rsp_to_xram_rsp_rok[i] = false;
+      }
+
+      r_xram_rsp_to_tgt_rsp_req	    = false;
+      r_xram_rsp_to_init_cmd_req    = false;
+      r_xram_rsp_to_ixr_cmd_req	    = false;
+      r_xram_rsp_trt_index	        = 0;
+
+      r_ixr_cmd_cpt         = 0;
+
+      r_copies_limit        = 3;
+
+      // Activity counters
+      m_cpt_cycles		    = 0;
+      m_cpt_read		    = 0;
+      m_cpt_read_miss	    = 0;
+      m_cpt_write		    = 0;
+      m_cpt_write_miss	    = 0;
+      m_cpt_write_cells	    = 0;
+      m_cpt_write_dirty	    = 0;
+      m_cpt_update		    = 0;
+      m_cpt_update_mult     = 0;
+      m_cpt_inval_brdcast 	= 0;
+      m_cpt_inval 		    = 0;
+      m_cpt_inval_mult 		= 0;
+      m_cpt_cleanup		    = 0;
+      m_cpt_ll     		    = 0;
+      m_cpt_sc     		    = 0;
+
+      return;
+    }
+
+    bool    cmd_read_fifo_put = false;
+    bool    cmd_read_fifo_get = false;
+
+    bool    cmd_write_fifo_put = false;
+    bool    cmd_write_fifo_get = false;
+
+    bool    cmd_llsc_fifo_put = false;
+    bool    cmd_llsc_fifo_get = false;
+
+#if DEBUG_VCI_MEM_CACHE 
+    std::cout << "---------------------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
+      << " - TGT_CMD FSM   = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
+      << " - TGT_RSP FSM   = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
+      << " - INIT_CMD FSM  = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
+      << " - INIT_RSP FSM  = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
+      << " - READ FSM      = " << read_fsm_str[r_read_fsm] << std::endl
+      << " - WRITE FSM     = " << write_fsm_str[r_write_fsm] << std::endl
+      << " - LLSC FSM      = " << llsc_fsm_str[r_llsc_fsm] << std::endl
+      << " - CLEANUP FSM   = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
+      << " - IXR_CMD FSM  = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
+      << " - IXR_RSP FSM   = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
+      << " - XRAM_RSP FSM  = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
+      << " - ALLOC_DIR FSM = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
+      << " - ALLOC_TRT FSM = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
+      << " - ALLOC_UPT FSM = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl;
+#endif
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
+    //
+    // There is 4 types of packets for the m_mem_segment :
+    // - READ    : a READ request has a length of 1 VCI cell. It can be a single word 
+    //             or an entire cache line, depending on the PLEN value.
+    // - WRITE   : a WRITE request has a maximum length of 16 cells, and can only
+    //             concern words in a same line.
+    // - LL      : The LL request has a length of 1 cell.
+    // - SC      : The SC request has a length of 1 cell. 
+    //             The WDATA field contains the data to write.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_cmd_fsm.read() ) {
+
+      //////////////////
+      case TGT_CMD_IDLE:
+        {
+          if ( p_vci_tgt.cmdval ) {
+            assert( (p_vci_tgt.srcid.read() < m_initiators)
+                && "VCI_MEM_CACHE error in VCI_MEM_CACHE : The received SRCID is larger than 31");
+
+            bool reached = false;
+            for ( size_t index = 0 ; index < nseg && !reached ; index++) 
+            {
+//              if ( m_seg[index]->contains((addr_t)(p_vci_tgt.address.read())) ) {
+              if ( m_seg[index]->contains(p_vci_tgt.address.read()) ) {
+                reached = true;
+                r_index = index;
+              }
+            }
+
+
+            if ( !reached ) 
+            { 
+              std::cout << "VCI_MEM_CACHE Out of segment access in VCI_MEM_CACHE" << std::endl;
+              std::cout << "Faulty address = " << std::hex << (addr_t)(p_vci_tgt.address.read()) << std::endl;
+              std::cout << "Faulty initiator = " << std::dec << p_vci_tgt.srcid.read() << std::endl;
+              exit(0);
+            } 
+            else if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_READ;
+            } 
+            else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ))
+            {  
+              r_tgt_cmd_fsm = TGT_CMD_WRITE;
+            } 
+            else if ((p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ) || 
+                (p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND) ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
+            } 
+          }
+          break;
+        }
+        //////////////////
+      case TGT_CMD_READ:
+
+        {
+          assert(((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2))<=16)
+              && "VCI_MEM_CACHE All read request to the MemCache must stay within a cache line"); 
+
+          if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) {
+            cmd_read_fifo_put = true;
+            if ( p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+            else                  r_tgt_cmd_fsm = TGT_CMD_READ_EOP;		
+          } 
+          break;
+        }
+        //////////////////////
+      case TGT_CMD_READ_EOP:
+        {
+          if ( p_vci_tgt.cmdval && p_vci_tgt.eop ){
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_CMD_WRITE:
+        {
+
+          if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() ) {
+            cmd_write_fifo_put = true;
+            if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+
+          }
+          break;
+        }
+        ////////////////////
+      case TGT_CMD_ATOMIC:
+        {
+          assert(p_vci_tgt.eop && "Memory Cache Error: LL or SC command with length > 1 ");
+
+          if ( p_vci_tgt.cmdval && m_cmd_llsc_addr_fifo.wok() ) {
+            cmd_llsc_fifo_put = true;
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+    } // end switch tgt_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////////
+    //		INIT_RSP FSM
+    /////////////////////////////////////////////////////////////////////////
+    // This FSM controls the response to the update or invalidate requests
+    // sent by the memory cache to the L1 caches :
+    //
+    // - update request initiated by the WRITE FSM.  
+    //   The FSM decrements the proper entry in the Update/Inval Table.
+    //   It sends a request to the TGT_RSP FSM to complete the pending 
+    //   write transaction (acknowledge response to the writer processor), 
+    //   and clear the UPT entry when all responses have been received.  
+    // - invalidate request initiated by the XRAM_RSP FSM.
+    //   The FSM decrements the proper entry in the Update/Inval_Table,
+    //   and clear the entry when all responses have been received.
+    //
+    // All those response packets are one word, compact
+    // packets complying with the VCI advanced format. 
+    // The index in the Table is defined in the RTRDID field, and
+    // the Transaction type is defined in the Update/Inval Table.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_rsp_fsm.read() ) {
+
+      ///////////////////
+      case INIT_RSP_IDLE:
+        {
+
+          if ( p_vci_ini.rspval ) {
+
+            assert ( ( p_vci_ini.rtrdid.read() < m_update_tab.size() )
+                && "VCI_MEM_CACHE UPT index too large in VCI response paquet received by memory cache" );
+            assert ( p_vci_ini.reop 
+                && "VCI_MEM_CACHE All response packets to update/invalidate requests must be one cell" );
+            r_init_rsp_upt_index = p_vci_ini.rtrdid.read(); 
+            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_RSP_UPT_LOCK:	// decrement the number of expected responses
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) { 
+            size_t count = 0;
+            bool valid  = m_update_tab.decrement(r_init_rsp_upt_index.read(), count);
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+#endif
+            assert ( valid 
+                && "VCI_MEM_CACHE Invalid UPT entry in VCI response paquet received by memory cache" );
+
+            if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
+            else              r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_RSP_UPT_CLEAR:	// clear the UPT entry
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) {
+            r_init_rsp_srcid = m_update_tab.srcid(r_init_rsp_upt_index.read());
+            r_init_rsp_trdid = m_update_tab.trdid(r_init_rsp_upt_index.read());
+            r_init_rsp_pktid = m_update_tab.pktid(r_init_rsp_upt_index.read());
+            r_init_rsp_nline = m_update_tab.nline(r_init_rsp_upt_index.read());
+            bool need_rsp = m_update_tab.need_rsp(r_init_rsp_upt_index.read());
+            if ( need_rsp ) r_init_rsp_fsm = INIT_RSP_END;
+            else            r_init_rsp_fsm = INIT_RSP_IDLE;
+            m_update_tab.clear(r_init_rsp_upt_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_CLEAR update table : " << std::endl;
+	m_update_tab.print();
+#endif
+          }
+          break;
+        }
+        //////////////////
+      case INIT_RSP_END:
+        {
+
+          if ( !r_init_rsp_to_tgt_rsp_req ) {
+            r_init_rsp_to_tgt_rsp_req = true;
+            r_init_rsp_to_tgt_rsp_srcid = r_init_rsp_srcid.read();
+            r_init_rsp_to_tgt_rsp_trdid = r_init_rsp_trdid.read();
+            r_init_rsp_to_tgt_rsp_pktid = r_init_rsp_pktid.read();
+            r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+    } // end switch r_init_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		READ FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The READ FSM controls the read requests sent by processors.
+    // It takes the lock protecting the cache directory to check the cache line status:
+    // - In case of HIT, the fsm copies the data (one line, or one single word)
+    //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
+    //   The requesting initiator is registered in the cache directory.
+    // - In case of MISS, the READ fsm takes the lock protecting the transaction tab.
+    //   If a read transaction to the XRAM for this line already exists,
+    //   or if the transaction tab is full, the fsm is stalled.
+    //   If a transaction entry is free, the READ fsm sends a request to the XRAM.
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_read_fsm.read() ) {
+
+      ///////////////
+      case READ_IDLE:
+        {
+          if (m_cmd_read_addr_fifo.rok()) {
+            m_cpt_read++;
+            r_read_fsm = READ_DIR_LOCK;
+          }
+          break;
+        }
+        ///////////////////
+      case READ_DIR_LOCK:	// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            size_t way = 0;
+            DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
+#ifdef DDEBUG
+	   std::cout << "In READ_DIR_LOCK printing the entry of address is : " << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            r_read_is_cnt   = entry.is_cnt;
+            r_read_dirty    = entry.dirty;
+            r_read_tag	    = entry.tag;
+            r_read_lock	    = entry.lock;
+            r_read_way	    = way;
+            r_read_d_copies = entry.d_copies; 
+            r_read_i_copies = entry.i_copies; 
+            r_read_count    = entry.count;
+
+            // In case of hit, the read acces must be registered in the copies bit-vector
+            if( entry.valid )  { 
+              r_read_fsm = READ_DIR_HIT;
+            } else {
+              r_read_fsm = READ_TRT_LOCK;
+              m_cpt_read_miss++;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_DIR_HIT:	// read hit : update the memory cache
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            // signals generation
+            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
+            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
+            bool is_cnt = ((r_read_count.read() >= r_copies_limit.read()) && cached_read) || r_read_is_cnt.read();
+
+            // read data in the cache
+            size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            size_t way = r_read_way.read();
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_data[i] = m_cache_data[way][set][i];
+            }
+
+            // update the cache directory (for the copies)
+            DirectoryEntry entry;
+            entry.valid	  = true;
+            entry.is_cnt  = is_cnt; // when we reach the limit of copies
+            entry.dirty	  = r_read_dirty.read();
+            entry.tag	  = r_read_tag.read();
+            entry.lock	  = r_read_lock.read();
+            if(cached_read){  // Cached read, we update the copies vector
+              if(inst_read && !is_cnt){ // Instruction read, vector mode
+                assert(!(r_read_i_copies.read() & (0x1 << m_cmd_read_srcid_fifo.read())) && "MemCache Error : processor read on an already owned cache line");
+                entry.d_copies  = r_read_d_copies.read();
+                entry.i_copies  = r_read_i_copies.read() | (0x1 << m_cmd_read_srcid_fifo.read()); 
+                entry.count     = r_read_count.read() + 1;
+              }
+              if(!inst_read && !is_cnt){ // Data read, vector mode
+                assert(!(r_read_d_copies.read() & (0x1 << m_cmd_read_srcid_fifo.read())) && "MemCache Error : processor read on an already owned cache line");
+                entry.d_copies  = r_read_d_copies.read() | (0x1 << m_cmd_read_srcid_fifo.read()); 
+                entry.i_copies  = r_read_i_copies.read();
+                entry.count     = r_read_count.read() + 1;
+              }
+              if( is_cnt ) { // Counter mode
+                entry.count     = r_read_count.read() + 1;
+                entry.d_copies  = 0;
+                entry.i_copies  = 0;
+              } 
+            } else { // Uncached read
+              entry.d_copies = r_read_d_copies.read();
+              entry.i_copies = r_read_i_copies.read();
+              entry.count    = r_read_count.read();
+            }
+#ifdef DDEBUG
+	   std::cout << "In READ_DIR_HIT printing the entry of address is : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            m_cache_directory.write(set, way, entry);
+            r_read_fsm    = READ_RSP;
+          }
+          break;
+        }
+        //////////////
+      case READ_RSP: 		//  request the TGT_RSP FSM to return data
+        {
+          if( !r_read_to_tgt_rsp_req ) {	
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_to_tgt_rsp_data[i] = r_read_data[i];
+            }
+            r_read_to_tgt_rsp_word   = m_x[(vci_addr_t)m_cmd_read_addr_fifo.read()];
+            r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
+            cmd_read_fifo_get 		 = true;
+            r_read_to_tgt_rsp_req	 = true;
+            r_read_to_tgt_rsp_srcid	 = m_cmd_read_srcid_fifo.read();
+            r_read_to_tgt_rsp_trdid	 = m_cmd_read_trdid_fifo.read();
+            r_read_to_tgt_rsp_pktid	 = m_cmd_read_pktid_fifo.read();
+            r_read_fsm 			     = READ_IDLE;  
+          }
+          break;
+        }
+        ///////////////////
+      case READ_TRT_LOCK:	// read miss : check the Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t index = 0;
+            bool   hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())], index);
+            bool   hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())]);
+            bool   wok = !m_transaction_tab.full(index);
+            if( hit_read || !wok || hit_write ) {  // missing line already requested or no space
+              r_read_fsm = READ_IDLE;
+            } else {			   // missing line is requested to the XRAM
+              r_read_trt_index = index;
+              r_read_fsm       = READ_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_TRT_SET:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+            m_transaction_tab.set(r_read_trt_index.read(),
+                true,
+                m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
+                m_cmd_read_srcid_fifo.read(),
+                m_cmd_read_trdid_fifo.read(),
+                m_cmd_read_pktid_fifo.read(),
+                true,
+                m_cmd_read_length_fifo.read(),
+                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));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_read_fsm 	 = READ_XRAM_REQ;
+          }
+          break;
+        }
+        /////////////////////
+      case READ_XRAM_REQ:
+        {
+          if( !r_read_to_ixr_cmd_req ) {
+            cmd_read_fifo_get		= true;
+            r_read_to_ixr_cmd_req  	= true;
+            r_read_to_ixr_cmd_nline 	= m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            r_read_to_ixr_cmd_trdid 	= r_read_trt_index.read();
+            r_read_fsm 			          = READ_IDLE;
+          }
+          break;
+        }
+    } // end switch read_fsm
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //		WRITE FSM
+    ///////////////////////////////////////////////////////////////////////////////////
+    // The WRITE FSM handles the write bursts 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.
+    // Then the FSM takes the lock protecting the cache directory, to check
+    // if the line is in the cache.
+    //
+    // - In case of HIT, the cache is updated.
+    //   If there is no other copy, an acknowledge response is immediately
+    //   returned to the writing processor.
+    //   if the data is cached by other processoris, the FSM takes the lock
+    //   protecting the Update Table (UPT) to register this update transaction.
+    //   If the UPT is full, it releases the lock  and waits. Then, it sends 
+    //   a multi-update request to all owners of the line (but the writer), 
+    //   through the INIT_CMD FSM. In case of multi-update transaction, the WRITE FSM 
+    //   does not respond to the writing processor, as this response will be sent by 
+    //   the INIT_RSP FSM when all update responses have been received.
+    //
+    // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
+    //   table (TRT). If a read transaction to the XRAM for this line already exists, 
+    //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free, 
+    //   the WRITE FSM register a new transaction in TRT, and sends a read line request 
+    //   to the XRAM. If the TRT is full, it releases the lock, and waits.
+    //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_write_fsm.read() ) {
+
+      ////////////////
+      case WRITE_IDLE:	// copy first word of a write burst in local buffer	
+        {
+          if ( m_cmd_write_addr_fifo.rok()) {
+            m_cpt_write++;
+            m_cpt_write_cells++;
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get	= true;
+            size_t 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();
+            r_write_srcid	    = m_cmd_write_srcid_fifo.read();
+            r_write_trdid	    = m_cmd_write_trdid_fifo.read();
+            r_write_pktid	    = m_cmd_write_pktid_fifo.read();
+
+            // the be field must be set for all words 
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              if ( i == index ) r_write_be[i] = m_cmd_write_be_fifo.read();
+              else		        r_write_be[i] = 0x0;
+            }
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+                    r_write_byte=true;
+            else    r_write_byte=false;
+
+            if( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+            else                               r_write_fsm = WRITE_NEXT;
+          }
+          break;
+        }
+        ////////////////
+      case WRITE_NEXT:	// copy next word of a write burst in local buffer
+        {
+          if ( m_cmd_write_addr_fifo.rok() ) {
+            m_cpt_write_cells++;
+
+            // check that the next word is in the same cache line
+            assert( (m_nline[(vci_addr_t)(r_write_address.read())] == m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())])  
+                && "VCI_MEM_CACHE write error in vci_mem_cache : write burst over a line" );
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get=true;
+            size_t index 	        = r_write_word_index.read() + r_write_word_count.read();
+            r_write_be[index]       = m_cmd_write_be_fifo.read();
+            r_write_data[index]     = m_cmd_write_data_fifo.read();
+            r_write_word_count 	    = r_write_word_count.read() + 1;
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+              r_write_byte=true;
+            if ( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_LOCK:	// access directory to check hit/miss
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ) {
+            size_t  way = 0;
+            DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
+
+            // copy directory entry in local buffers in case of hit
+            if ( entry.valid )  {	
+              r_write_is_cnt    = entry.is_cnt;
+              r_write_lock	    = entry.lock;
+              r_write_tag       = entry.tag;
+              r_write_d_copies  = entry.d_copies;
+              r_write_i_copies  = entry.i_copies;
+              r_write_count     = entry.count;
+              r_write_way  	    = way;
+              if((entry.is_cnt && entry.count) ||
+                  entry.i_copies){
+                r_write_fsm      = WRITE_DIR_HIT_READ;
+              } else {
+                if(r_write_byte.read())
+                  r_write_fsm      = WRITE_DIR_HIT_READ;
+                else {
+                    bool owner     = (bool) (entry.d_copies & (0x1 << r_write_srcid.read()));
+                    bool no_update = (owner && (entry.count == 1)) || (entry.count==0);
+                    if( no_update ) r_write_fsm  = WRITE_DIR_HIT_RSP; 
+                    else            r_write_fsm  = WRITE_DIR_HIT;
+                }
+              }
+            } else {
+              r_write_fsm = WRITE_TRT_LOCK;
+              m_cpt_write_miss++;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_READ:	// read the cache and complete the buffer (data, when be!=0xF)
+        {
+          // update local buffer
+          size_t set	= m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	= r_write_way.read();
+          for(size_t i=0 ; i<m_words ; i++) {
+            data_t mask      = 0;
+            if  (r_write_be[i].read() & 0x1) mask = mask | 0x000000FF;
+            if  (r_write_be[i].read() & 0x2) mask = mask | 0x0000FF00;
+            if  (r_write_be[i].read() & 0x4) mask = mask | 0x00FF0000;
+            if  (r_write_be[i].read() & 0x8) mask = mask | 0xFF000000;
+            if(r_write_be[i].read()||r_write_is_cnt.read()||r_write_i_copies.read()) { // complete only if mask is not null (for energy consumption)
+              r_write_data[i]  = (r_write_data[i].read() & mask) | 
+                (m_cache_data[way][set][i] & ~mask);
+            }
+          } // end for
+
+          if((r_write_is_cnt.read() && r_write_count.read()) ||
+              r_write_i_copies.read()){
+              r_write_fsm    = WRITE_TRT_WRITE_LOCK;
+          } else {
+              bool owner     = (bool) (r_write_d_copies.read() & (0x1 << r_write_srcid.read()));
+              bool no_update = (owner && (r_write_count.read() == 1)) || (r_write_count.read()==0);
+              if( no_update )   r_write_fsm    = WRITE_DIR_HIT_RSP;
+              else              r_write_fsm    = WRITE_DIR_HIT;
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT:	// update the cache (data & dirty bit)
+        {
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.dirty	    = true;
+          entry.tag	        = r_write_tag.read();
+          entry.is_cnt      = r_write_is_cnt.read();
+          entry.lock	    = r_write_lock.read();
+          entry.d_copies    = r_write_d_copies.read();
+          entry.i_copies    = 0;
+          entry.count       = r_write_count.read();
+          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	    = r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          // write data in cache
+          for(size_t i=0 ; i<m_words ; i++) {
+            if  ( r_write_be[i].read() ) {
+              m_cache_data[way][set][i]  = r_write_data[i].read();
+            }
+          } // end for
+
+          // compute the actual number of copies & the modified bit vector
+          bool owner = (bool) (r_write_d_copies.read() & (0x1 << r_write_srcid.read()));
+          copy_t d_copies = r_write_d_copies.read() & ~(0x1 << r_write_srcid.read());
+          r_write_d_copies      = d_copies;
+          size_t count_signal   = r_write_count.read();
+          if(owner){
+            count_signal        = count_signal - 1;
+          }
+          r_write_count         = count_signal;
+
+          r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_RSP:	// update the cache (data & dirty bit) (no update)
+        {
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.dirty	    = true;
+          entry.tag	        = r_write_tag.read();
+          entry.is_cnt      = r_write_is_cnt.read();
+          entry.lock	    = r_write_lock.read();
+          entry.d_copies    = r_write_d_copies.read();
+          entry.i_copies    = 0;
+          entry.count       = r_write_count.read();
+          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	    = r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          // write data in cache
+          for(size_t i=0 ; i<m_words ; i++) {
+            if  ( r_write_be[i].read() ) {
+              m_cache_data[way][set][i]  = r_write_data[i].read();
+            }
+          } // end for
+
+          if ( !r_write_to_tgt_rsp_req.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_fsm 		        = WRITE_IDLE;
+          } else {
+            r_write_fsm = WRITE_RSP;
+          }
+          break;
+        }
+
+        /////////////////////
+      case WRITE_UPT_LOCK: 	// Try to register the request in Update Table
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool        wok        = false;
+            size_t      index      = 0;
+            size_t      srcid      = r_write_srcid.read();
+            size_t      trdid      = r_write_trdid.read();
+            size_t      pktid      = r_write_pktid.read();
+            addr_t      nline      = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t      nb_copies  = r_write_count.read();
+
+            wok =m_update_tab.set(true,	// it's an update transaction
+                false,                  // it's not a broadcast
+                true,                   // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_write_fsm = WRITE_UPDATE;
+            else       r_write_fsm = WRITE_WAIT_UPT;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT_UPT:	// release the lock protecting UPT
+        {
+          r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        //////////////////
+      case WRITE_UPDATE:	// send a multi-update request to INIT_CMD fsm
+        {
+
+          if ( !r_write_to_init_cmd_req ) {
+            r_write_to_init_cmd_req      = true;
+            r_write_to_init_cmd_brdcast  = false;
+            r_write_to_init_cmd_trdid    = r_write_upt_index.read();
+            r_write_to_init_cmd_nline    = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index    = r_write_word_index.read();
+            r_write_to_init_cmd_count    = r_write_word_count.read();
+            r_write_to_init_cmd_d_copies = r_write_d_copies.read();
+
+            for(size_t i=0; i<m_words ; i++){
+              if(r_write_be[i].read())  r_write_to_init_cmd_we[i]=true;
+              else                      r_write_to_init_cmd_we[i]=false;
+            }
+
+            size_t min = r_write_word_index.read();
+            size_t max = r_write_word_index.read() + r_write_word_count.read();
+            for (size_t i=min ; i<max ; i++) {
+              r_write_to_init_cmd_data[i] = r_write_data[i];
+            }
+            r_write_fsm = WRITE_IDLE; // Response will be sent after receiving
+            // all update responses
+          }
+          break;
+        }
+        ///////////////
+      case WRITE_RSP:		// send a request to TGT_RSP FSM to acknowledge the write
+        {
+          if ( !r_write_to_tgt_rsp_req.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_fsm 		        = WRITE_IDLE;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_LOCK:	// Miss : check Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t hit_index = 0;
+            size_t wok_index = 0;
+            bool hit_read  = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(r_write_address.read())],hit_index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(r_write_address.read())]);
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( hit_read ) {	// register the modified data in TRT 
+              r_write_trt_index = hit_index;
+              r_write_fsm       = WRITE_TRT_DATA;
+            } else if ( wok && !hit_write ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_TRT_SET;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT_TRT;
+            }
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT_TRT:	// release the lock protecting TRT
+        { 
+          r_write_fsm = WRITE_DIR_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_TRT_SET:	// register a new transaction in TRT (Write Buffer)
+        {  
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) 
+          {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) 
+            {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.set(r_write_trt_index.read(),
+                true,				// read request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                r_write_srcid.read(),
+                r_write_trdid.read(),
+                r_write_pktid.read(),
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                be_vector,
+                data_vector);
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_write_fsm = WRITE_XRAM_REQ;
+          }
+          break;
+        }  
+        ///////////////////
+      case WRITE_TRT_DATA:	// update an entry in TRT (Write Buffer)
+        { 
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.write_data_mask(r_write_trt_index.read(),
+                be_vector,
+                data_vector);
+            r_write_fsm = WRITE_RSP;
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_DATA transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_REQ:	// send a request to IXR_CMD FSM
+        {  
+
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req   = true;
+            r_write_to_ixr_cmd_write = false;
+            r_write_to_ixr_cmd_nline = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
+            r_write_fsm              = WRITE_RSP;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_WRITE_LOCK:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            size_t wok_index = 0;
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( wok ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_INVAL_LOCK;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT_TRT;
+            }
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool        wok       = false;
+            size_t      index     = 0;
+            size_t      srcid     = r_write_srcid.read();
+            size_t      trdid     = r_write_trdid.read();
+            size_t      pktid     = r_write_pktid.read();
+            addr_t	    nline     = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t      nb_copies = r_write_count.read();
+
+            wok =m_update_tab.set(false,	// it's an inval transaction
+                true,                       // it's a broadcast
+                true,                       // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_INVAL_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_write_fsm = WRITE_DIR_INVAL;
+            else       r_write_fsm = WRITE_WAIT_TRT;
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_INVAL:
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) &&
+              (r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) )
+          {
+            m_transaction_tab.set(r_write_trt_index.read(),
+                false,				// write request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                0,
+                0,
+                0,
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_DIR_INVAL transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            // invalidate directory entry
+            DirectoryEntry entry;
+            entry.valid	   = false;
+            entry.dirty	   = false;
+            entry.tag	   = 0;
+            entry.is_cnt   = false;
+            entry.lock	   = false;
+            entry.d_copies = 0;
+            entry.i_copies = 0;
+            entry.count    = 0;
+            size_t set	   = m_y[(vci_addr_t)(r_write_address.read())];
+            size_t way	   = r_write_way.read();
+            m_cache_directory.write(set, way, entry);
+
+            r_write_fsm = WRITE_INVAL;
+          } else {
+            assert(false && "LOCK ERROR in WRITE_FSM, STATE = WRITE_DIR_INVAL");
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_INVAL:
+        {
+          if ( !r_write_to_init_cmd_req ) {
+            r_write_to_init_cmd_req      = true;
+            r_write_to_init_cmd_brdcast  = true;
+            r_write_to_init_cmd_trdid    = r_write_upt_index.read();
+            r_write_to_init_cmd_nline    = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index    = 0;
+            r_write_to_init_cmd_count    = 0;
+            r_write_to_init_cmd_d_copies = 0;
+
+            for(size_t i=0; i<m_words ; i++){
+              r_write_to_init_cmd_we[i]=false;
+              r_write_to_init_cmd_data[i] = 0;
+            }
+            r_write_fsm = WRITE_XRAM_SEND;
+            // all update responses
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_SEND:
+        {
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req     = true;
+            r_write_to_ixr_cmd_write   = true;
+            r_write_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
+            for(size_t i=0; i<m_words; i++){
+              r_write_to_ixr_cmd_data[i] = r_write_data[i];
+            }
+            r_write_fsm                 = WRITE_IDLE;
+          }
+          break;
+        }
+    } // end switch r_write_fsm
+
+    ///////////////////////////////////////////////////////////////////////
+    //		IXR_CMD FSM
+    ///////////////////////////////////////////////////////////////////////
+    // The IXR_CMD fsm controls the command packets to the XRAM :
+    // - It sends a single cell VCI read to the XRAM in case of MISS request
+    // posted by the READ, WRITE or LLSC FSMs : the TRDID field contains 
+    // the Transaction Tab index.
+    // The VCI response is a multi-cell packet : the N cells contain
+    // the N data words.
+    // - It sends a multi-cell VCI write when the XRAM_RSP FSM request 
+    // to save a dirty line to the XRAM. 
+    // The VCI response is a single cell packet.
+    // This FSM handles requests from the READ, WRITE, LLSC & XRAM_RSP FSMs 
+    // with a round-robin priority.
+    ////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_cmd_fsm.read() ) {
+      //////////////////////// 
+      case IXR_CMD_READ_IDLE:
+        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_WRITE_IDLE:
+        if      ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_LLSC_IDLE:
+        if      ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_XRAM_IDLE:
+        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        break;
+        /////////////////////////
+      case IXR_CMD_READ_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;		
+          r_read_to_ixr_cmd_req = false;
+        }
+        break;
+        //////////////////////////
+      case IXR_CMD_WRITE_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          if( r_write_to_ixr_cmd_write.read()){
+            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+              r_ixr_cmd_cpt = 0;
+              r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
+              r_write_to_ixr_cmd_req = false;
+            } else {
+              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+            }
+          } else {
+            r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;		
+            r_write_to_ixr_cmd_req = false;
+          }
+        }
+        break;
+        /////////////////////////
+      case IXR_CMD_LLSC_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          if( r_llsc_to_ixr_cmd_write.read()){
+            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+              r_ixr_cmd_cpt = 0;
+              r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;
+              r_llsc_to_ixr_cmd_req = false;
+            } else {
+              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+            }
+          } else {
+            r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;		
+            r_llsc_to_ixr_cmd_req = false;
+          }
+        }
+        break;
+        ////////////////////////
+      case IXR_CMD_XRAM_DATA:
+        if ( p_vci_ixr.cmdack ) {
+          if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+            r_ixr_cmd_cpt = 0;
+            r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
+            r_xram_rsp_to_ixr_cmd_req = false;
+          } else {
+            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+          }
+        }
+        break;
+
+    } // end switch r_ixr_cmd_fsm
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                IXR_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The IXR_RSP FSM receives the response packets from the XRAM,
+    // for both write transaction, and read transaction.
+    //
+    // - A response to a write request is a single-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The FSM takes the lock protecting the TRT, and the corresponding
+    // entry is erased.
+    //	
+    // - A response to a read request is a multi-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The N cells contain the N words of the cache line in the RDATA field.
+    // The FSM takes the lock protecting the TRT to store the line in the TRT
+    // (taking into account the write requests already stored in the TRT).
+    // When the line is completely written, the corresponding rok signal is set.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_rsp_fsm.read() ) {
+
+      ///////////////////
+      case IXR_RSP_IDLE:	// test if it's a read or a write transaction
+        {
+          if ( p_vci_ixr.rspval ) {
+            r_ixr_rsp_cpt   = 0;
+            r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
+            if ( p_vci_ixr.reop )  r_ixr_rsp_fsm = IXR_RSP_ACK;
+            else                   r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
+          }
+          break;  
+        }
+        ////////////////////////
+      case IXR_RSP_ACK:        // Acknowledge the vci response
+        r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
+        break;
+        ////////////////////////
+      case IXR_RSP_TRT_ERASE: 	// erase the entry in the TRT
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP ) {
+            m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
+            r_ixr_rsp_fsm = IXR_RSP_IDLE;
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_ERASE transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ///////////////////////
+      case IXR_RSP_TRT_READ:		// write data in the TRT
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval ) {
+            bool   eop  	= p_vci_ixr.reop.read();
+            data_t data 	= p_vci_ixr.rdata.read();
+            size_t index        = r_ixr_rsp_trt_index.read();
+            assert( eop == (r_ixr_rsp_cpt.read() == (m_words-1)) 
+                && "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
+            m_transaction_tab.write_rsp(index, r_ixr_rsp_cpt.read(), data);
+            r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
+            if ( eop ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_READ transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+              r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
+              r_ixr_rsp_fsm = IXR_RSP_IDLE;
+            }
+          }
+          break;
+        }
+    } // end swich r_ixr_rsp_fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                XRAM_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
+    // The cache line has been written in the TRT buffer by the IXR_FSM.
+    //
+    // When a response is available, the corresponding TRT entry 
+    // is copied in a local buffer to be written in the cache. 
+    // Then, the FSM releases the lock protecting the TRT, and takes the lock 
+    // protecting the cache directory.
+    // It selects a cache slot and writes the line in the cache.
+    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
+    // FSM to return the cache line to the registered processor.
+    // If there is no empty slot, a victim line is evicted, and
+    // invalidate requests are sent to the L1 caches containing copies.
+    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD 
+    // FSM to save the victim line to the XRAM, and register the write transaction
+    // in the TRT (using the entry previously used by the read transaction).
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_xram_rsp_fsm.read() ) {
+
+      ///////////////////
+      case XRAM_RSP_IDLE:	// test if there is a response with a round robin priority
+        {
+          size_t ptr   = r_xram_rsp_trt_index.read();
+          size_t lines = TRANSACTION_TAB_LINES;
+          for(size_t i=0; i<lines; i++){
+            size_t index=(i+ptr+1)%lines;
+            if(r_ixr_rsp_to_xram_rsp_rok[index]){
+              r_xram_rsp_trt_index=index;
+              r_ixr_rsp_to_xram_rsp_rok[index]=false;
+              r_xram_rsp_fsm           = XRAM_RSP_DIR_LOCK;
+              break;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_IDLE state" << std::endl;
+#endif
+            }
+          }
+          break;  
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_LOCK: 	// Take the lock on the directory
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) {
+            r_xram_rsp_fsm           = XRAM_RSP_TRT_COPY;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_LOCK state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_TRT_COPY:		// Copy the TRT entry in the local buffer and eviction of a cache line
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) ) {
+            size_t index = r_xram_rsp_trt_index.read();
+            TransactionTabEntry    trt_entry(m_transaction_tab.read(index));	
+
+            r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
+
+            // selects & extracts a victim line from cache
+            size_t way = 0;
+            size_t set = m_y[(vci_addr_t)(trt_entry.nline * m_words * 4)];
+            DirectoryEntry victim(m_cache_directory.select(set, way));
+
+            for (size_t i=0 ; i<m_words ; i++) r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
+
+            bool inval = (victim.count && victim.valid) ;
+
+            r_xram_rsp_victim_d_copies = victim.d_copies;
+            r_xram_rsp_victim_i_copies = victim.i_copies;
+            r_xram_rsp_victim_count    = victim.count;
+            r_xram_rsp_victim_way      = way;
+            r_xram_rsp_victim_set      = set;
+            r_xram_rsp_victim_nline    = victim.tag*m_sets + set;
+            r_xram_rsp_victim_is_cnt   = victim.is_cnt;
+            r_xram_rsp_victim_inval    = inval ;
+            r_xram_rsp_victim_dirty    = victim.dirty;
+
+            r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_TRT_COPY state" << std::endl;
+	std::cout << "Victim way : " << std::hex << way << " set " << std::hex << set << std::endl;
+	victim.print();
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP ) {
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state" << std::endl;
+#endif
+            size_t index;
+            if(m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index)){
+              r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+
+            }
+	    else if(m_update_tab.is_full() && r_xram_rsp_victim_inval.read()){
+	      r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+	    }
+            else {
+              r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_DIR_UPDT state" << std::endl;
+#endif
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_WAIT:
+        {
+          r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
+          break;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_UPDT:		// updates the cache (both data & directory)
+        {
+          // signals generation
+          bool inst_read = (r_xram_rsp_trt_buf.trdid & 0x2) && r_xram_rsp_trt_buf.proc_read; // It is an instruction read
+          bool cached_read = (r_xram_rsp_trt_buf.trdid & 0x1) && r_xram_rsp_trt_buf.proc_read ;
+          // update data
+          size_t set   = r_xram_rsp_victim_set.read();
+          size_t way   = r_xram_rsp_victim_way.read();
+          for(size_t i=0; i<m_words ; i++){
+            m_cache_data[way][set][i] = r_xram_rsp_trt_buf.wdata[i];
+          }
+          // compute dirty 
+          bool dirty = false;
+          for(size_t i=0; i<m_words;i++){
+            dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
+          }
+
+          // update directory
+          DirectoryEntry entry;
+          entry.valid	  = true;
+          entry.is_cnt    = false;
+          entry.lock	  = false;
+          entry.dirty	  = dirty;
+          entry.tag	    = r_xram_rsp_trt_buf.nline / m_sets;
+          if(cached_read) {
+            if(inst_read) {
+              entry.i_copies = 0x1 << r_xram_rsp_trt_buf.srcid;
+              entry.d_copies = 0x0;
+              entry.count    = 1;
+            } else {
+              entry.i_copies = 0x0;
+              entry.d_copies = 0x1 << r_xram_rsp_trt_buf.srcid;
+              entry.count    = 1;
+            }
+          } else {
+            entry.d_copies = 0;
+            entry.i_copies = 0;
+            entry.count    = 0;
+          }
+          m_cache_directory.write(set, way, entry);
+#ifdef DDEBUG
+	   std::cout << "printing the entry : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_DIR_UPDT transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          if(r_xram_rsp_victim_inval.read()){
+            bool    brdcast = r_xram_rsp_victim_is_cnt.read();
+            size_t index;
+            size_t count_copies = r_xram_rsp_victim_count.read();
+
+            bool	 wok = m_update_tab.set(false,	// it's an inval transaction
+                brdcast,                          // set brdcast bit
+                false,  // it does not need a response
+                0,
+                0,
+                0,
+                r_xram_rsp_victim_nline.read(),
+                count_copies,
+                index);
+
+#ifdef IDEBUG
+            std::cout << "xram_rsp : record invalidation, time = " << std::dec << m_cpt_cycles << std::endl;
+            m_update_tab.print();
+#endif
+            r_xram_rsp_upt_index = index;
+            if(!wok) {
+              assert(false && "mem_cache error : xram_rsp_dir_upt, an update_tab entry was free but write unsuccessful");
+            }
+          }
+          // If the victim is not dirty, we erase the entry in the TRT
+          if      (!r_xram_rsp_victim_dirty.read()){
+	  m_transaction_tab.erase(r_xram_rsp_trt_index.read());
+
+	  }
+          // Next state
+          if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
+          else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+          else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+          else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          break;
+        }
+        ////////////////////////
+      case XRAM_RSP_TRT_DIRTY:		// set the TRT entry (write line to XRAM) if the victim is dirty
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP ) {
+            m_transaction_tab.set(r_xram_rsp_trt_index.read(),
+                false,				// write to XRAM
+                r_xram_rsp_victim_nline.read(), // line index
+                0,
+                0,
+                0,
+                false,
+                0,
+                0,
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0) );
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_TRT_DIRTY transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+          }
+          break;
+        }
+        //////////////////////
+      case XRAM_RSP_DIR_RSP:     // send a request to TGT_RSP FSM in case of read
+        {
+          if ( !r_xram_rsp_to_tgt_rsp_req ) {
+            r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
+            r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
+            r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
+            for (size_t i=0; i < m_words; i++) {
+              r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
+            } 
+            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_req    = true;
+
+            if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY; 
+            else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#ifdef DDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_RSP state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ////////////////////
+      case XRAM_RSP_INVAL:	// send invalidate request to INIT_CMD FSM
+        {
+          if( !r_xram_rsp_to_init_cmd_req ) {	      
+            r_xram_rsp_to_init_cmd_req      = true; 
+            r_xram_rsp_to_init_cmd_brdcast  = r_xram_rsp_victim_is_cnt.read();
+            r_xram_rsp_to_init_cmd_nline    = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_init_cmd_trdid    = r_xram_rsp_upt_index;
+            r_xram_rsp_to_init_cmd_d_copies = r_xram_rsp_victim_d_copies ;
+            r_xram_rsp_to_init_cmd_i_copies = r_xram_rsp_victim_i_copies ;
+            if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+            else		                    r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef DDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL state" << std::endl;
+#endif
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_WRITE_DIRTY:	// send a write request to IXR_CMD FSM
+        {
+          if ( !r_xram_rsp_to_ixr_cmd_req ) {
+            r_xram_rsp_to_ixr_cmd_req = true;
+            r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
+            for(size_t i=0; i<m_words ; i++) {
+              r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
+            }
+            m_cpt_write_dirty++;
+            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_WRITE_DIRTY state" << std::endl;
+#endif
+          }
+          break;
+        }
+    } // end swich r_xram_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		CLEANUP FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The CLEANUP FSM handles the cleanup request from L1 caches.
+    // It accesses the cache directory to update the list of copies.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+    switch ( r_cleanup_fsm.read() ) {
+
+      ///////////////////
+      case CLEANUP_IDLE:
+        {
+
+          if ( p_vci_tgt_cleanup.cmdval.read() ) {
+            assert( (p_vci_tgt_cleanup.srcid.read() < m_initiators) &&
+                "VCI_MEM_CACHE error in VCI_MEM_CACHE in the CLEANUP network : The received SRCID is larger than 31");
+            bool reached = false;
+            for ( size_t index = 0 ; index < ncseg && !reached ; index++ ){
+              if ( m_cseg[index]->contains((addr_t)(p_vci_tgt_cleanup.address.read())) ){
+                reached = true;
+              }
+            }
+            if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
+                (((addr_t)(p_vci_tgt_cleanup.address.read())) != BROADCAST_ADDR) &&
+                reached) {
+
+              m_cpt_cleanup++;
+
+              r_cleanup_nline      = (addr_t)(m_nline[(vci_addr_t)(p_vci_tgt_cleanup.address.read())]) ;
+              r_cleanup_srcid      = p_vci_tgt_cleanup.srcid.read();
+              r_cleanup_trdid      = p_vci_tgt_cleanup.trdid.read();
+              r_cleanup_pktid      = p_vci_tgt_cleanup.pktid.read();
+
+              r_cleanup_fsm        = CLEANUP_DIR_LOCK;
+            }
+          }
+          break;
+        }
+        //////////////////////
+      case CLEANUP_DIR_LOCK:
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) {
+
+            // Read the directory
+            size_t way = 0;
+	   addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
+           DirectoryEntry entry = m_cache_directory.read(cleanup_address , way);
+#ifdef DDEBUG
+	   std::cout << "In CLEANUP_DIR_LOCK printing the entry of address is : " << std::hex << cleanup_address << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+            r_cleanup_is_cnt    = entry.is_cnt;
+            r_cleanup_dirty	    = entry.dirty;
+            r_cleanup_tag	    = entry.tag;
+            r_cleanup_lock	    = entry.lock;
+            r_cleanup_way	    = way;
+            r_cleanup_d_copies  = entry.d_copies;
+            r_cleanup_i_copies  = entry.i_copies;
+            r_cleanup_count     = entry.count;
+
+            // In case of hit, the copy must be cleaned in the copies bit-vector
+            if( entry.valid )  { 
+              r_cleanup_fsm = CLEANUP_DIR_WRITE;
+            } else {
+              r_cleanup_fsm = CLEANUP_UPT_LOCK;
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case CLEANUP_DIR_WRITE:
+        {
+          size_t way      = r_cleanup_way.read();
+#define L2 soclib::common::uint32_log2
+          size_t set      = m_y[(vci_addr_t)(r_cleanup_nline.read() << (L2(m_words) +2))];
+#undef L2
+          bool cleanup_inst  = r_cleanup_trdid.read() & 0x1; 
+
+          // update the cache directory (for the copies)
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.is_cnt  = r_cleanup_is_cnt.read();
+          entry.dirty	= r_cleanup_dirty.read();
+          entry.tag	= r_cleanup_tag.read();
+          entry.lock	= r_cleanup_lock.read();
+          if(r_cleanup_is_cnt.read()) { // Directory is a counter
+            entry.count  = r_cleanup_count.read() -1;
+            entry.i_copies = 0;
+            entry.d_copies = 0;
+            // response to the cache 
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          else{                         // Directory is a vector
+            if(cleanup_inst){           // Cleanup from a ICACHE
+              if(r_cleanup_i_copies.read() & (0x1 << r_cleanup_srcid.read())){ // hit
+                entry.count  = r_cleanup_count.read() -1;
+                r_cleanup_fsm = CLEANUP_RSP;
+              } else { // miss
+                assert(false && "MemCache ERROR : Cleanup instruction hit but the line is not shared");
+              }
+              entry.i_copies  = r_cleanup_i_copies.read() & ~(0x1 << r_cleanup_srcid.read());
+              entry.d_copies  = r_cleanup_d_copies.read();
+            } else {                    // Cleanup from a DCACHE
+              if(r_cleanup_d_copies.read() & (0x1 << r_cleanup_srcid.read())){ // hit
+                entry.count  = r_cleanup_count.read() -1;
+                r_cleanup_fsm = CLEANUP_RSP; 
+              } else { // miss
+                assert(false && "MemCache ERROR : Cleanup data hit but the line is not shared");
+              }
+              entry.i_copies  = r_cleanup_i_copies.read();
+              entry.d_copies  = r_cleanup_d_copies.read() & ~(0x1 << r_cleanup_srcid.read());
+            }
+          }
+          m_cache_directory.write(set, way, entry);  
+
+          // response to the cache      
+//          r_cleanup_fsm = CLEANUP_RSP;
+
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_LOCK:
+        {
+          if( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
+          {
+            size_t index = 0;
+            bool hit_inval;
+            hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
+            if(!hit_inval) {
+#ifdef DEBUG_VCI_MEM_CACHE
+              std::cout << "MEM_CACHE WARNING: cleanup with no corresponding entry at address : " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::dec << std::endl;
+#endif
+              r_cleanup_fsm = CLEANUP_RSP;
+            } else {
+              r_cleanup_write_srcid = m_update_tab.srcid(index);
+              r_cleanup_write_trdid = m_update_tab.trdid(index);
+              r_cleanup_write_pktid = m_update_tab.pktid(index);
+              r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
+              r_cleanup_fsm = CLEANUP_UPT_WRITE;
+            }
+            r_cleanup_index.write(index) ; 
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_WRITE:
+        {
+          size_t count = 0;
+          m_update_tab.decrement(r_cleanup_index.read(), count); // &count
+          if(count == 0){
+            m_update_tab.clear(r_cleanup_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " CLEANUP_UPT_WRITE update table : " << std::endl;
+	m_update_tab.print();
+#endif
+
+            if(r_cleanup_need_rsp.read()){
+              r_cleanup_fsm = CLEANUP_WRITE_RSP ;
+            } else {
+              r_cleanup_fsm = CLEANUP_RSP;
+            }
+          } else {
+            r_cleanup_fsm = CLEANUP_RSP ;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_WRITE_RSP:
+        {
+          if( !r_cleanup_to_tgt_rsp_req.read()) {
+            r_cleanup_to_tgt_rsp_req     = true;
+            r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
+            r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
+            r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_RSP:
+        {
+          if(p_vci_tgt_cleanup.rspack)
+            r_cleanup_fsm = CLEANUP_IDLE;
+          break;
+        }
+    } // end switch cleanup fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		LLSC FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The LLSC FSM handles the LL & SC atomic access.
+    //
+    // For a LL :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the LL request is registered in the Atomic Table and the
+    // response is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state.
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the LL request is not consumed in the FIFO.
+    //
+    // For a SC :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the Atomic Table is checked and the proper response
+    // (true or false is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state. 
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the SC request is not consumed in the FIFO.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_llsc_fsm.read() ) {
+
+      ///////////////
+      case LLSC_IDLE:		// test LL / SC
+        {
+          if( m_cmd_llsc_addr_fifo.rok() ) {
+            if(m_cmd_llsc_sc_fifo.read()){
+              m_cpt_sc++;
+              r_llsc_fsm = SC_DIR_LOCK;
+            }
+            else{
+              m_cpt_ll++;
+              r_llsc_fsm = LL_DIR_LOCK;
+            }
+          }	
+          break;
+        }
+        /////////////////
+      case LL_DIR_LOCK:		// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+            size_t way = 0;
+            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+            r_llsc_is_cnt     = entry.is_cnt;
+            r_llsc_dirty      = entry.dirty;
+            r_llsc_tag        = entry.tag;
+            r_llsc_way        = way;
+            r_llsc_d_copies   = entry.d_copies;
+            r_llsc_i_copies   = entry.i_copies ;
+            r_llsc_count      = entry.count ;
+
+            // set Atomic Table
+            m_atomic_tab.set(m_cmd_llsc_srcid_fifo.read(), m_cmd_llsc_addr_fifo.read());
+
+            if ( entry.valid )  r_llsc_fsm = LL_DIR_HIT;
+            else                r_llsc_fsm = LLSC_TRT_LOCK;
+          }
+          break;
+        }
+        ////////////////
+      case LL_DIR_HIT:		// read hit : update the memory cache
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+
+          // update directory (lock bit & copies)
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.is_cnt      = r_llsc_is_cnt.read();
+          entry.dirty	    = r_llsc_dirty.read();
+          entry.lock	    = true;
+          entry.tag	        = r_llsc_tag.read();
+          entry.d_copies    = r_llsc_d_copies.read();
+          entry.i_copies    = r_llsc_i_copies.read();
+          entry.count       = r_llsc_count.read();
+          m_cache_directory.write(set, way, entry);
+
+          // read data in cache
+          r_llsc_data	= m_cache_data[way][set][word];
+
+          r_llsc_fsm 	= LL_RSP;
+          break;
+        }
+        ////////////
+      case LL_RSP:		// request the TGT_RSP FSM to return data
+        {
+          if ( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_data	= r_llsc_data.read();
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_fsm = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_DIR_LOCK:
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+            size_t way = 0;
+            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+            bool ok = m_atomic_tab.isatomic(m_cmd_llsc_srcid_fifo.read(),m_cmd_llsc_addr_fifo.read());
+            if( ok ) {
+              r_llsc_is_cnt   = entry.is_cnt;
+              r_llsc_dirty    = entry.dirty;
+              r_llsc_tag      = entry.tag;
+              r_llsc_way      = way;
+              r_llsc_d_copies = entry.d_copies;
+              r_llsc_i_copies = entry.i_copies;
+              r_llsc_count    = entry.count;
+              /* to avoid livelock, force the atomic access to fail (pseudo-)randomly */
+              bool fail = (r_llsc_lfsr % (64) == 0);
+              r_llsc_lfsr = (r_llsc_lfsr >> 1) ^ ((-(r_llsc_lfsr & 1)) & 0xd0000001);
+#ifdef RANDOMIZE_SC
+              if(fail){
+#else
+              if(0){
+#endif
+                r_llsc_fsm = SC_RSP_FALSE;
+              } else {
+                  if ( entry.valid ){
+                      if((entry.is_cnt && entry.count) || entry.i_copies) {
+                          r_llsc_fsm = SC_TRT_LOCK;
+                      } else {
+                          r_llsc_fsm = SC_DIR_HIT;
+                      }
+                  }
+                  else r_llsc_fsm = LLSC_TRT_LOCK;
+              }
+            } else {
+              r_llsc_fsm = SC_RSP_FALSE;
+            }
+          }
+          break;
+        }
+        ////////////////
+      case SC_DIR_HIT:
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+
+          // update directory (lock & dirty bits
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.is_cnt      = r_llsc_is_cnt.read();
+          entry.dirty	    = true;
+          entry.lock	    = true;
+          entry.tag	        = r_llsc_tag.read();
+          entry.d_copies    = r_llsc_d_copies.read();
+          entry.i_copies    = r_llsc_i_copies.read();
+          entry.count       = r_llsc_count.read();
+          m_cache_directory.write(set, way, entry);
+
+
+          // write data in cache
+          m_cache_data[way][set][word] = m_cmd_llsc_wdata_fifo.read();
+
+          // reset Atomic Table
+          m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+          
+          if(r_llsc_count.read()) {  // Shared line
+            r_llsc_fsm = SC_UPT_LOCK;
+          } else {
+            r_llsc_fsm = SC_RSP_TRUE;
+          }
+          break;
+        }
+        /////////////////////
+      case SC_UPT_LOCK: 	// Try to register the request in Update Table
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
+            bool        wok        = false;
+            size_t      index      = 0;
+            size_t      srcid      = m_cmd_llsc_srcid_fifo.read();
+            size_t      trdid      = m_cmd_llsc_trdid_fifo.read();
+            size_t      pktid      = m_cmd_llsc_pktid_fifo.read();
+            addr_t	    nline      = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t      nb_copies  = r_llsc_count.read();
+
+            wok =m_update_tab.set(true,	// it's an update transaction
+                false,                  // it's not a broadcast
+                true,                   // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " SC_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_llsc_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_llsc_fsm = SC_UPDATE;
+            else       r_llsc_fsm = SC_WAIT_UPT;
+          }
+          break;
+        }
+        ////////////////////
+      case SC_WAIT_UPT: 	// release the lock protecting UPT
+        {
+          r_llsc_fsm = SC_UPT_LOCK;
+          break;
+        }
+        //////////////////
+      case SC_UPDATE:   	// send a multi-update request to INIT_CMD fsm
+        {
+
+          if ( !r_llsc_to_init_cmd_req ) {
+            r_llsc_to_init_cmd_req      = true;
+            r_llsc_to_init_cmd_brdcast  = false;
+            r_llsc_to_init_cmd_trdid    = r_llsc_upt_index.read();
+            r_llsc_to_init_cmd_nline    = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_index    = m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_wdata    = m_cmd_llsc_wdata_fifo.read();
+            r_llsc_to_init_cmd_d_copies = r_llsc_d_copies.read();
+            
+            cmd_llsc_fifo_get         = true;
+
+            r_llsc_fsm = LLSC_IDLE; // Response will be sent after receiving
+            // all update responses
+          }
+          break;
+        }
+
+        //////////////////
+      case SC_TRT_LOCK:
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            if( !r_llsc_to_ixr_cmd_req ) { // we can transfer the data to the buffer
+              size_t way	= r_llsc_way.read();
+              size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+              for(size_t i = 0; i<m_words; i++){
+                if(i==m_x[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]) {
+                  r_llsc_to_ixr_cmd_data[i] = m_cmd_llsc_wdata_fifo.read();
+                } else {
+                  r_llsc_to_ixr_cmd_data[i] = m_cache_data[way][set][i];
+                }
+              }
+              size_t wok_index = 0;
+              bool wok = !m_transaction_tab.full(wok_index);
+              if ( wok ) { // set a new entry in TRT
+                r_llsc_trt_index = wok_index;
+                r_llsc_fsm       = SC_INVAL_LOCK; 
+              } else {
+                r_llsc_fsm       = LLSC_IDLE;
+              }
+            } else {
+              r_llsc_fsm = LLSC_IDLE;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case SC_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
+            bool        wok       = false;
+            size_t      index     = 0;
+            size_t      srcid     = m_cmd_llsc_srcid_fifo.read();
+            size_t      trdid     = m_cmd_llsc_trdid_fifo.read();
+            size_t      pktid     = m_cmd_llsc_pktid_fifo.read();
+            addr_t	    nline     = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t      nb_copies = r_llsc_count.read();
+
+            wok =m_update_tab.set(false,	// it's an inval transaction
+                true,                       // it's a broadcast
+                true,                       // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " LLSC_INVAL_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_llsc_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_llsc_fsm = SC_DIR_INVAL;
+            else       r_llsc_fsm = LLSC_IDLE;
+          }
+          break;
+        }
+        //////////////////
+      case SC_DIR_INVAL:
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) &&
+              (r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) )
+          {
+            m_transaction_tab.set(r_llsc_trt_index.read(),
+                false,				// write request to XRAM
+                m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())],
+                0,
+                0,
+                0,
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " SC_DIR_INVAL transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+            // reset Atomic Table
+            m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+
+            // invalidate directory entry
+            DirectoryEntry entry;
+            entry.valid	   = false;
+            entry.dirty	   = false;
+            entry.tag	   = 0;
+            entry.is_cnt   = false;
+            entry.lock	   = false;
+            entry.d_copies = 0;
+            entry.i_copies = 0;
+            entry.count    = 0;
+            size_t set	   = m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t way	   = r_llsc_way.read();
+            m_cache_directory.write(set, way, entry);
+
+            r_llsc_fsm = SC_INVAL;
+          } else {
+            assert(false && "LOCK ERROR in LLSC_FSM, STATE = LLSC_DIR_INVAL");
+          }
+
+          break;
+
+        }
+        //////////////////
+      case SC_INVAL:
+        {
+          if ( !r_llsc_to_init_cmd_req ) {
+            r_llsc_to_init_cmd_req      = true;
+            r_llsc_to_init_cmd_brdcast  = true;
+            r_llsc_to_init_cmd_trdid    = r_llsc_upt_index.read();
+            r_llsc_to_init_cmd_nline    = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_index    = 0;
+            r_llsc_to_init_cmd_d_copies = 0;
+            r_llsc_to_init_cmd_wdata    = 0;
+
+            r_llsc_fsm = SC_XRAM_SEND;
+            // all update responses
+          }
+
+          break;
+        }
+        //////////////////
+      case SC_XRAM_SEND:
+        {
+          if ( !r_llsc_to_ixr_cmd_req ) {
+            r_llsc_to_ixr_cmd_req     = true;
+            r_llsc_to_ixr_cmd_write   = true;
+            r_llsc_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_ixr_cmd_trdid   = r_llsc_trt_index.read();
+            r_llsc_fsm                = LLSC_IDLE;
+            cmd_llsc_fifo_get         = true;
+          } else {
+            assert( false && "MEM_CACHE, LLSC FSM : SC_XRAM_SEND state : the request should not have been previously set");
+          }
+          break;
+
+        }
+        //////////////////
+      case SC_RSP_FALSE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 1;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_RSP_TRUE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get	    = true;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 0;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_TRT_LOCK:         // read or write miss : check the Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            size_t   index = 0;
+            bool hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]);
+            bool wok = !m_transaction_tab.full(index);
+
+            if ( hit_read || !wok || hit_write ) {  // missing line already requested or no space in TRT
+              r_llsc_fsm = LLSC_IDLE;
+            } else {
+              r_llsc_trt_index = index;
+              r_llsc_fsm       = LLSC_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case LLSC_TRT_SET:	// register the XRAM transaction in Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+            bool proc_read = !m_cmd_llsc_sc_fifo.read();
+            if(proc_read){
+              m_transaction_tab.set(r_llsc_trt_index.read(),
+                  true,
+                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
+                  m_cmd_llsc_srcid_fifo.read(),
+                  m_cmd_llsc_trdid_fifo.read(),
+                  m_cmd_llsc_pktid_fifo.read(),
+                  true,
+                  1,
+                  word,
+                  std::vector<be_t>(m_words,0),
+                  std::vector<data_t>(m_words,0));
+            }else{
+              std::vector<be_t> be_vector;
+              std::vector<data_t> data_vector;
+              be_vector.clear();
+              data_vector.clear();
+              // reset Atomic Table
+              m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+              for ( size_t i=0; i<m_words; i++ ) 
+              {   
+                if(i == word){
+                  be_vector.push_back(0xF);
+                  data_vector.push_back(m_cmd_llsc_wdata_fifo.read());
+                } else {
+                  be_vector.push_back(0);
+                  data_vector.push_back(0);
+                }
+              }
+ 
+              m_transaction_tab.set(r_llsc_trt_index.read(),
+                  true,
+                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
+                  m_cmd_llsc_srcid_fifo.read(),
+                  m_cmd_llsc_trdid_fifo.read(),
+                  m_cmd_llsc_pktid_fifo.read(),
+                  false,
+                  0,
+                  0,
+                  be_vector,
+                  data_vector);
+            }
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " LLSC_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_llsc_fsm = LLSC_XRAM_REQ;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_XRAM_REQ:	// request the IXR_CMD FSM to fetch the missing line
+        {
+          if ( !r_llsc_to_ixr_cmd_req ) {
+            r_llsc_to_ixr_cmd_req        = true;
+            r_llsc_to_ixr_cmd_write      = false;
+            r_llsc_to_ixr_cmd_trdid      = r_llsc_trt_index.read();
+            r_llsc_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()];
+            if( m_cmd_llsc_sc_fifo.read() ) {
+              r_llsc_fsm                 = SC_RSP_TRUE;
+            } else {
+              cmd_llsc_fifo_get          = true;
+              r_llsc_fsm                 = LLSC_IDLE;
+            }
+          }
+          break;
+        }
+    } // end switch r_llsc_fsm
+
+
+    //////////////////////////////////////////////////////////////////////////////
+    //		INIT_CMD FSM
+    //////////////////////////////////////////////////////////////////////////////
+    // The INIT_CMD fsm controls the VCI CMD initiator port, used to update
+    // or invalidate cache lines in L1 caches.
+    // It implements a round-robin priority between the two following requests:
+    // - r_write_to_init_cmd_req : update request from WRITE FSM 
+    // - r_xram_rsp_to_init_cmd_req : invalidate request from XRAM_RSP FSM 
+    // The inval request is a single cell VCI write command containing the 
+    // index of the line to be invalidated.
+    // The update request is a multi-cells VCI write command : The first cell 
+    // contains the index of the cache line to be updated. The second cell contains 
+    // the index of the first modified word in the line. The following cells
+    // contain the data.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      //////////////////////// 
+      case INIT_CMD_UPDT_IDLE:	// Invalidate requests have highest priority
+        {
+
+          if ( r_xram_rsp_to_init_cmd_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          } else if ( r_write_to_init_cmd_req.read() ) {
+            if(r_write_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+              m_cpt_update++;
+            }
+          } else if (r_llsc_to_init_cmd_req.read() ) {
+            if(r_llsc_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_SC_UPDT_SEL;
+              m_cpt_update++;
+            }
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_INVAL_IDLE:	// Update requests have highest priority
+        {
+          if ( r_write_to_init_cmd_req.read() ) {
+            if(r_write_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+              m_cpt_update++;
+            }
+          } else if (r_llsc_to_init_cmd_req.read() ) {
+            if(r_llsc_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_SC_UPDT_SEL;
+              m_cpt_update++;
+            }
+          } else if ( r_xram_rsp_to_init_cmd_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_IDLE:	// Update requests for SCs have highest priority
+        {
+          if (r_llsc_to_init_cmd_req.read() ) {
+            if(r_llsc_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_SC_UPDT_SEL;
+              m_cpt_update++;
+            }
+          } else if ( r_xram_rsp_to_init_cmd_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+            m_cpt_inval++;
+          } else if ( r_write_to_init_cmd_req.read() ) {
+            if(r_write_to_init_cmd_brdcast.read()){
+              r_init_cmd_fsm = INIT_CMD_BRDCAST;
+              m_cpt_inval++;
+              m_cpt_inval_brdcast++;
+            } else {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+              m_cpt_update++;
+            }
+          }
+          break;
+        }
+
+        ////////////////////////
+      case INIT_CMD_INVAL_SEL:	// selects L1 caches
+        {
+          if(r_xram_rsp_to_init_cmd_brdcast.read()){
+            m_cpt_inval_brdcast++;
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            break;
+          }
+          if ((r_xram_rsp_to_init_cmd_d_copies.read() == 0) &&
+              (r_xram_rsp_to_init_cmd_i_copies.read() == 0)) {	// no more copies
+            r_xram_rsp_to_init_cmd_req = false;
+            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+            break;
+          }
+          m_cpt_inval_mult++;
+          copy_t copies;
+          bool inst = false;
+          if(r_xram_rsp_to_init_cmd_i_copies.read()){
+            copies = r_xram_rsp_to_init_cmd_i_copies.read();
+            inst = true;
+          } else {
+            copies = r_xram_rsp_to_init_cmd_d_copies.read();
+          }
+          copy_t mask   = 0x1;
+          for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+            if ( copies & mask ) {
+              r_init_cmd_target = i;
+              break;
+            }
+            mask = mask << 1;
+          } // end for 
+          r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+          r_init_cmd_inst = inst;
+          if(inst){
+            r_xram_rsp_to_init_cmd_i_copies = copies & ~mask;
+          } else {
+            r_xram_rsp_to_init_cmd_d_copies = copies & ~mask;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_INVAL_NLINE:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ) {
+            if ( r_xram_rsp_to_init_cmd_brdcast.read() ) {
+              r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+              r_xram_rsp_to_init_cmd_req = false;
+            }
+            else r_init_cmd_fsm = INIT_CMD_INVAL_SEL;
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_CMD_UPDT_SEL:	// selects the next L1 cache
+        {
+          if (r_write_to_init_cmd_d_copies.read() == 0) {	// no more copies
+            r_write_to_init_cmd_req = false;
+            r_init_cmd_fsm    = INIT_CMD_UPDT_IDLE;
+          } else {						// select the first target
+            copy_t copies;
+            copies = r_write_to_init_cmd_d_copies.read();
+            copy_t mask   = 0x1;
+            for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+              if ( copies & mask ) {
+                r_init_cmd_target = i;
+                break;
+              }
+              mask = mask << 1;
+            } // end for 
+            r_init_cmd_fsm    = INIT_CMD_UPDT_NLINE;
+            r_write_to_init_cmd_d_copies = copies & ~mask;
+            r_init_cmd_cpt    = 0;
+            m_cpt_update_mult++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_BRDCAST:
+        {
+          if( p_vci_ini.cmdack ) {
+            r_write_to_init_cmd_req = false;
+            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_NLINE:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ){
+            r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_INDEX:	// send the first word index
+        {
+
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) ) {
+              r_init_cmd_fsm = INIT_CMD_UPDT_SEL;
+            } else {
+              r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_CMD_SC_UPDT_SEL:	// selects the next L1 cache
+        {
+          if (r_llsc_to_init_cmd_d_copies.read() == 0) {	// no more copies
+            r_llsc_to_init_cmd_req = false;
+            r_init_cmd_fsm    = INIT_CMD_SC_UPDT_IDLE;
+          } else {						// select the first target
+            copy_t copies;
+            copies = r_llsc_to_init_cmd_d_copies.read();
+            copy_t mask   = 0x1;
+            for ( size_t i=0 ; i<8*sizeof(copy_t) ; i++ ) {
+              if ( copies & mask ) {
+                r_init_cmd_target = i;
+                break;
+              }
+              mask = mask << 1;
+            } // end for 
+            r_init_cmd_fsm    = INIT_CMD_SC_UPDT_NLINE;
+            r_llsc_to_init_cmd_d_copies = copies & ~mask;
+            r_init_cmd_cpt    = 0;
+            m_cpt_update_mult++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_BRDCAST:
+        {
+          if( p_vci_ini.cmdack ) {
+            r_llsc_to_init_cmd_req = false;
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_NLINE:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ){
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_INDEX;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_INDEX:	// send the first word index
+        {
+
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_SC_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_SEL;
+          }
+          break;
+        }
+
+    } // end switch r_init_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_RSP FSM
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_RSP fsm sends the responses on the VCI target port
+    // with a round robin priority between six requests :
+    // - r_read_to_tgt_rsp_req
+    // - r_write_to_tgt_rsp_req
+    // - r_llsc_to_tgt_rsp_req
+    // - r_cleanup_to_tgt_rsp_req
+    // - r_init_rsp_to_tgt_rsp_req
+    // - r_xram_rsp_to_tgt_rsp_req
+    // The  ordering is :  read > write > llsc > cleanup > xram > init
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      ///////////////////////
+      case TGT_RSP_READ_IDLE:		// write requests have the highest priority
+        {
+          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          break;
+        }
+        ////////////////////////
+      case TGT_RSP_WRITE_IDLE:		// llsc requests have the highest priority
+        {
+          if      ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_LLSC_IDLE:		// cleanup requests have the highest priority
+        {
+          if ( r_xram_rsp_to_tgt_rsp_req )  {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          break;
+        }
+      case TGT_RSP_XRAM_IDLE:		// init requests have the highest priority
+        {
+
+          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req )  {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_INIT_IDLE:		// cleanup requests have the highest priority
+        {
+          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_CLEANUP_IDLE:		// read requests have the highest priority
+        {
+          if      ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ:		// send the response
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) ) {
+              r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
+              r_read_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_WRITE:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
+            r_write_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_CLEANUP:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
+            r_cleanup_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        //////////////////
+      case TGT_RSP_LLSC:		// send one atomic word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_LLSC_IDLE;
+            r_llsc_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+
+        ///////////////////////
+      case TGT_RSP_XRAM:		// send the response
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1)) {
+              r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
+              r_xram_rsp_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_INIT:		// send the pending write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
+            r_init_rsp_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+    } // end switch tgt_rsp_fsm
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		NEW ALLOC_UPT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
+    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP 
+    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
+    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
+    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
+    // - The CLEANUP  FSM decrement an entry in UPT.
+    // The resource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_upt_fsm.read() ) {
+
+      ////////////////////////
+      case ALLOC_UPT_INIT_RSP:
+        if ( (r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK) && 
+             (r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR) ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_UPT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_UPT_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+        }
+        break;
+
+        ////////////////////////
+      case ALLOC_UPT_XRAM_RSP:
+        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK) 
+        { 
+          if       (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)       r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+        }
+        break;
+
+        //////////////////////////
+      case ALLOC_UPT_CLEANUP:
+        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
+        {
+          if      ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+        }
+        break;
+        
+        //////////////////////////
+      case ALLOC_UPT_LLSC:
+        if( (r_llsc_fsm.read() != SC_UPT_LOCK) && 
+            (r_llsc_fsm.read() != SC_INVAL_LOCK))
+        {
+          if      (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+        }
+        break;
+
+    } // end switch r_alloc_upt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_DIR FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_DIR FSM allocates the access to the directory and
+    // the data cache with a round robin priority between 5 user FSMs :
+    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
+    // The ressource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_dir_fsm.read() ) {
+
+      ////////////////////
+      case ALLOC_DIR_READ:
+        if ( ( (r_read_fsm.read() != READ_DIR_LOCK) &&
+              (r_read_fsm.read() != READ_TRT_LOCK)     )
+            ||
+            ( (r_read_fsm.read()      == READ_TRT_LOCK)  &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)    )  ) 
+        {
+          if        (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_DIR_WRITE:
+        if ( ( (r_write_fsm.read() != WRITE_DIR_LOCK)     &&
+              (r_write_fsm.read() != WRITE_TRT_LOCK)     &&
+              (r_write_fsm.read() != WRITE_DIR_HIT_READ) &&
+              (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+              (r_write_fsm.read() != WRITE_INVAL_LOCK) )
+            ||
+            ( (r_write_fsm.read()     == WRITE_TRT_LOCK) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
+        {
+          if        ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+        }
+        break;
+
+        ////////////////////
+      case ALLOC_DIR_LLSC:
+        if ( ( (r_llsc_fsm.read() != LL_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != LL_DIR_HIT )    &&
+              (r_llsc_fsm.read() != SC_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != SC_DIR_HIT )    &&
+              (r_llsc_fsm.read() != LLSC_TRT_LOCK ) &&
+              (r_llsc_fsm.read() != SC_TRT_LOCK)    &&
+              (r_llsc_fsm.read() != SC_INVAL_LOCK))
+            || 
+            ( (r_llsc_fsm.read()      == LLSC_TRT_LOCK ) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC)    ) )
+        {
+          if      (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)  r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+        }
+        break;
+
+        ///////////////////////
+      case ALLOC_DIR_CLEANUP:
+        if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
+            (r_cleanup_fsm.read() != CLEANUP_DIR_WRITE) )
+        {
+          if        (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if   (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_DIR_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)   && 
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
+        {
+          if      (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if ( (r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))         r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+        }
+        break;
+
+    } // end switch alloc_dir_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_TRT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
+    // with a round robin priority between 4 user FSMs :
+    // The cyclic priority is READ > WRITE > LLSC > XRAM_RSP
+    // The ressource is always allocated.
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    switch (r_alloc_trt_fsm) {
+
+      ////////////////////
+      case ALLOC_TRT_READ:
+        if ( r_read_fsm.read() != READ_TRT_LOCK ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ) )    r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+        }
+        break;
+        /////////////////////
+      case ALLOC_TRT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_TRT_LOCK) &&
+             (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+        }
+        break;
+        ////////////////////
+      case ALLOC_TRT_LLSC:
+        if ( (r_llsc_fsm.read() != LLSC_TRT_LOCK) &&
+             (r_llsc_fsm.read() != SC_TRT_LOCK) &&
+             (r_llsc_fsm.read() != SC_INVAL_LOCK))
+        { 
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)     ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT)   &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)) {
+          if      ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)    ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_IXR_RSP:
+        if ( (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
+            (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ) ) {
+          if      (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+        }
+        break;
+
+    } // end switch alloc_trt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to READ FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_read_fifo_put ) {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
+        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+      } else {
+        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
+        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+      }
+    } else {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.simple_get();
+        m_cmd_read_length_fifo.simple_get();
+        m_cmd_read_srcid_fifo.simple_get();
+        m_cmd_read_trdid_fifo.simple_get();
+        m_cmd_read_pktid_fifo.simple_get();
+      }
+    }
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to WRITE FIFO
+    /////////////////////////////////////////////////////////////////////
+
+    if ( cmd_write_fifo_put ) {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
+      } else {
+        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
+      }
+    } else {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.simple_get();
+        m_cmd_write_eop_fifo.simple_get();
+        m_cmd_write_srcid_fifo.simple_get();
+        m_cmd_write_trdid_fifo.simple_get();
+        m_cmd_write_pktid_fifo.simple_get();
+        m_cmd_write_data_fifo.simple_get();
+        m_cmd_write_be_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to LLSC FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_llsc_fifo_put ) {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_sc_fifo.put_and_get(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
+      } else {
+        m_cmd_llsc_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_sc_fifo.simple_put(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
+      }
+    } else {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.simple_get();
+        m_cmd_llsc_sc_fifo.simple_get();
+        m_cmd_llsc_srcid_fifo.simple_get();
+        m_cmd_llsc_trdid_fifo.simple_get();
+        m_cmd_llsc_pktid_fifo.simple_get();
+        m_cmd_llsc_wdata_fifo.simple_get();
+      }
+    }
+
+  //////////////////////////////////////////////////////////////
+    m_cpt_cycles++;
+
+  } // end transition()
+
+  /////////////////////////////
+  tmpl(void)::genMoore()
+    /////////////////////////////
+  {
+    ////////////////////////////////////////////////////////////
+    // Command signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////////////
+
+
+    p_vci_ixr.be      = 0xF;
+    p_vci_ixr.pktid   = 0;
+    p_vci_ixr.srcid   = m_srcid_ixr;
+    p_vci_ixr.cons    = false;
+    p_vci_ixr.wrap    = false;
+    p_vci_ixr.contig  = true;
+    p_vci_ixr.clen    = 0;
+    p_vci_ixr.cfixed  = false;
+
+    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_LLSC_NLINE ) {
+      if(r_llsc_to_ixr_cmd_write.read()){
+        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)((r_llsc_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = r_llsc_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+      } else {
+        p_vci_ixr.cmd     = vci_param::CMD_READ;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)(r_llsc_to_ixr_cmd_nline.read()*m_words*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = 0x00000000;
+        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = true;
+      }
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
+      if(r_write_to_ixr_cmd_write.read()){
+        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+      } else {
+        p_vci_ixr.cmd     = vci_param::CMD_READ;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = 0x00000000;
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = true;
+      }
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
+      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+    } else {
+      p_vci_ixr.cmdval  = false;
+      p_vci_ixr.address = 0;
+      p_vci_ixr.plen    = 0;
+      p_vci_ixr.wdata   = 0;
+      p_vci_ixr.trdid   = 0;
+      p_vci_ixr.eop	= false;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////
+
+    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
+          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) || 
+        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
+    else                                        p_vci_ixr.rspack = false;
+
+    ////////////////////////////////////////////////////
+    // Command signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+
+    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
+      case TGT_CMD_IDLE:
+        p_vci_tgt.cmdack  = false;
+        break;
+      case TGT_CMD_READ:
+        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
+        break;
+      case TGT_CMD_READ_EOP:
+        p_vci_tgt.cmdack  = true;
+        break;
+      case TGT_CMD_WRITE:
+        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
+        break;
+      case TGT_CMD_ATOMIC:
+        p_vci_tgt.cmdack  = m_cmd_llsc_addr_fifo.wok();
+        break;
+      default:
+        p_vci_tgt.cmdack = false;
+        break;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      case TGT_RSP_READ_IDLE:
+      case TGT_RSP_WRITE_IDLE:
+      case TGT_RSP_LLSC_IDLE:
+      case TGT_RSP_XRAM_IDLE:
+      case TGT_RSP_INIT_IDLE:
+      case TGT_RSP_CLEANUP_IDLE:
+        p_vci_tgt.rspval  = false;
+        p_vci_tgt.rsrcid  = 0;
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rpktid  = 0;
+        p_vci_tgt.rtrdid  = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = false;	
+        break;
+      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();
+        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
+        break;
+      case TGT_RSP_WRITE:
+        p_vci_tgt.rspval   = true;
+        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   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_CLEANUP:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_LLSC:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = r_llsc_to_tgt_rsp_data.read();
+        p_vci_tgt.rsrcid   = r_llsc_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_llsc_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_llsc_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      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();
+        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1));
+        break;
+      case TGT_RSP_INIT:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        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;
+        p_vci_tgt.reop     = true;	
+        break;
+    } // end switch r_tgt_rsp_fsm
+
+    ///////////////////////////////////////////////////
+    // Command signals on the p_vci_ini port
+    ///////////////////////////////////////////////////
+
+    p_vci_ini.cmd     = vci_param::CMD_WRITE;
+    p_vci_ini.srcid   = m_srcid_ini;
+    p_vci_ini.pktid   = 0;
+    p_vci_ini.cons    = true;
+    p_vci_ini.wrap    = false;
+    p_vci_ini.contig  = false;
+    p_vci_ini.clen    = 0;
+    p_vci_ini.cfixed  = false;
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      case INIT_CMD_UPDT_IDLE:
+      case INIT_CMD_INVAL_IDLE:
+      case INIT_CMD_SC_UPDT_IDLE:
+      case INIT_CMD_UPDT_SEL:
+      case INIT_CMD_INVAL_SEL:
+      case INIT_CMD_SC_UPDT_SEL:
+        p_vci_ini.cmdval  = false;
+        p_vci_ini.address = 0;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0;
+        p_vci_ini.plen    = 0;
+        p_vci_ini.trdid   = 0;
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_INVAL_NLINE:
+        p_vci_ini.cmdval  = true;
+        if(r_xram_rsp_to_init_cmd_brdcast.read())
+          p_vci_ini.address = BROADCAST_ADDR;
+        else {
+          if(r_init_cmd_inst.read()) {
+            p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()]+8);
+          } else {
+            p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()]);
+          }
+        }
+        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4;
+        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+      case INIT_CMD_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4 ;
+        p_vci_ini.eop     = true;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_NLINE:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.eop     = false;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
+          r_write_to_init_cmd_index.read()].read();
+        if(r_write_to_init_cmd_we[r_init_cmd_cpt.read() +
+            r_write_to_init_cmd_index.read()].read())  
+          p_vci_ini.be      = 0xF;
+        else			p_vci_ini.be      = 0x0;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
+        break;
+
+      case INIT_CMD_SC_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (addr_t)r_llsc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4 ;
+        p_vci_ini.eop     = true;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_SC_UPDT_NLINE:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = (uint32_t)r_llsc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        p_vci_ini.plen    = 4 * 3;
+        p_vci_ini.eop     = false;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_SC_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = r_llsc_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * 3;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_SC_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[r_init_cmd_target.read()] + 4);
+        p_vci_ini.wdata   = r_llsc_to_init_cmd_wdata.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * 3;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+
+    } // end switch r_init_cmd_fsm
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_ini port
+    //////////////////////////////////////////////////////
+
+    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
+    else                                          p_vci_ini.rspack  = false;
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt_cleanup port
+    //////////////////////////////////////////////////////
+    p_vci_tgt_cleanup.rspval = false;
+    p_vci_tgt_cleanup.rsrcid = 0;
+    p_vci_tgt_cleanup.rdata  = 0;
+    p_vci_tgt_cleanup.rpktid = 0;
+    p_vci_tgt_cleanup.rtrdid = 0;
+    p_vci_tgt_cleanup.rerror = 0;
+    p_vci_tgt_cleanup.reop   = false;
+    p_vci_tgt_cleanup.cmdack = false ;
+
+    switch(r_cleanup_fsm.read()){
+      case CLEANUP_IDLE:
+        {
+          p_vci_tgt_cleanup.cmdack = true ;
+          break;
+        }
+      case CLEANUP_RSP:
+        {
+          p_vci_tgt_cleanup.rspval = true;
+          p_vci_tgt_cleanup.rdata  = 0;
+          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
+          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
+          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
+          p_vci_tgt_cleanup.rerror = 0;
+          p_vci_tgt_cleanup.reop   = 1;
+          break;
+        }
+
+    }
+
+  } // end genMoore()
+
+}} // end name space
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v3/caba/metadata/vci_mem_cache_v3.sd
===================================================================
--- trunk/modules/vci_mem_cache_v3/caba/metadata/vci_mem_cache_v3.sd	(revision 2)
+++ trunk/modules/vci_mem_cache_v3/caba/metadata/vci_mem_cache_v3.sd	(revision 2)
@@ -0,0 +1,41 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_mem_cache_v3',
+       classname = 'soclib::caba::VciMemCacheV3',
+       tmpl_parameters = [parameter.Module('vci_param', default = 'caba:vci_param'),],
+       header_files = ['../source/include/vci_mem_cache_v3.h',
+                       '../source/include/xram_transaction_v3.h',
+                       '../source/include/mem_cache_directory_v3.h',
+                       '../source/include/atomic_tab_v3.h',
+                       '../source/include/update_tab_v3.h',],
+       implementation_files = ['../source/src/vci_mem_cache_v3.cpp',],
+       uses = [Uses('caba:base_module'),
+               Uses('common:loader'),
+               Uses('common:mapping_table'),
+               Uses('caba:generic_fifo'),
+               ],
+       ports = [Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:vci_target','p_vci_tgt_cleanup'),
+		Port('caba:vci_initiator','p_vci_ini'),
+		Port('caba:vci_initiator','p_vci_ixr'),
+                Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+                Port('caba:clock_in', 'p_clk', auto = 'clock'),],
+       instance_parameters = [
+		parameter.Module('mtp', 'common:mapping_table'),
+		parameter.Module('mtc', 'common:mapping_table'),
+		parameter.Module('mtx', 'common:mapping_table'),
+		parameter.IntTab('vci_ixr_index'),
+		parameter.IntTab('vci_ini_index'),
+		parameter.IntTab('vci_tgt_index'),
+		parameter.IntTab('vci_tgt_index_cleanup'),
+    parameter.Int('nways'),
+		parameter.Int('nsets'),
+		parameter.Int('nwords'),
+		parameter.Int('heap_size'),
+		],
+       extensions = ['dsx:get_ident=initiator_index:p_vci_ini',],
+)
Index: trunk/modules/vci_mem_cache_v3/caba/source/include/atomic_tab_v3.h
===================================================================
--- trunk/modules/vci_mem_cache_v3/caba/source/include/atomic_tab_v3.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v3/caba/source/include/atomic_tab_v3.h	(revision 2)
@@ -0,0 +1,121 @@
+#ifndef ATOMIC_TAB_V3_H_
+#define ATOMIC_TAB_V3_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+/*                  The atomic access tab                             */
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+class AtomicTab{
+    typedef uint32_t size_t;
+    typedef sc_dt::sc_uint<40> addr_t;
+
+private:
+    size_t size_tab;                            // The size of the tab
+    std::vector<addr_t> addr_tab;               // Address entries
+    std::vector<bool>   valid_tab;              // Valid entries
+
+public:
+
+    AtomicTab()
+	: addr_tab(0),
+	  valid_tab(0)
+	{
+    	size_tab=0;
+    }
+
+    AtomicTab(size_t size_tab_i)
+	: addr_tab(size_tab_i),
+	  valid_tab(size_tab_i)
+	{
+	    size_tab=size_tab_i;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The size() function returns the size of the tab */
+    /////////////////////////////////////////////////////////////////////
+    const size_t size(){
+	    return size_tab;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The init() function initializes the transaction tab entries */
+    /////////////////////////////////////////////////////////////////////
+    void init(){
+    	for ( size_t i=0; i<size_tab; i++) {
+		    addr_tab[i]=0;
+		    valid_tab[i]=false;
+    	}
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The set() function sets an entry 
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void set(const size_t id, const addr_t addr){
+	    assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	    addr_tab[id]=addr;
+	    valid_tab[id]=true;
+	    return;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The isatomic() function tests if the SC request corresponds to an entry
+       Arguments :
+       - id : the id of the initiator (index of the entry)
+       - addr : the address of the lock
+
+       This function return true if the request corresponds
+     */
+    /////////////////////////////////////////////////////////////////////
+    bool isatomic(const size_t id, const addr_t addr){
+	    assert( (id<size_tab) && "Atomic Tab Error : bad entry");
+	    bool test=valid_tab[id];
+	    test=test && (addr == addr_tab[id]);
+	    return test;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////
+    /* The reset() function resets all the entries for this lock
+       Arguments :
+       - addr : the address of the lock
+     */
+    /////////////////////////////////////////////////////////////////////
+    void reset(const addr_t addr){
+	    for(size_t i=0 ; i<size_tab ; i++){
+		    if(addr == addr_tab[i]){
+			    valid_tab[i]=false;
+		    }
+	    }
+	    return;
+    }
+
+};
+ 
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v3/caba/source/include/mem_cache_directory_v3.h
===================================================================
--- trunk/modules/vci_mem_cache_v3/caba/source/include/mem_cache_directory_v3.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v3/caba/source/include/mem_cache_directory_v3.h	(revision 2)
@@ -0,0 +1,538 @@
+#ifndef SOCLIB_CABA_MEM_CACHE_DIRECTORY_V3_H
+#define SOCLIB_CABA_MEM_CACHE_DIRECTORY_V3_H 
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+namespace soclib { namespace caba {
+
+  using namespace sc_core;
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A LRU entry 
+  ////////////////////////////////////////////////////////////////////////
+  class LruEntry {
+
+    public:
+
+      bool recent;            
+
+      void init()
+      {
+        recent=false;
+      }
+
+  }; // end class LruEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    An Owner
+  ////////////////////////////////////////////////////////////////////////
+  class Owner{
+    typedef uint32_t size_t;
+    
+    public:
+    // Fields
+      bool      inst;       // Is the owner an ICache ?
+      size_t    srcid;      // The SRCID of the owner
+
+    ////////////////////////
+    // Constructors
+    ////////////////////////
+      Owner(bool i_inst,size_t i_srcid){
+        inst    = i_inst;
+        srcid   = i_srcid;
+      }
+
+      Owner(const Owner &a){
+        inst    = a.inst;
+        srcid   = a.srcid;
+      }
+
+      Owner(){
+        inst    = false;
+        srcid   = 0;
+      }
+      // end constructors
+
+  }; // end class Owner
+
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A directory entry                               
+  ////////////////////////////////////////////////////////////////////////
+  class DirectoryEntry {
+
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+
+    public:
+
+    bool    valid;                  // entry valid
+    bool    is_cnt;                 // directory entry is in counter mode
+    bool    dirty;                  // entry dirty
+    bool    lock;                   // entry locked
+    bool    inst;                   // at least one ICache owner
+    tag_t   tag;                    // tag of the entry
+    size_t  count;                  // number of copies
+    Owner   owner;                  // an owner of the line 
+    size_t  ptr;                    // pointer to the next owner
+
+    DirectoryEntry()
+    {
+      valid         = false;
+      is_cnt        = false;
+      dirty         = false;
+      lock          = false;
+      inst          = false;
+      tag           = 0;
+      count         = 0;
+      owner.inst    = 0;
+      owner.srcid   = 0;
+      ptr           = 0;
+    }
+
+    DirectoryEntry(const DirectoryEntry &source)
+    {
+      valid         = source.valid;
+      is_cnt        = source.is_cnt;
+      dirty         = source.dirty;
+      lock          = source.lock;
+      inst          = source.inst;
+      tag           = source.tag;
+      count         = source.count;
+      owner         = source.owner;
+      ptr           = source.ptr;
+    }          
+
+    /////////////////////////////////////////////////////////////////////
+    // The init() function initializes the entry 
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      valid     = false;
+      is_cnt    = false;
+      dirty     = false;
+      lock      = false;
+      inst      = false;
+      count     = 0;
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    // The copy() function copies an existing source entry to a target 
+    /////////////////////////////////////////////////////////////////////
+    void copy(const DirectoryEntry &source)
+    {
+      valid	    = source.valid;
+      is_cnt    = source.is_cnt;
+      dirty	    = source.dirty;
+      lock	    = source.lock;
+      inst      = source.inst;
+      tag	    = source.tag;
+      count     = source.count;
+      owner     = source.owner;
+      ptr       = source.ptr;
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // The print() function prints the entry 
+    ////////////////////////////////////////////////////////////////////
+    void print()
+    {
+      std::cout << "Valid = " << valid << " ; IS COUNT = " << is_cnt << " ; Dirty = " << dirty << " ; Lock = " 
+        << lock << " ; Inst = " << inst << " ; Tag = " << std::hex << tag << std::dec << " ; Count = " << count << " ; Owner = " << owner.srcid << " " << owner.inst << " ; Pointer = " << ptr << std::endl;
+    }
+
+  }; // end class DirectoryEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                       The directory  
+  ////////////////////////////////////////////////////////////////////////
+  class CacheDirectory {
+
+    typedef sc_dt::sc_uint<40> addr_t;
+    typedef uint32_t data_t;
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+
+    private:
+
+    // Directory constants
+    size_t					m_ways;
+    size_t					m_sets;
+    size_t					m_words;
+    size_t					m_width;
+
+    // the directory & lru tables
+    DirectoryEntry 				**m_dir_tab;
+    LruEntry	 				**m_lru_tab;
+
+    public:
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+    CacheDirectory( size_t ways, size_t sets, size_t words, size_t address_width)	 
+    {
+      m_ways  = ways; 
+      m_sets  = sets;
+      m_words = words;
+      m_width = address_width;
+
+      m_dir_tab = new DirectoryEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_dir_tab[i] = new DirectoryEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_dir_tab[i][j].init();
+      }
+      m_lru_tab = new LruEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_lru_tab[i] = new LruEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_lru_tab[i][j].init();
+      }
+    } // end constructor
+
+    /////////////////
+    // Destructor
+    /////////////////
+    ~CacheDirectory()
+    {
+      for(size_t i=0 ; i<m_sets ; i++){
+        delete [] m_dir_tab[i];
+        delete [] m_lru_tab[i];
+      }
+      delete [] m_dir_tab;
+      delete [] m_lru_tab;
+    } // end destructor
+
+    /////////////////////////////////////////////////////////////////////
+    // The read() function reads a directory entry. In case of hit, the
+    // LRU is updated.
+    // Arguments :
+    // - address : the address of the entry 
+    // - way : (return argument) the way of the entry in case of hit
+    // The function returns a copy of a (valid or invalid) entry  
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry read(const addr_t &address,size_t &way)
+    {
+
+#define L2 soclib::common::uint32_log2
+      const size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
+      const tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
+#undef L2
+
+      bool hit       = false;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        bool equal = ( m_dir_tab[set][i].tag == tag );
+        bool valid = m_dir_tab[set][i].valid;
+        hit = equal && valid;
+        if ( hit ) {			
+          way = i;
+          break;
+        } 
+      }
+      if ( hit ) {
+        m_lru_tab[set][way].recent = true;
+        return DirectoryEntry(m_dir_tab[set][way]);
+      } else {
+        return DirectoryEntry();
+      }
+    } // end read()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write function writes a new entry, 
+    // and updates the LRU bits if necessary.
+    // Arguments :
+    // - set : the set of the entry
+    // - way : the way of the entry
+    // - entry : the entry value
+    /////////////////////////////////////////////////////////////////////
+    void write(const size_t &set, const size_t &way, const DirectoryEntry &entry)
+    {
+      assert( (set<m_sets) 
+          && "Cache Directory write : The set index is invalid");
+      assert( (way<m_ways) 
+          && "Cache Directory write : The way index is invalid");
+
+      // update Directory
+      m_dir_tab[set][way].copy(entry);
+
+      // update LRU bits
+      bool all_recent = true;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
+      }
+      if ( all_recent ) {
+        for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
+      } else {
+        m_lru_tab[set][way].recent = true;
+      }
+    } // end write()
+
+    /////////////////////////////////////////////////////////////////////
+    // The print() function prints a selected directory entry
+    // Arguments :
+    // - set : the set of the entry to print
+    // - way : the way of the entry to print
+    /////////////////////////////////////////////////////////////////////
+    void print(const size_t &set, const size_t &way)
+    {
+      std::cout << std::dec << " set : " << set << " ; way : " << way << " ; " ;
+      m_dir_tab[set][way].print();
+    } // end print()
+
+    /////////////////////////////////////////////////////////////////////
+    // The select() function selects a directory entry to evince.
+    // Arguments :
+    // - set   : (input argument) the set to modify
+    // - way   : (return argument) the way to evince
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry select(const size_t &set, size_t &way)
+    {
+      assert( (set < m_sets) 
+          && "Cache Directory : (select) The set index is invalid");
+
+      for(size_t i=0; i<m_ways; i++){
+        if(!m_dir_tab[set][way].valid){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if(!(m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( !(m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( (m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      way = 0;
+      return DirectoryEntry(m_dir_tab[set][0]);
+    } // end select()
+
+    /////////////////////////////////////////////////////////////////////
+    // 		Global initialisation function
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      for ( size_t set=0 ; set<m_sets ; set++ ) {
+        for ( size_t way=0 ; way<m_ways ; way++ ) {
+          m_dir_tab[set][way].init();
+          m_lru_tab[set][way].init();
+        }
+      }
+    } // end init()
+
+  }; // end class CacheDirectory
+
+  ///////////////////////////////////////////////////////////////////////
+  //                    A Heap Entry
+  ///////////////////////////////////////////////////////////////////////
+  class HeapEntry{
+    typedef uint32_t size_t;
+
+    public:
+    // Fields of the entry
+      Owner     owner;
+      size_t    next;
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+      HeapEntry()
+      :owner(false,0)
+      {
+        next = 0;
+      } // end constructor
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+      HeapEntry(const HeapEntry &entry){
+        owner.srcid = entry.owner.srcid;
+        owner.inst  = entry.owner.inst;
+        next        = entry.next;
+      } // end constructor
+
+    /////////////////////////////////////////////////////////////////////
+    // The copy() function copies an existing source entry to a target 
+    /////////////////////////////////////////////////////////////////////
+      void copy(const HeapEntry &entry){
+        owner.srcid = entry.owner.srcid;
+        owner.inst  = entry.owner.inst;
+        next        = entry.next;
+      } // end copy()
+
+    ////////////////////////////////////////////////////////////////////
+    // The print() function prints the entry 
+    ////////////////////////////////////////////////////////////////////
+      void print(){
+        std::cout 
+        << " -- owner.srcid : " << std::dec << owner.srcid << std::endl
+        << " -- owner.inst  : " << std::dec << owner.inst << std::endl
+        << " -- next        : " << std::dec << next << std::endl;
+
+      } // end print()
+
+  }; // end class HeapEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                        The Heap 
+  ////////////////////////////////////////////////////////////////////////
+  class HeapDirectory{
+    typedef uint32_t size_t;
+    
+    private:
+    // Registers and the heap
+      size_t    ptr_free;
+      bool      full;
+      HeapEntry *m_heap_tab;
+
+    // Constants for debugging purpose
+      size_t    tab_size;
+
+    public:
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+      HeapDirectory(uint32_t size){
+        assert(size>0 && "Memory Cache, HeapDirectory constructor : invalid size");
+        ptr_free    = 0;
+        full        = false;
+        m_heap_tab  = new HeapEntry[size];
+        tab_size    = size;
+      } // end constructor
+
+    /////////////////
+    // Destructor
+    /////////////////
+      ~HeapDirectory(){
+        delete [] m_heap_tab;
+      } // end destructor
+
+    /////////////////////////////////////////////////////////////////////
+    // 		Global initialisation function
+    /////////////////////////////////////////////////////////////////////
+      void init(){
+        ptr_free=0;
+        full=false;
+        for(size_t i=0; i< tab_size-1;i++){
+          m_heap_tab[i].next = i+1;
+        }
+        m_heap_tab[tab_size-1].next = tab_size-1;
+        return;
+      }
+
+    /////////////////////////////////////////////////////////////////////
+    // The print() function prints a selected directory entry
+    // Arguments :
+    // - ptr : the pointer to the entry to print
+    /////////////////////////////////////////////////////////////////////
+      void print(const size_t &ptr){
+        std::cout << "Heap, printing the entry : " << std::dec << ptr << std::endl;
+        m_heap_tab[ptr].print();
+      } // end print()
+
+    /////////////////////////////////////////////////////////////////////
+    // The is_full() function return true if the heap is full.
+    /////////////////////////////////////////////////////////////////////
+      bool is_full(){
+        return full;
+      } // end is_full()
+
+    /////////////////////////////////////////////////////////////////////
+    // The next_free_ptr() function returns the pointer 
+    // to the next free entry.
+    /////////////////////////////////////////////////////////////////////
+      size_t next_free_ptr(){
+        return ptr_free;
+      } // end next_free_ptr()
+
+    /////////////////////////////////////////////////////////////////////
+    // The next_free_entry() function returns 
+    // a copy of the next free entry.
+    /////////////////////////////////////////////////////////////////////
+      HeapEntry next_free_entry(){
+        return HeapEntry(m_heap_tab[ptr_free]);
+      } // end next_free_entry()
+   
+    /////////////////////////////////////////////////////////////////////
+    // The write_free_entry() function modify the next free entry.
+    // Arguments :
+    // - entry : the entry to write
+    /////////////////////////////////////////////////////////////////////
+      void write_free_entry(const HeapEntry &entry){
+        m_heap_tab[ptr_free].copy(entry);
+      } // end write_free_entry()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write_free_ptr() function writes the pointer
+    // to the next free entry
+    /////////////////////////////////////////////////////////////////////
+      void write_free_ptr(const size_t &ptr){
+        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
+        ptr_free = ptr;
+      } // end write_free_ptr()
+
+    /////////////////////////////////////////////////////////////////////
+    // The set_full() function sets the full bit (to true).
+    /////////////////////////////////////////////////////////////////////
+      void set_full(){
+        full = true;
+      } // end set_full()
+
+    /////////////////////////////////////////////////////////////////////
+    // The unset_full() function unsets the full bit (to false).
+    /////////////////////////////////////////////////////////////////////
+      void unset_full(){
+        full = false;
+      } // end unset_full()
+
+    /////////////////////////////////////////////////////////////////////
+    // The read() function returns a copy of
+    // the entry pointed by the argument
+    // Arguments :
+    //  - ptr : the pointer to the entry to read
+    /////////////////////////////////////////////////////////////////////
+      HeapEntry read(const size_t &ptr){
+        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
+        return HeapEntry(m_heap_tab[ptr]);
+      } // end read()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write() function writes an entry in the heap
+    // Arguments :
+    //  - ptr : the pointer to the entry to replace
+    //  - entry : the entry to write
+    /////////////////////////////////////////////////////////////////////
+      void write(const size_t &ptr, const HeapEntry &entry){
+        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
+        m_heap_tab[ptr].copy(entry);
+      } // end write()
+
+  }; // end class HeapDirectory
+
+
+}} // end namespaces
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v3/caba/source/include/update_tab_v3.h
===================================================================
--- trunk/modules/vci_mem_cache_v3/caba/source/include/update_tab_v3.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v3/caba/source/include/update_tab_v3.h	(revision 2)
@@ -0,0 +1,402 @@
+#ifndef UPDATE_TAB_V3_H_
+#define UPDATE_TAB_V3_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+////////////////////////////////////////////////////////////////////////
+//                  An update tab entry    
+////////////////////////////////////////////////////////////////////////
+class UpdateTabEntry {
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  public:
+  bool 	valid;                // It is a valid pending transaction
+  bool	update;               // It is an update transaction
+  bool  brdcast;              // It is a broadcast invalidate
+  bool  rsp;                  // It needs a response to the initiator
+  size_t 	srcid;        // The srcid of the initiator which wrote the data
+  size_t 	trdid;        // The trdid of the initiator which wrote the data
+  size_t 	pktid;        // The pktid of the initiator which wrote the data
+  addr_t	nline;	      // The identifier of the cache line
+  size_t 	count;        // The number of acknowledge responses to receive
+
+  UpdateTabEntry(){
+    valid	= false;
+    update  = false;
+    brdcast = false;
+    rsp     = false;
+    srcid	= 0;
+    trdid	= 0;
+    pktid	= 0;
+    nline	= 0;
+    count	= 0;
+  }
+
+  UpdateTabEntry(bool   i_valid, 
+      bool   i_update,
+      bool   i_brdcast,
+      bool   i_rsp,
+      size_t i_srcid, 
+      size_t i_trdid, 
+      size_t i_pktid, 
+      addr_t i_nline,
+      size_t i_count) 
+  {
+    valid		= i_valid;
+    update	    = i_update;
+    brdcast     = i_brdcast;
+    rsp         = i_rsp;
+    srcid		= i_srcid;
+    trdid		= i_trdid;
+    pktid		= i_pktid;
+    nline		= i_nline;
+    count		= i_count;
+  }
+
+  UpdateTabEntry(const UpdateTabEntry &source)
+  {
+    valid   = source.valid;
+    update  = source.update;
+    brdcast = source.brdcast;
+    rsp     = source.rsp;
+    srcid   = source.srcid;
+    trdid   = source.trdid;
+    pktid   = source.pktid;
+    nline   = source.nline;
+    count   = source.count;
+  }
+
+  ////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  ///////////////////////////////////////////////////
+  void init()
+  {
+    valid  = false;
+    update = false;
+    brdcast= false;
+    rsp    = false;
+    srcid  = 0;
+    trdid  = 0;
+    pktid  = 0;
+    nline  = 0;
+    count  = 0;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the update tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const UpdateTabEntry &source)
+  {
+    valid  = source.valid;
+    update = source.update;
+    brdcast= source.brdcast;
+    rsp    = source.rsp;
+    srcid  = source.srcid;
+    trdid  = source.trdid;
+    pktid  = source.pktid;
+    nline  = source.nline;
+    count  = source.count;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << std::dec << "valid  = " << valid  << std::endl;
+    std::cout << "update = " << update << std::endl;
+    std::cout << "brdcast= " << brdcast<< std::endl;
+    std::cout << "rsp    = " << rsp    << std::endl;
+    std::cout << "srcid  = " << srcid  << std::endl; 
+    std::cout << "trdid  = " << trdid  << std::endl; 
+    std::cout << "pktid  = " << pktid  << std::endl; 
+    std::cout << std::hex << "nline  = " << nline  << std::endl;
+    std::cout << std::dec << "count  = " << count  << std::endl;
+  }
+};
+
+////////////////////////////////////////////////////////////////////////
+//                        The update tab             
+////////////////////////////////////////////////////////////////////////
+class UpdateTab{
+
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  private:
+  size_t size_tab;
+  std::vector<UpdateTabEntry> tab;
+
+  public:
+
+  UpdateTab()
+    : tab(0)
+  {
+    size_tab=0;
+  }
+
+  UpdateTab(size_t size_tab_i)
+    : tab(size_tab_i)
+  {
+    size_tab=size_tab_i;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  const size_t size(){
+    return size_tab;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    for(size_t i=0; i<size_tab; i++) {
+      std::cout << "UPDATE TAB ENTRY " << std::dec << i << "--------" << std::endl;
+      tab[i].print();
+    }
+    return;
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the tab 
+  /////////////////////////////////////////////////////////////////////
+  void init(){
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The reads() function reads an entry 
+  // Arguments :
+  // - entry : the entry to read
+  // This function returns a copy of the entry.
+  /////////////////////////////////////////////////////////////////////
+  UpdateTabEntry read (size_t entry)
+  {
+    assert(entry<size_tab && "Bad Update Tab Entry");
+    return UpdateTabEntry(tab[entry]);
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // The set() function writes an entry in the Update Table
+  // Arguments :
+  // - update : transaction type (bool)
+  // - srcid : srcid of the initiator
+  // - trdid : trdid of the initiator
+  // - pktid : pktid of the initiator
+  // - count : number of expected responses
+  // - index : (return argument) index of the selected entry
+  // This function returns true if the write successed (an entry was empty).
+  ///////////////////////////////////////////////////////////////////////////
+  bool set(const bool	update,
+      const bool   brdcast,
+      const bool   rsp,
+      const size_t srcid,
+      const size_t trdid,
+      const size_t pktid,
+      const addr_t nline,
+      const size_t count,
+      size_t &index)
+  {
+    for ( size_t i=0 ; i<size_tab ; i++ ) {
+      if( !tab[i].valid ) {
+        tab[i].valid		= true;
+        tab[i].update		= update;
+        tab[i].brdcast      = brdcast;
+        tab[i].rsp          = rsp;
+        tab[i].srcid		= (size_t) srcid;
+        tab[i].trdid		= (size_t) trdid;
+        tab[i].pktid		= (size_t) pktid;
+        tab[i].nline		= (addr_t) nline;
+        tab[i].count		= (size_t) count;
+        index			    = i;
+        return true;
+      }
+    }
+    return false;
+  } // end set()
+
+  /////////////////////////////////////////////////////////////////////
+  // The decrement() function decrements the counter for a given entry.
+  // Arguments :
+  // - index   : the index of the entry
+  // - counter : (return argument) value of the counter after decrement
+  // This function returns true if the entry is valid.
+  /////////////////////////////////////////////////////////////////////
+  bool decrement( const size_t index,
+      size_t &counter ) 
+  {
+    assert((index<size_tab) && "Bad Update Tab Entry");
+    if ( tab[index].valid ) {
+      tab[index].count--;
+      counter = tab[index].count;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_full() function returns true if the table is full
+  /////////////////////////////////////////////////////////////////////
+  bool is_full()
+  {
+    for(size_t i = 0 ; i < size_tab ; i++){
+      if(!tab[i].valid){
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The need_rsp() function returns the need of a response
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool need_rsp(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].rsp;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_brdcast(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].brdcast;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_update(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].update;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The srcid() function returns the srcid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t srcid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].srcid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The trdid() function returns the trdid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t trdid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].trdid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The pktid() function returns the pktid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t pktid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].pktid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The nline() function returns the nline value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  addr_t nline(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].nline;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The search_inval() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool search_inval(const addr_t nline,size_t &index)
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        if(!tab[i].update){
+          index = i ;
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read_nline() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool read_nline(const addr_t nline,size_t &index) 
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        index = i ;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The clear() function erases an entry of the tab
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////       
+  void clear(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    tab[index].valid=false;
+    return;	
+  }
+
+};
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v3/caba/source/include/vci_mem_cache_v3.h
===================================================================
--- trunk/modules/vci_mem_cache_v3/caba/source/include/vci_mem_cache_v3.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v3/caba/source/include/vci_mem_cache_v3.h	(revision 2)
@@ -0,0 +1,714 @@
+/* -*- c++ -*-
+ * File         : vci_mem_cache_v3.h
+ * Date         : 26/10/2008
+ * Copyright    : UPMC / LIP6
+ * Authors      : Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+/*
+ *
+ * Modifications done by Christophe Choichillon on the 7/04/2009:
+ * - Adding new states in the CLEANUP FSM : CLEANUP_UPT_LOCK and CLEANUP_UPT_WRITE
+ * - Adding a new VCI target port for the CLEANUP network
+ * - Adding new state in the ALLOC_UPT_FSM : ALLOC_UPT_CLEANUP
+ * 
+ * Modifications to do :
+ * - Adding new variables used by the CLEANUP FSM
+ *
+ */
+
+#ifndef SOCLIB_CABA_MEM_CACHE_V3_H
+#define SOCLIB_CABA_MEM_CACHE_V3_H
+
+#include <inttypes.h>
+#include <systemc>
+#include <list>
+#include <cassert>
+#include "arithmetics.h"
+#include "alloc_elems.h"
+#include "caba_base_module.h"
+#include "vci_target.h"
+#include "vci_initiator.h"
+#include "generic_fifo.h"
+#include "mapping_table.h"
+#include "int_tab.h"
+#include "mem_cache_directory_v3.h"
+#include "xram_transaction_v3.h"
+#include "update_tab_v3.h"
+#include "atomic_tab_v3.h"
+
+#define TRANSACTION_TAB_LINES 4     // Number of lines in the transaction tab
+#define UPDATE_TAB_LINES 4          // Number of lines in the update tab
+#define BROADCAST_ADDR 0x0000000003 // Address to send the broadcast invalidate
+
+namespace soclib {  namespace caba {
+  using namespace sc_core;
+
+  template<typename vci_param>
+    class VciMemCacheV3
+    : public soclib::caba::BaseModule
+    {
+      typedef sc_dt::sc_uint<40> addr_t;
+      typedef typename vci_param::fast_addr_t vci_addr_t;
+      typedef uint32_t data_t;
+      typedef uint32_t tag_t;
+      typedef uint32_t size_t;
+      typedef uint32_t be_t;
+      typedef uint32_t copy_t;
+
+      /* States of the TGT_CMD fsm */
+      enum tgt_cmd_fsm_state_e{
+        TGT_CMD_IDLE,
+        TGT_CMD_READ,
+        TGT_CMD_READ_EOP,
+        TGT_CMD_WRITE,
+        TGT_CMD_ATOMIC,
+      };
+
+      /* States of the TGT_RSP fsm */
+      enum tgt_rsp_fsm_state_e{
+        TGT_RSP_READ_IDLE,
+        TGT_RSP_WRITE_IDLE,
+        TGT_RSP_LLSC_IDLE,
+        TGT_RSP_XRAM_IDLE,
+        TGT_RSP_INIT_IDLE,
+        TGT_RSP_CLEANUP_IDLE,
+        TGT_RSP_READ,
+        TGT_RSP_WRITE,
+        TGT_RSP_LLSC,
+        TGT_RSP_XRAM,
+        TGT_RSP_INIT,
+        TGT_RSP_CLEANUP,
+      };
+
+      /* States of the INIT_CMD fsm */
+      enum init_cmd_fsm_state_e{
+        INIT_CMD_INVAL_IDLE,
+        INIT_CMD_INVAL_NLINE,
+        INIT_CMD_XRAM_BRDCAST,
+        INIT_CMD_UPDT_IDLE,
+        INIT_CMD_WRITE_BRDCAST,
+        INIT_CMD_UPDT_NLINE,
+        INIT_CMD_UPDT_INDEX,
+        INIT_CMD_UPDT_DATA,
+        INIT_CMD_SC_UPDT_IDLE,
+        INIT_CMD_SC_BRDCAST,
+        INIT_CMD_SC_UPDT_NLINE,
+        INIT_CMD_SC_UPDT_INDEX,
+        INIT_CMD_SC_UPDT_DATA,
+      };
+
+      /* States of the INIT_RSP fsm */
+      enum init_rsp_fsm_state_e{
+        INIT_RSP_IDLE,
+        INIT_RSP_UPT_LOCK,
+        INIT_RSP_UPT_CLEAR,
+        INIT_RSP_END,
+      };
+
+      /* States of the READ fsm */
+      enum read_fsm_state_e{
+        READ_IDLE,
+        READ_DIR_LOCK,
+        READ_DIR_HIT,
+        READ_HEAP_LOCK,
+        READ_HEAP_WRITE,
+        READ_HEAP_ERASE,
+        READ_HEAP_LAST,
+        READ_RSP,
+        READ_TRT_LOCK,
+        READ_TRT_SET,
+        READ_XRAM_REQ,
+      };
+
+      /* States of the WRITE fsm */
+      enum write_fsm_state_e{
+        WRITE_IDLE,
+        WRITE_NEXT,
+        WRITE_DIR_LOCK,
+        WRITE_DIR_HIT_READ,
+        WRITE_DIR_HIT,
+        WRITE_DIR_HIT_RSP,
+        WRITE_UPT_LOCK,
+        WRITE_HEAP_LOCK,
+        WRITE_UPT_REQ,
+        WRITE_UPDATE,
+        WRITE_UPT_DEC,
+        WRITE_RSP,
+        WRITE_TRT_LOCK,
+        WRITE_TRT_DATA,
+        WRITE_TRT_SET,
+        WRITE_WAIT,
+        WRITE_XRAM_REQ,
+        WRITE_TRT_WRITE_LOCK,
+        WRITE_INVAL_LOCK,
+        WRITE_DIR_INVAL,
+        WRITE_INVAL,
+        WRITE_XRAM_SEND,
+        WRITE_HEAP_ERASE,
+        WRITE_HEAP_LAST,
+      };
+
+      /* States of the IXR_RSP fsm */
+      enum ixr_rsp_fsm_state_e{
+        IXR_RSP_IDLE,
+        IXR_RSP_ACK,
+        IXR_RSP_TRT_ERASE,
+        IXR_RSP_TRT_READ,
+      };
+
+      /* States of the XRAM_RSP fsm */
+      enum xram_rsp_fsm_state_e{
+        XRAM_RSP_IDLE,
+        XRAM_RSP_TRT_COPY,
+        XRAM_RSP_TRT_DIRTY,
+        XRAM_RSP_DIR_LOCK,
+        XRAM_RSP_DIR_UPDT,
+        XRAM_RSP_DIR_RSP,
+        XRAM_RSP_INVAL_LOCK,
+        XRAM_RSP_INVAL_WAIT,
+        XRAM_RSP_INVAL,
+        XRAM_RSP_WRITE_DIRTY,
+        XRAM_RSP_HEAP_ERASE,
+        XRAM_RSP_HEAP_LAST,
+      };
+
+      /* States of the IXR_CMD fsm */
+      enum ixr_cmd_fsm_state_e{
+        IXR_CMD_READ_IDLE,
+        IXR_CMD_WRITE_IDLE,
+        IXR_CMD_LLSC_IDLE,
+        IXR_CMD_XRAM_IDLE,
+        IXR_CMD_READ_NLINE,
+        IXR_CMD_WRITE_NLINE,
+        IXR_CMD_LLSC_NLINE,
+        IXR_CMD_XRAM_DATA,
+      };
+
+      /* States of the LLSC fsm */
+      enum llsc_fsm_state_e{
+        LLSC_IDLE,
+        LL_DIR_LOCK,
+        LL_DIR_HIT,
+        LL_RSP,
+        SC_DIR_LOCK,
+        SC_DIR_HIT,
+        SC_UPT_LOCK,
+        SC_WAIT,
+        SC_HEAP_LOCK,
+        SC_UPT_REQ,
+        SC_UPDATE,
+        SC_TRT_LOCK,
+        SC_INVAL_LOCK,
+        SC_DIR_INVAL,
+        SC_INVAL,
+        SC_XRAM_SEND,
+        SC_HEAP_ERASE,
+        SC_HEAP_LAST,
+        SC_RSP_FALSE,
+        SC_RSP_TRUE,
+        LLSC_TRT_LOCK,
+        LLSC_TRT_SET,
+        LLSC_XRAM_REQ,
+      };
+
+      /* States of the CLEANUP fsm */
+      enum cleanup_fsm_state_e{
+        CLEANUP_IDLE,
+        CLEANUP_DIR_LOCK,
+        CLEANUP_DIR_WRITE,
+        CLEANUP_HEAP_LOCK,
+        CLEANUP_HEAP_SEARCH,
+        CLEANUP_HEAP_CLEAN,
+        CLEANUP_HEAP_FREE,
+        CLEANUP_UPT_LOCK,
+        CLEANUP_UPT_WRITE,
+        CLEANUP_WRITE_RSP,
+        CLEANUP_RSP,
+      };
+
+      /* States of the ALLOC_DIR fsm */
+      enum alloc_dir_fsm_state_e{
+        ALLOC_DIR_READ,
+        ALLOC_DIR_WRITE,
+        ALLOC_DIR_LLSC,
+        ALLOC_DIR_CLEANUP,
+        ALLOC_DIR_XRAM_RSP,
+      };
+
+      /* States of the ALLOC_TRT fsm */
+      enum alloc_trt_fsm_state_e{
+        ALLOC_TRT_READ,
+        ALLOC_TRT_WRITE,
+        ALLOC_TRT_LLSC,
+        ALLOC_TRT_XRAM_RSP,
+        ALLOC_TRT_IXR_RSP,
+      };
+
+      /* States of the ALLOC_UPT fsm */
+      enum alloc_upt_fsm_state_e{
+        ALLOC_UPT_WRITE,
+        ALLOC_UPT_XRAM_RSP,
+        ALLOC_UPT_INIT_RSP,
+        ALLOC_UPT_CLEANUP,
+        ALLOC_UPT_LLSC,
+      };
+
+      /* States of the ALLOC_HEAP fsm */
+      enum alloc_heap_fsm_state_e{
+        ALLOC_HEAP_READ,
+        ALLOC_HEAP_WRITE,
+        ALLOC_HEAP_LLSC,
+        ALLOC_HEAP_CLEANUP,
+        ALLOC_HEAP_XRAM_RSP,
+      };
+
+      uint32_t	   m_cpt_cycles;            // Counter of cycles 
+      uint32_t	   m_cpt_read;              // Number of READ transactions
+      uint32_t	   m_cpt_read_miss;         // Number of MISS READ 
+      uint32_t	   m_cpt_write;             // Number of WRITE transactions
+      uint32_t	   m_cpt_write_miss;        // Number of MISS WRITE
+      uint32_t     m_cpt_write_cells;	    // Cumulated length for WRITE transactions
+      uint32_t     m_cpt_write_dirty;	    // Cumulated length for WRITE transactions
+      uint32_t	   m_cpt_update;            // Number of UPDATE transactions
+      uint32_t	   m_cpt_update_mult;       // Number of targets for UPDATE
+      uint32_t	   m_cpt_inval;             // Number of INVAL  transactions
+      uint32_t	   m_cpt_inval_mult;        // Number of targets for INVAL  
+      uint32_t	   m_cpt_inval_brdcast;     // Number of BROADCAST INVAL  
+      uint32_t	   m_cpt_cleanup;           // Number of CLEANUP transactions
+      uint32_t	   m_cpt_ll;                // Number of LL transactions
+      uint32_t	   m_cpt_sc;                // Number of SC transactions
+
+      protected:
+
+      SC_HAS_PROCESS(VciMemCacheV3);
+
+      public:
+      sc_in<bool> 			  	p_clk;
+      sc_in<bool> 			  	p_resetn;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt_cleanup;
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ini;	
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ixr;
+
+      VciMemCacheV3(
+          sc_module_name name,                              // Instance Name 
+          const soclib::common::MappingTable &mtp,          // Mapping table for primary requets
+          const soclib::common::MappingTable &mtc,          // Mapping table for coherence requets
+          const soclib::common::MappingTable &mtx,          // Mapping table for XRAM
+          const soclib::common::IntTab &vci_ixr_index,      // VCI port to XRAM (initiator)
+          const soclib::common::IntTab &vci_ini_index,      // VCI port to PROC (initiator)
+          const soclib::common::IntTab &vci_tgt_index,      // VCI port to PROC (target)
+          const soclib::common::IntTab &vci_tgt_index_cleanup,    // VCI port to PROC (target) for cleanup
+          size_t nways,                                     // Number of ways per set 
+          size_t nsets,                                     // Number of sets
+          size_t nwords,                                    // Number of words per line
+          size_t heap_size=1024);                           // Size of the heap
+
+      ~VciMemCacheV3();
+
+      void transition();
+
+      void genMoore();
+
+      void print_stats();
+
+      private:
+
+      // Component attributes
+      const size_t              m_initiators;           // Number of initiators
+      const size_t              m_heap_size;            // Size of the heap
+      const size_t              m_ways;                 // Number of ways in a set
+      const size_t              m_sets;                 // Number of cache sets
+      const size_t              m_words;		        // Number of words in a line
+      const size_t              m_srcid_ixr;		    // Srcid for requests to XRAM 
+      const size_t              m_srcid_ini;		    // Srcid for requests to processors
+      std::list<soclib::common::Segment>  m_seglist;    // memory cached into the cache
+      std::list<soclib::common::Segment>  m_cseglist;   // coherence segment for the cache
+      vci_addr_t        		*m_coherence_table; 	// address(srcid)
+      AtomicTab                 m_atomic_tab;           // atomic access table
+      TransactionTab      		m_transaction_tab;	    // xram transaction table
+      UpdateTab                 m_update_tab;		    // pending update & invalidate 
+      CacheDirectory			m_cache_directory;	    // data cache directory
+      HeapDirectory             m_heap_directory;       // heap directory
+
+      data_t	        	       ***m_cache_data;		// data array[set][way][word]
+
+      // adress masks
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_x;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_y;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_z;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_nline; 
+
+      //////////////////////////////////////////////////
+      // Others registers
+      //////////////////////////////////////////////////
+      sc_signal<size_t>   r_copies_limit; // Limit of the number of copies for one line
+
+      //////////////////////////////////////////////////
+      // Registers controlled by the TGT_CMD fsm
+      //////////////////////////////////////////////////
+
+      // Fifo between TGT_CMD fsm and READ fsm
+      GenericFifo<uint64_t>  m_cmd_read_addr_fifo;
+      GenericFifo<size_t>    m_cmd_read_length_fifo;
+      GenericFifo<size_t>    m_cmd_read_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_read_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_read_pktid_fifo;
+
+      // Fifo between TGT_CMD fsm and WRITE fsm    
+      GenericFifo<uint64_t>  m_cmd_write_addr_fifo;
+      GenericFifo<bool>      m_cmd_write_eop_fifo;
+      GenericFifo<size_t>    m_cmd_write_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_write_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_write_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_write_data_fifo;
+      GenericFifo<be_t>	     m_cmd_write_be_fifo;
+
+      // Fifo between TGT_CMD fsm and LLSC fsm
+      GenericFifo<uint64_t>  m_cmd_llsc_addr_fifo;
+      GenericFifo<bool>      m_cmd_llsc_sc_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_llsc_wdata_fifo;
+
+      sc_signal<int>         r_tgt_cmd_fsm;
+
+      sc_signal<size_t>	     r_index;
+      size_t nseg;
+      size_t ncseg;
+      soclib::common::Segment  **m_seg;
+      soclib::common::Segment  **m_cseg;
+      ///////////////////////////////////////////////////////
+      // Registers controlled by the READ fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>         r_read_fsm;        // FSM state 
+      sc_signal<size_t>      r_read_copy;       // Srcid of the first copy
+      sc_signal<bool>        r_read_copy_inst;  // Type of the first copy
+      sc_signal<tag_t>       r_read_tag;	    // cache line tag (in directory)
+      sc_signal<bool>        r_read_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>        r_read_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_read_dirty;	    // dirty bit (in directory)
+      sc_signal<bool>        r_read_inst;       // it is an instruction line
+      sc_signal<size_t>      r_read_count;      // number of copies
+      sc_signal<size_t>      r_read_ptr;        // pointer to the heap
+      sc_signal<data_t>     *r_read_data;       // data (one cache line)
+      sc_signal<size_t>      r_read_way;        // associative way (in cache)
+      sc_signal<size_t>      r_read_trt_index;  // Transaction Table index
+      sc_signal<size_t>      r_read_next_ptr;   // Next entry to point to
+      sc_signal<bool>        r_read_last_free;  // Last free entry
+
+      // Buffer between READ fsm and IXR_CMD fsm (ask a missing cache line to XRAM)   
+      sc_signal<bool>        r_read_to_ixr_cmd_req;     // valid request
+      sc_signal<addr_t>      r_read_to_ixr_cmd_nline;   // cache line index
+      sc_signal<size_t>      r_read_to_ixr_cmd_trdid;   // index in Transaction Table
+
+      // Buffer between READ fsm and TGT_RSP fsm (send a hit read response to L1 cache)
+      sc_signal<bool>	   r_read_to_tgt_rsp_req;       // valid request
+      sc_signal<size_t>	   r_read_to_tgt_rsp_srcid;	    // Transaction srcid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_trdid;	    // Transaction trdid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_pktid;	    // Transaction pktid
+      sc_signal<data_t>   *r_read_to_tgt_rsp_data;	    // data (one cache line)
+      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
+
+      ///////////////////////////////////////////////////////////////
+      // Registers controlled by the WRITE fsm
+      ///////////////////////////////////////////////////////////////
+
+      sc_signal<int>       r_write_fsm;             // FSM state
+      sc_signal<addr_t>	   r_write_address;         // first word address
+      sc_signal<size_t>    r_write_word_index;      // first word index in line
+      sc_signal<size_t>    r_write_word_count;      // number of words in line
+      sc_signal<size_t>    r_write_srcid;           // transaction srcid
+      sc_signal<size_t>    r_write_trdid;           // transaction trdid
+      sc_signal<size_t>    r_write_pktid;           // transaction pktid
+      sc_signal<data_t>	  *r_write_data;            // data (one cache line)	
+      sc_signal<be_t>     *r_write_be;              // one byte enable per word
+      sc_signal<bool>      r_write_byte;            // is it a byte write
+      sc_signal<bool>      r_write_is_cnt;          // is_cnt bit (in directory)
+      sc_signal<bool>      r_write_lock;            // lock bit (in directory)
+      sc_signal<bool>      r_write_inst;            // instruction bit
+      sc_signal<tag_t>     r_write_tag;             // cache line tag (in directory)
+      sc_signal<size_t>    r_write_copy;            // first owner of the line
+      sc_signal<bool>      r_write_copy_inst;       // is this owner a ICache ?
+      sc_signal<size_t>	   r_write_count;           // number of copies
+      sc_signal<size_t>    r_write_ptr;             // pointer to the heap
+      sc_signal<size_t>    r_write_next_ptr;        // next pointer to the heap
+      sc_signal<bool>      r_write_to_dec;          // need to decrement update counter
+      sc_signal<size_t>	   r_write_way;		        // way of the line
+      sc_signal<size_t>    r_write_trt_index;	    // index in Transaction Table
+      sc_signal<size_t>    r_write_upt_index;	    // index in Update Table
+
+      // 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
+
+      // Buffer between WRITE fsm and IXR_CMD fsm (ask a missing cache line to XRAM) 
+      sc_signal<bool>	   r_write_to_ixr_cmd_req;      // valid request
+      sc_signal<bool>	   r_write_to_ixr_cmd_write;    // write request
+      sc_signal<addr_t>    r_write_to_ixr_cmd_nline; 	// cache line index
+      sc_signal<data_t>	  *r_write_to_ixr_cmd_data;	    // cache line data
+      sc_signal<size_t>    r_write_to_ixr_cmd_trdid;	// index in Transaction Table
+
+      // Buffer between WRITE fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>	   r_write_to_init_cmd_multi_req;   // valid multicast request
+      sc_signal<bool>	   r_write_to_init_cmd_brdcast_req; // valid brdcast request
+      sc_signal<addr_t>	   r_write_to_init_cmd_nline;	    // cache line index
+      sc_signal<size_t>	   r_write_to_init_cmd_trdid;	    // index in Update Table
+      sc_signal<data_t>   *r_write_to_init_cmd_data;	    // data (one cache line)
+      sc_signal<bool>     *r_write_to_init_cmd_we;	        // word enable
+      sc_signal<size_t>	   r_write_to_init_cmd_count;	    // number of words in line
+      sc_signal<size_t>	   r_write_to_init_cmd_index;	    // index of first word in line
+      GenericFifo<bool>    m_write_to_init_cmd_inst_fifo;   // fifo for the L1 type
+      GenericFifo<size_t>  m_write_to_init_cmd_srcid_fifo;  // fifo for srcids
+
+      // Buffer between WRITE fsm and INIT_RSP fsm (Decrement UPT entry)
+      sc_signal<bool>      r_write_to_init_rsp_req;         // valid request
+      sc_signal<size_t>    r_write_to_init_rsp_upt_index;   // index in update table
+
+      /////////////////////////////////////////////////////////
+      // Registers controlled by INIT_RSP fsm
+      //////////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_init_rsp_fsm;        // FSM state
+      sc_signal<size_t>	   r_init_rsp_upt_index;  // index in the Update Table
+      sc_signal<size_t>	   r_init_rsp_srcid;	  // pending write srcid      
+      sc_signal<size_t>	   r_init_rsp_trdid;	  // pending write trdid      
+      sc_signal<size_t>	   r_init_rsp_pktid;	  // pending write pktid      
+      sc_signal<addr_t>	   r_init_rsp_nline;	  // pending write nline      
+
+      // Buffer between INIT_RSP fsm and TGT_RSP fsm (complete write/update transaction)
+      sc_signal<bool>	     r_init_rsp_to_tgt_rsp_req;   	// valid request
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_srcid;		// Transaction srcid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_trdid;		// Transaction trdid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_pktid;		// Transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by CLEANUP fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int> 	     r_cleanup_fsm;         // FSM state
+      sc_signal<size_t>      r_cleanup_srcid;       // transaction srcid
+      sc_signal<size_t>      r_cleanup_trdid;       // transaction trdid
+      sc_signal<size_t>      r_cleanup_pktid;       // transaction pktid
+      sc_signal<addr_t>      r_cleanup_nline;       // cache line index
+
+      sc_signal<copy_t>      r_cleanup_copy;        // first copy
+      sc_signal<size_t>      r_cleanup_copy_inst;   // type of the first copy
+      sc_signal<copy_t>      r_cleanup_count;       // number of copies 
+      sc_signal<size_t>      r_cleanup_ptr;         // pointer to the heap
+      sc_signal<size_t>      r_cleanup_prev_ptr;    // previous pointer to the heap
+      sc_signal<size_t>      r_cleanup_prev_srcid;  // srcid of previous heap entry
+      sc_signal<bool>        r_cleanup_prev_inst;   // inst bit of previous heap entry
+      sc_signal<size_t>      r_cleanup_next_ptr;    // next pointer to the heap
+      sc_signal<tag_t>       r_cleanup_tag;	        // cache line tag (in directory)
+      sc_signal<bool>        r_cleanup_is_cnt;      // inst bit (in directory)
+      sc_signal<bool>        r_cleanup_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_cleanup_inst;	    // inst bit (in directory)
+      sc_signal<bool>        r_cleanup_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>      r_cleanup_way;	        // associative way (in cache)
+
+      sc_signal<size_t>      r_cleanup_write_srcid; // srcid of write response
+      sc_signal<size_t>      r_cleanup_write_trdid; // trdid of write rsp
+      sc_signal<size_t>      r_cleanup_write_pktid; // pktid of write rsp
+      sc_signal<bool>        r_cleanup_need_rsp;    // needs a write rsp
+
+      sc_signal<size_t>      r_cleanup_index;	    // index of the INVAL line (in the UPT)
+
+      // Buffer between CLEANUP fsm and TGT_RSP fsm (acknowledge a write command from L1)
+      sc_signal<bool>      r_cleanup_to_tgt_rsp_req;    // valid request
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_srcid;  // transaction srcid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_trdid;	// transaction trdid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_pktid;	// transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by LLSC fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>       r_llsc_fsm;          // FSM state
+      sc_signal<data_t>	   r_llsc_data;		    // read data word
+      sc_signal<copy_t>    r_llsc_copy; 	    // Srcid of the first copy
+      sc_signal<bool>      r_llsc_copy_inst;	// Type of the first copy
+      sc_signal<size_t>    r_llsc_count;	    // number of copies
+      sc_signal<size_t>    r_llsc_ptr;  	    // pointer to the heap
+      sc_signal<size_t>    r_llsc_next_ptr;  	// next pointer to the heap
+      sc_signal<bool>      r_llsc_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>      r_llsc_dirty;	    // dirty bit (in directory)
+      sc_signal<bool>      r_llsc_inst;         // inst bit
+      sc_signal<size_t>    r_llsc_way;		    // way in directory
+      sc_signal<size_t>    r_llsc_set;		    // set in directory
+      sc_signal<data_t>    r_llsc_tag;		    // cache line tag (in directory)
+      sc_signal<size_t>    r_llsc_trt_index;    // Transaction Table index
+      sc_signal<size_t>    r_llsc_upt_index;    // Update Table index
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (XRAM read)	
+      sc_signal<bool>	   r_llsc_to_ixr_cmd_req;   // valid request
+      sc_signal<addr_t>	   r_llsc_to_ixr_cmd_nline; // cache line index
+      sc_signal<size_t>	   r_llsc_to_ixr_cmd_trdid; // index in Transaction Table
+      sc_signal<bool>	   r_llsc_to_ixr_cmd_write; // write request
+      sc_signal<data_t>	  *r_llsc_to_ixr_cmd_data;  // cache line data
+
+
+      // Buffer between LLSC fsm and TGT_RSP fsm
+      sc_signal<bool>	   r_llsc_to_tgt_rsp_req;   // valid request
+      sc_signal<data_t>    r_llsc_to_tgt_rsp_data;  // read data word
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_srcid; // Transaction srcid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_trdid; // Transaction trdid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_pktid; // Transaction pktid
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>	   r_llsc_to_init_cmd_multi_req;    // valid request
+      sc_signal<bool>	   r_llsc_to_init_cmd_brdcast_req;  // brdcast request
+      sc_signal<addr_t>	   r_llsc_to_init_cmd_nline;	    // cache line index
+      sc_signal<size_t>	   r_llsc_to_init_cmd_trdid;	    // index in Update Table
+      sc_signal<data_t>    r_llsc_to_init_cmd_wdata;        // data (one word)
+      sc_signal<size_t>	   r_llsc_to_init_cmd_index;	    // index of the word in line
+      GenericFifo<bool>    m_llsc_to_init_cmd_inst_fifo;    // fifo for the L1 type
+      GenericFifo<size_t>  m_llsc_to_init_cmd_srcid_fifo;   // fifo for srcids
+
+      // Buffer between LLSC fsm and INIT_RSP fsm (Decrement UPT entry)
+      sc_signal<bool>      r_llsc_to_init_rsp_req;          // valid request
+      sc_signal<size_t>    r_llsc_to_init_rsp_upt_index;    // index in update table
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_rsp_fsm;       // FSM state
+      sc_signal<size_t>	   r_ixr_rsp_trt_index;	// TRT entry index
+      sc_signal<size_t>    r_ixr_rsp_cpt;	    // word counter
+
+      // Buffer between IXR_RSP fsm and XRAM_RSP fsm  (response from the XRAM)
+      sc_signal<bool>	  *r_ixr_rsp_to_xram_rsp_rok;	// A xram response is ready
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the XRAM_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_xram_rsp_fsm;		        // FSM state
+      sc_signal<size_t>	   r_xram_rsp_trt_index;	    // TRT entry index
+      TransactionTabEntry  r_xram_rsp_trt_buf;		    // TRT entry local buffer
+      sc_signal<bool>	   r_xram_rsp_victim_inval;	    // victim line invalidate 
+      sc_signal<bool>	   r_xram_rsp_victim_is_cnt;    // victim line inst bit
+      sc_signal<bool>	   r_xram_rsp_victim_dirty;	    // victim line dirty bit
+      sc_signal<size_t>    r_xram_rsp_victim_way;	    // victim line way
+      sc_signal<size_t>    r_xram_rsp_victim_set;	    // victim line set
+      sc_signal<addr_t>    r_xram_rsp_victim_nline;     // victim line index
+      sc_signal<copy_t>    r_xram_rsp_victim_copy;  	// victim line first copy
+      sc_signal<bool>      r_xram_rsp_victim_copy_inst;	// victim line type of first copy
+      sc_signal<size_t>    r_xram_rsp_victim_count;	    // victim line number of copies
+      sc_signal<size_t>    r_xram_rsp_victim_ptr;       // victim line pointer to the heap
+      sc_signal<data_t>	  *r_xram_rsp_victim_data;	    // victim line data
+      sc_signal<size_t>	   r_xram_rsp_upt_index;	    // UPT entry index
+      sc_signal<size_t>    r_xram_rsp_next_ptr;         // Next pointer to the heap
+
+      // Buffer between XRAM_RSP fsm and TGT_RSP fsm  (response to L1 cache)
+      sc_signal<bool>	   r_xram_rsp_to_tgt_rsp_req;	// Valid request
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_srcid;	// Transaction srcid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_trdid;	// Transaction trdid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_pktid;	// Transaction pktid
+      sc_signal<data_t>   *r_xram_rsp_to_tgt_rsp_data;	// data (one cache line)
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_word;  // first word index
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_length;// length of the response
+
+      // Buffer between XRAM_RSP fsm and INIT_CMD fsm (Inval L1 Caches) 
+      sc_signal<bool>	    r_xram_rsp_to_init_cmd_multi_req;       // Valid request
+      sc_signal<bool>       r_xram_rsp_to_init_cmd_brdcast_req;     // Broadcast request
+      sc_signal<addr_t>     r_xram_rsp_to_init_cmd_nline;           // cache line index;
+      sc_signal<size_t>	    r_xram_rsp_to_init_cmd_trdid;           // index of UPT entry
+      GenericFifo<bool>     m_xram_rsp_to_init_cmd_inst_fifo;       // fifo for the L1 type
+      GenericFifo<size_t>   m_xram_rsp_to_init_cmd_srcid_fifo;      // fifo for srcids
+
+      // Buffer between XRAM_RSP fsm and IXR_CMD fsm (XRAM write)
+      sc_signal<bool>	   r_xram_rsp_to_ixr_cmd_req;	// Valid request
+      sc_signal<addr_t>	   r_xram_rsp_to_ixr_cmd_nline;	// cache line index
+      sc_signal<data_t>	  *r_xram_rsp_to_ixr_cmd_data;	// cache line data
+      sc_signal<size_t>	   r_xram_rsp_to_ixr_cmd_trdid;	// index in transaction table
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_cmd_fsm;
+      sc_signal<size_t>	   r_ixr_cmd_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by TGT_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_tgt_rsp_fsm;
+      sc_signal<size_t>    r_tgt_rsp_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by INIT_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	  r_init_cmd_fsm;
+      sc_signal<size_t>   r_init_cmd_cpt;
+      sc_signal<bool>     r_init_cmd_inst;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_DIR fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_dir_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_TRT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_trt_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_UPT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_upt_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_HEAP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_heap_fsm;
+
+    }; // end class VciMemCacheV3
+
+}}
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v3/caba/source/include/xram_transaction_v3.h
===================================================================
--- trunk/modules/vci_mem_cache_v3/caba/source/include/xram_transaction_v3.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v3/caba/source/include/xram_transaction_v3.h	(revision 2)
@@ -0,0 +1,404 @@
+#ifndef XRAM_TRANSACTION_V3_H_
+#define XRAM_TRANSACTION_V3_H_
+ 
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+#define DEBUG_XRAM_TRANSACTION 0
+
+////////////////////////////////////////////////////////////////////////
+//                  A transaction tab entry         
+////////////////////////////////////////////////////////////////////////
+
+class TransactionTabEntry {
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ public:
+  bool 		      valid;     	    // entry valid 
+  bool 		      xram_read; 	    // read request to XRAM
+  addr_t   	      nline;    	    // index (zy) of the requested line
+  size_t 	      srcid;     	    // processor requesting the transaction
+  size_t 	      trdid;     	    // processor requesting the transaction
+  size_t 	      pktid;     	    // processor requesting the transaction
+  bool 		      proc_read;	    // read request from processor
+  size_t 		  read_length;      // length of the read (for the response)
+  size_t 	      word_index;    	// index of the first read word (for the response)
+  std::vector<data_t> wdata;        // write buffer (one cache line)
+  std::vector<be_t>   wdata_be;    	// be for each data in the write buffer
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    valid		= false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The alloc() function initializes the vectors of an entry
+  // Its arguments are :
+  // - n_words : number of words per line in the cache
+  /////////////////////////////////////////////////////////////////////
+  void alloc(size_t n_words)
+  {
+    wdata_be.reserve( (int)n_words );
+    wdata.reserve( (int)n_words );
+    for(size_t i=0; i<n_words; i++){
+      wdata_be.push_back(false);
+      wdata.push_back(0);
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the transaction tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const TransactionTabEntry &source)
+  {
+    valid	    = source.valid;
+    xram_read 	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read 	= source.proc_read;
+    read_length = source.read_length;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry 
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << "valid       = " << valid        << std::endl;
+    std::cout << "xram_read   = " << xram_read    << std::endl;
+    std::cout << "nline       = " << std::hex << nline << std::endl;
+    std::cout << "srcid       = " << srcid        << std::endl;
+    std::cout << "trdid       = " << trdid        << std::endl;
+    std::cout << "pktid       = " << pktid        << std::endl;
+    std::cout << "proc_read   = " << proc_read    << std::endl;
+    std::cout << "read_length = " << read_length  << std::endl;
+    std::cout << "word_index  = " << word_index   << std::endl; 
+    for(size_t i=0; i<wdata_be.size() ; i++){
+      std::cout << "wdata_be [" << i <<"] = " << wdata_be[i] << std::endl;
+    }
+    for(size_t i=0; i<wdata.size() ; i++){
+      std::cout << "wdata [" << i <<"] = " << wdata[i] << std::endl;
+    }
+    std::cout << std::endl;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // 		Constructors
+  /////////////////////////////////////////////////////////////////////
+
+  TransactionTabEntry()
+    {
+      wdata_be.clear();
+      wdata.clear();
+      valid=false;
+    }
+
+  TransactionTabEntry(const TransactionTabEntry &source){
+    valid	    = source.valid;
+    xram_read	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read	= source.proc_read;
+    read_length = source.read_length;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+}; // end class TransactionTabEntry
+
+////////////////////////////////////////////////////////////////////////
+//                  The transaction tab                              
+////////////////////////////////////////////////////////////////////////
+class TransactionTab{
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ private:
+  size_t size_tab;                // The size of the tab
+
+  data_t be_to_mask(be_t be)
+  {
+    data_t ret = 0;
+    if ( be&0x1 ) {
+      ret = ret | 0x000000FF;
+    }
+    if ( be&0x2 ) {
+      ret = ret | 0x0000FF00;
+    }
+    if ( be&0x4 ) {
+      ret = ret | 0x00FF0000;
+    }
+    if ( be&0x8 ) {
+      ret = ret | 0xFF000000;
+    }
+    return ret;
+  }
+
+ public:
+  TransactionTabEntry *tab;       // The transaction tab
+
+  ////////////////////////////////////////////////////////////////////
+  //		Constructors
+  ////////////////////////////////////////////////////////////////////
+  TransactionTab()
+    {
+      size_tab=0;
+      tab=NULL;
+    }
+
+  TransactionTab(size_t n_entries, size_t n_words)
+    {
+      size_tab = n_entries;
+      tab = new TransactionTabEntry[size_tab];
+      for ( size_t i=0; i<size_tab; i++) {
+	tab[i].alloc(n_words);
+      }
+    }
+
+  ~TransactionTab()
+    {
+      delete [] tab;
+    }
+
+  /////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab
+  /////////////////////////////////////////////////////////////////////
+  size_t size()
+  {
+    return size_tab;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the transaction tab entries
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The print() function prints a transaction tab entry
+  // Arguments :
+  // - index : the index of the entry to print
+  /////////////////////////////////////////////////////////////////////
+  void print(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    tab[index].print();
+    return;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read() function returns a transaction tab entry.
+  // Arguments :
+  // - index : the index of the entry to read
+  /////////////////////////////////////////////////////////////////////
+  TransactionTabEntry read(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    return tab[index];
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The full() function returns the state of the transaction tab
+  // Arguments :
+  // - index : (return argument) the index of an empty entry 
+  // The function returns true if the transaction tab is full
+  /////////////////////////////////////////////////////////////////////
+  bool full(size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(!tab[i].valid){
+	    index=i;
+	    return false;	
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The hit_read() function checks if an XRAM read transaction exists 
+  // for a given cache line.
+  // Arguments :
+  // - index : (return argument) the index of the hit entry, if there is 
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a read request has already been sent
+  //////////////////////////////////////////////////////////////////////
+  bool hit_read(const addr_t nline,size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if((tab[i].valid && (nline==tab[i].nline)) && (tab[i].xram_read)) {
+	    index=i;
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  ///////////////////////////////////////////////////////////////////////
+  // The hit_write() function looks if an XRAM write transaction exists 
+  // for a given line.
+  // Arguments :
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a write request has already been sent
+  ///////////////////////////////////////////////////////////////////////
+  bool hit_write(const addr_t nline)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(tab[i].valid && (nline==tab[i].nline) && !(tab[i].xram_read)) {
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_data_mask() function writes a vector of data (a line).
+  // The data is written only if the corresponding bits are set
+  // in the be vector. 
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  // - be   : vector of be 
+  // - data : vector of data
+  /////////////////////////////////////////////////////////////////////
+  void write_data_mask(const size_t index, 
+		       const std::vector<be_t> &be, 
+		       const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    assert(be.size()==tab[index].wdata_be.size() 
+	   && "Bad data mask in write_data_mask in TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data in write_data_mask in TransactionTab");
+
+    for(size_t i=0; i<tab[index].wdata_be.size() ; i++) {
+      tab[index].wdata_be[i] = tab[index].wdata_be[i] | be[i];
+      data_t mask = be_to_mask(be[i]);
+      tab[index].wdata[i] = (tab[index].wdata[i] & ~mask) | (data[i] & mask);
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The set() function registers a transaction (read or write)
+  // to the XRAM in the transaction tab.
+  // Arguments :
+  // - index : index in the transaction tab
+  // - xram_read : transaction type (read or write a cache line)
+  // - nline : the index (zy) of the cache line
+  // - srcid : srcid of the initiator that caused the transaction
+  // - trdid : trdid of the initiator that caused the transaction
+  // - pktid : pktid of the initiator that caused the transaction
+  // - proc_read : does the initiator want a copy
+  // - read_length : length of read (in case of processor read)
+  // - word_index : index in the line (in case of single word read)
+  // - data : the data to write (in case of write)
+  // - data_be : the mask of the data to write (in case of write)
+  /////////////////////////////////////////////////////////////////////
+  void set(const size_t index,
+	   const bool xram_read,
+	   const addr_t nline,
+	   const size_t srcid,
+	   const size_t trdid,
+	   const size_t pktid,
+	   const bool proc_read,
+	   const size_t read_length,
+	   const size_t word_index,
+	   const std::vector<be_t> &data_be,
+	   const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in set() Transaction Tab");
+    assert(data_be.size()==tab[index].wdata_be.size() 
+	   && "Bad data_be argument in set() TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data argument in set() TransactionTab");
+
+    tab[index].valid	        = true;
+    tab[index].xram_read        = xram_read;
+    tab[index].nline	        = nline;
+    tab[index].srcid	        = srcid;
+    tab[index].trdid	        = trdid;
+    tab[index].pktid	        = pktid;
+    tab[index].proc_read	    = proc_read;
+    tab[index].read_length	    = read_length;
+    tab[index].word_index	    = word_index;
+    for(size_t i=0; i<tab[index].wdata.size(); i++) {
+      tab[index].wdata_be[i]    = data_be[i];
+      tab[index].wdata[i]       = data[i];
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_rsp() function writes a word of the response to an 
+  // XRAM read transaction.
+  // The data is only written when the corresponding BE field is Ox0.
+  // Arguments :
+  // - index : the index of the transaction in the transaction tab
+  // - word_index : the index of the data in the line
+  // - data : the data to write
+  /////////////////////////////////////////////////////////////////////
+  void write_rsp(const size_t index,
+		 const size_t word,
+		 const data_t data)
+  {
+    assert( (index < size_tab) 
+	    && "Selected entry  out of range in write_rsp() Transaction Tab");
+    assert( (word <= tab[index].wdata_be.size()) 
+	    && "Bad word_index in write_rsp() in TransactionTab");
+    assert( tab[index].valid 
+	    && "Transaction Tab Entry invalid in write_rsp()");
+    assert( tab[index].xram_read 
+	    && "Selected entry is not an XRAM read transaction in write_rsp()");
+
+    data_t mask = be_to_mask(tab[index].wdata_be[word]);
+    tab[index].wdata[word] = (tab[index].wdata[word] & mask) | (data & ~mask);
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The erase() function erases an entry in the transaction tab.
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  /////////////////////////////////////////////////////////////////////
+  void erase(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in erase() Transaction Tab");
+    tab[index].valid	= false;
+  }
+}; // end class TransactionTab
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v3/caba/source/src/vci_mem_cache_v3.cpp
===================================================================
--- trunk/modules/vci_mem_cache_v3/caba/source/src/vci_mem_cache_v3.cpp	(revision 2)
+++ trunk/modules/vci_mem_cache_v3/caba/source/src/vci_mem_cache_v3.cpp	(revision 2)
@@ -0,0 +1,4561 @@
+/* -*- c++ -*-
+ * File 	: vci_mem_cache_v3.cpp
+ * Date 	: 30/10/2008
+ * Copyright 	: UPMC / LIP6
+ * Authors 	: Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+#include "../include/vci_mem_cache_v3.h"
+
+//#define TDEBUG // Transaction tab debug
+//#define IDEBUG // Update tab debug
+//#define DDEBUG // Directory debug
+//#define DEBUG_VCI_MEM_CACHE 1
+namespace soclib { namespace caba {
+
+#ifdef DEBUG_VCI_MEM_CACHE 
+  const char *tgt_cmd_fsm_str[] = {
+    "TGT_CMD_IDLE",
+    "TGT_CMD_READ",
+    "TGT_CMD_READ_EOP",
+    "TGT_CMD_WRITE",
+    "TGT_CMD_ATOMIC",
+  };
+  const char *tgt_rsp_fsm_str[] = {
+    "TGT_RSP_READ_IDLE",
+    "TGT_RSP_WRITE_IDLE",
+    "TGT_RSP_LLSC_IDLE",
+    "TGT_RSP_XRAM_IDLE",
+    "TGT_RSP_INIT_IDLE",
+    "TGT_RSP_CLEANUP_IDLE",
+    "TGT_RSP_READ",
+    "TGT_RSP_WRITE",
+    "TGT_RSP_LLSC",
+    "TGT_RSP_XRAM",
+    "TGT_RSP_INIT",
+    "TGT_RSP_CLEANUP",
+  };
+  const char *init_cmd_fsm_str[] = {
+    "INIT_CMD_INVAL_IDLE",
+    "INIT_CMD_INVAL_NLINE",
+    "INIT_CMD_XRAM_BRDCAST",
+    "INIT_CMD_UPDT_IDLE",
+    "INIT_CMD_WRITE_BRDCAST",
+    "INIT_CMD_UPDT_NLINE",
+    "INIT_CMD_UPDT_INDEX",
+    "INIT_CMD_UPDT_DATA",
+    "INIT_CMD_SC_UPDT_IDLE",
+    "INIT_CMD_SC_BRDCAST",
+    "INIT_CMD_SC_UPDT_NLINE",
+    "INIT_CMD_SC_UPDT_INDEX",
+    "INIT_CMD_SC_UPDT_DATA",
+  };
+  const char *init_rsp_fsm_str[] = {
+    "INIT_RSP_IDLE",
+    "INIT_RSP_UPT_LOCK",
+    "INIT_RSP_UPT_CLEAR",
+    "INIT_RSP_END",
+  };
+  const char *read_fsm_str[] = {
+    "READ_IDLE",
+    "READ_DIR_LOCK",
+    "READ_DIR_HIT",
+    "READ_HEAP_LOCK",
+    "READ_HEAP_WRITE",
+    "READ_HEAP_ERASE",
+    "READ_HEAP_LAST",
+    "READ_RSP",
+    "READ_TRT_LOCK",
+    "READ_TRT_SET",
+    "READ_XRAM_REQ",
+  };
+  const char *write_fsm_str[] = {
+    "WRITE_IDLE",
+    "WRITE_NEXT",
+    "WRITE_DIR_LOCK",
+    "WRITE_DIR_HIT_READ",
+    "WRITE_DIR_HIT",
+    "WRITE_DIR_HIT_RSP",
+    "WRITE_UPT_LOCK",
+    "WRITE_HEAP_LOCK",
+    "WRITE_UPT_REQ",
+    "WRITE_UPDATE",
+    "WRITE_UPT_DEC",
+    "WRITE_RSP",
+    "WRITE_TRT_LOCK",
+    "WRITE_TRT_DATA",
+    "WRITE_TRT_SET",
+    "WRITE_WAIT",
+    "WRITE_XRAM_REQ",
+    "WRITE_TRT_WRITE_LOCK",
+    "WRITE_INVAL_LOCK",
+    "WRITE_DIR_INVAL",
+    "WRITE_INVAL",
+    "WRITE_XRAM_SEND",
+    "WRITE_HEAP_ERASE",
+    "WRITE_HEAP_LAST",
+  };
+  const char *ixr_rsp_fsm_str[] = {
+    "IXR_RSP_IDLE",
+    "IXR_RSP_ACK",
+    "IXR_RSP_TRT_ERASE",
+    "IXR_RSP_TRT_READ",
+  };
+  const char *xram_rsp_fsm_str[] = {
+    "XRAM_RSP_IDLE",
+    "XRAM_RSP_TRT_COPY",
+    "XRAM_RSP_TRT_DIRTY",
+    "XRAM_RSP_DIR_LOCK",
+    "XRAM_RSP_DIR_UPDT",
+    "XRAM_RSP_DIR_RSP",
+    "XRAM_RSP_INVAL_LOCK",
+    "XRAM_RSP_INVAL_WAIT",
+    "XRAM_RSP_INVAL",
+    "XRAM_RSP_WRITE_DIRTY",
+    "XRAM_RSP_HEAP_ERASE",
+    "XRAM_RSP_HEAP_LAST",
+  };
+  const char *ixr_cmd_fsm_str[] = {
+    "IXR_CMD_READ_IDLE",
+    "IXR_CMD_WRITE_IDLE",
+    "IXR_CMD_LLSC_IDLE",
+    "IXR_CMD_XRAM_IDLE",
+    "IXR_CMD_READ_NLINE",
+    "IXR_CMD_WRITE_NLINE",
+    "IXR_CMD_LLSC_NLINE",
+    "IXR_CMD_XRAM_DATA",
+  };
+  const char *llsc_fsm_str[] = {
+    "LLSC_IDLE",
+    "LL_DIR_LOCK",
+    "LL_DIR_HIT",
+    "LL_RSP",
+    "SC_DIR_LOCK",
+    "SC_DIR_HIT",
+    "SC_UPT_LOCK",
+    "SC_WAIT",
+    "SC_HEAP_LOCK",
+    "SC_UPT_REQ",
+    "SC_UPDATE",
+    "SC_TRT_LOCK",
+    "SC_INVAL_LOCK",
+    "SC_DIR_INVAL",
+    "SC_INVAL",
+    "SC_XRAM_SEND",
+    "SC_HEAP_ERASE",
+    "SC_HEAP_LAST",
+    "SC_RSP_FALSE",
+    "SC_RSP_TRUE",
+    "LLSC_TRT_LOCK",
+    "LLSC_TRT_SET",
+    "LLSC_XRAM_REQ",
+  };
+  const char *cleanup_fsm_str[] = {
+    "CLEANUP_IDLE",
+    "CLEANUP_DIR_LOCK",
+    "CLEANUP_DIR_WRITE",
+    "CLEANUP_HEAP_LOCK",
+    "CLEANUP_HEAP_SEARCH",
+    "CLEANUP_HEAP_CLEAN",
+    "CLEANUP_HEAP_FREE",
+    "CLEANUP_UPT_LOCK",
+    "CLEANUP_UPT_WRITE",
+    "CLEANUP_WRITE_RSP",
+    "CLEANUP_RSP",
+  };
+  const char *alloc_dir_fsm_str[] = {
+    "ALLOC_DIR_READ",
+    "ALLOC_DIR_WRITE",
+    "ALLOC_DIR_LLSC",
+    "ALLOC_DIR_CLEANUP",
+    "ALLOC_DIR_XRAM_RSP",
+  };
+  const char *alloc_trt_fsm_str[] = {
+    "ALLOC_TRT_READ",
+    "ALLOC_TRT_WRITE",
+    "ALLOC_TRT_LLSC",
+    "ALLOC_TRT_XRAM_RSP",
+    "ALLOC_TRT_IXR_RSP",
+  };
+  const char *alloc_upt_fsm_str[] = {
+    "ALLOC_UPT_WRITE",
+    "ALLOC_UPT_XRAM_RSP",
+    "ALLOC_UPT_INIT_RSP",
+    "ALLOC_UPT_CLEANUP",
+  };
+  const char *alloc_heap_fsm_str[] = {
+    "ALLOC_HEAP_READ",
+    "ALLOC_HEAP_WRITE",
+    "ALLOC_HEAP_LLSC",
+    "ALLOC_HEAP_CLEANUP",
+    "ALLOC_HEAP_XRAM_RSP",
+  };
+
+#endif
+
+#define tmpl(x) template<typename vci_param> x VciMemCacheV3<vci_param>
+
+  using soclib::common::uint32_log2;
+
+  ////////////////////////////////
+  // 	Constructor 
+  ////////////////////////////////
+
+  tmpl(/**/)::VciMemCacheV3( 
+      sc_module_name name,
+      const soclib::common::MappingTable &mtp,
+      const soclib::common::MappingTable &mtc,
+      const soclib::common::MappingTable &mtx,
+      const soclib::common::IntTab &vci_ixr_index,
+      const soclib::common::IntTab &vci_ini_index,
+      const soclib::common::IntTab &vci_tgt_index,
+      const soclib::common::IntTab &vci_tgt_index_cleanup,
+      size_t nways,
+      size_t nsets,
+      size_t nwords,
+      size_t heap_size)
+
+    : soclib::caba::BaseModule(name),
+
+    p_clk("clk"),
+    p_resetn("resetn"),
+    p_vci_tgt("vci_tgt"),
+    p_vci_tgt_cleanup("vci_tgt_cleanup"),
+    p_vci_ini("vci_ini"),
+    p_vci_ixr("vci_ixr"),
+
+    m_initiators( 1 << vci_param::S ),
+    m_heap_size( heap_size ),
+    m_ways( nways ),
+    m_sets( nsets ),
+    m_words( nwords ),
+    m_srcid_ixr( mtx.indexForId(vci_ixr_index) ),
+    m_srcid_ini( mtc.indexForId(vci_ini_index) ),
+    m_seglist(mtp.getSegmentList(vci_tgt_index)),
+    m_cseglist(mtc.getSegmentList(vci_tgt_index_cleanup)),
+    m_coherence_table( mtc.getCoherenceTable<vci_addr_t>() ),
+    m_atomic_tab( m_initiators ),
+    m_transaction_tab( TRANSACTION_TAB_LINES, nwords ),
+    m_update_tab( UPDATE_TAB_LINES ),
+    m_cache_directory( nways, nsets, nwords, vci_param::N ),
+    m_heap_directory( m_heap_size ),
+#define L2 soclib::common::uint32_log2
+    m_x( L2(m_words), 2),
+    m_y( L2(m_sets), L2(m_words) + 2),
+    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
+    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
+#undef L2
+
+    //  FIFOs 
+    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
+    m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
+    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
+    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
+    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
+
+    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
+    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
+    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
+    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
+    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
+    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
+    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
+
+    m_cmd_llsc_addr_fifo("m_cmd_llsc_addr_fifo",4),
+    m_cmd_llsc_sc_fifo("m_cmd_llsc_sc_fifo",4),
+    m_cmd_llsc_srcid_fifo("m_cmd_llsc_srcid_fifo",4),
+    m_cmd_llsc_trdid_fifo("m_cmd_llsc_trdid_fifo",4),
+    m_cmd_llsc_pktid_fifo("m_cmd_llsc_pktid_fifo",4),
+    m_cmd_llsc_wdata_fifo("m_cmd_llsc_wdata_fifo",4),
+
+    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
+    
+    nseg(0),	
+
+    r_read_fsm("r_read_fsm"),
+    r_write_fsm("r_write_fsm"),
+    m_write_to_init_cmd_inst_fifo("m_write_to_init_cmd_inst_fifo",8),
+    m_write_to_init_cmd_srcid_fifo("m_write_to_init_cmd_srcid_fifo",8),
+    r_init_rsp_fsm("r_init_rsp_fsm"),
+    r_cleanup_fsm("r_cleanup_fsm"),
+    r_llsc_fsm("r_llsc_fsm"),
+    m_llsc_to_init_cmd_inst_fifo("m_llsc_to_init_cmd_inst_fifo",8),
+    m_llsc_to_init_cmd_srcid_fifo("m_llsc_to_init_cmd_srcid_fifo",8),
+    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
+    r_xram_rsp_fsm("r_xram_rsp_fsm"),
+    m_xram_rsp_to_init_cmd_inst_fifo("m_xram_rsp_to_init_cmd_inst_fifo",8),
+    m_xram_rsp_to_init_cmd_srcid_fifo("m_xram_rsp_to_init_cmd_srcid_fifo",8),
+    r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
+    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
+    r_init_cmd_fsm("r_init_cmd_fsm"),
+    r_alloc_dir_fsm("r_alloc_dir_fsm"),
+    r_alloc_trt_fsm("r_alloc_trt_fsm"),
+    r_alloc_upt_fsm("r_alloc_upt_fsm")
+    {
+      assert(IS_POW_OF_2(nsets));
+      assert(IS_POW_OF_2(nwords));
+      assert(IS_POW_OF_2(nways));
+      assert(nsets);
+      assert(nwords);
+      assert(nways);
+      assert(nsets <= 1024);
+      assert(nwords <= 32);
+      assert(nways <= 32);
+
+
+      // Get the segments associated to the MemCache 
+      std::list<soclib::common::Segment>::iterator seg;
+
+      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
+        nseg++;
+      }
+      for(seg = m_cseglist.begin(); seg != m_cseglist.end() ; seg++) {
+        ncseg++;
+      }
+
+      m_seg = new soclib::common::Segment*[nseg];
+      size_t i = 0;
+      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) { 
+        m_seg[i] = &(*seg);
+        i++;
+      }
+      m_cseg = new soclib::common::Segment*[ncseg];
+      i = 0;
+      for ( seg = m_cseglist.begin() ; seg != m_cseglist.end() ; seg++ ) { 
+          m_cseg[i] = &(*seg);
+          i++;
+      }
+
+      // Memory cache allocation & initialisation
+      m_cache_data = new data_t**[nways];
+      for ( size_t i=0 ; i<nways ; ++i ) {
+        m_cache_data[i] = new data_t*[nsets];
+      }
+      for ( size_t i=0; i<nways; ++i ) {
+        for ( size_t j=0; j<nsets; ++j ) {
+          m_cache_data[i][j] = new data_t[nwords];
+          for ( size_t k=0; k<nwords; k++){
+            m_cache_data[i][j][k]=0;
+          }	
+        }
+      }
+
+      // Allocation for IXR_RSP FSM
+      r_ixr_rsp_to_xram_rsp_rok	    = new sc_signal<bool>[TRANSACTION_TAB_LINES];
+
+      // Allocation for XRAM_RSP FSM
+      r_xram_rsp_victim_data        = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_tgt_rsp_data    = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
+
+      // Allocation for READ FSM
+      r_read_data 			        = new sc_signal<data_t>[nwords];
+      r_read_to_tgt_rsp_data 		= new sc_signal<data_t>[nwords];
+
+      // Allocation for WRITE FSM
+      r_write_data 			        = new sc_signal<data_t>[nwords];
+      r_write_be 			        = new sc_signal<be_t>[nwords];
+      r_write_to_init_cmd_data 		= new sc_signal<data_t>[nwords];
+      r_write_to_init_cmd_we		= new sc_signal<bool>[nwords];
+      r_write_to_ixr_cmd_data	    = new sc_signal<data_t>[nwords];
+
+      // Allocation for LLSC FSM
+      r_llsc_to_ixr_cmd_data	    = new sc_signal<data_t>[nwords];
+
+
+      // Simulation
+
+      SC_METHOD(transition);
+      dont_initialize();
+      sensitive << p_clk.pos();
+
+      SC_METHOD(genMoore);
+      dont_initialize();
+      sensitive << p_clk.neg();
+
+    } // end constructor
+
+  /////////////////////////////////////////
+  // This function prints the statistics 
+  /////////////////////////////////////////
+
+  tmpl(void)::print_stats()
+  {
+    std::cout << "----------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
+      << "- READ RATE            = " << (double)m_cpt_read/m_cpt_cycles << std::endl
+      << "- READ MISS RATE       = " << (double)m_cpt_read_miss/m_cpt_read << std::endl
+      << "- WRITE RATE           = " << (double)m_cpt_write/m_cpt_cycles << std::endl
+      << "- WRITE MISS RATE      = " << (double)m_cpt_write_miss/m_cpt_write << std::endl
+      << "- WRITE BURST LENGTH   = " << (double)m_cpt_write_cells/m_cpt_write << std::endl
+      << "- UPDATE RATE          = " << (double)m_cpt_update/m_cpt_cycles << std::endl
+      << "- UPDATE ARITY         = " << (double)m_cpt_update_mult/m_cpt_update << std::endl
+      << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
+      << "- INVAL MULTICAST ARITY= " << (double)m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
+      << "- INVAL BROADCAST RATE = " << (double)m_cpt_inval_brdcast/m_cpt_cycles << std::endl
+      << "- SAVE DIRTY RATE      = " << (double)m_cpt_write_dirty/m_cpt_cycles << std::endl
+      << "- CLEANUP RATE         = " << (double)m_cpt_cleanup/m_cpt_cycles << std::endl
+      << "- LL RATE              = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
+      << "- SC RATE              = " << (double)m_cpt_sc/m_cpt_cycles << std::endl;
+  }
+
+  /////////////////////////////////
+  tmpl(/**/)::~VciMemCacheV3()
+    /////////////////////////////////
+  {
+    for(size_t i=0; i<m_ways ; i++){
+      for(size_t j=0; j<m_sets ; j++){
+        delete [] m_cache_data[i][j];
+      }
+    }
+    for(size_t i=0; i<m_ways ; i++){
+      delete [] m_cache_data[i];
+    }
+    delete [] m_cache_data;
+    delete [] m_coherence_table;
+
+    delete [] r_ixr_rsp_to_xram_rsp_rok;
+
+    delete [] r_xram_rsp_victim_data;
+    delete [] r_xram_rsp_to_tgt_rsp_data;
+    delete [] r_xram_rsp_to_ixr_cmd_data;
+
+    delete [] r_read_data;
+    delete [] r_read_to_tgt_rsp_data;
+
+    delete [] r_write_data;
+    delete [] r_write_be;
+    delete [] r_write_to_init_cmd_data;
+  }
+
+  //////////////////////////////////
+  tmpl(void)::transition()
+    //////////////////////////////////
+  {
+    using soclib::common::uint32_log2;
+    //  RESET          
+    if ( ! p_resetn.read() ) {
+
+      //     Initializing FSMs
+      r_tgt_cmd_fsm 	= TGT_CMD_IDLE;
+      r_tgt_rsp_fsm 	= TGT_RSP_READ_IDLE;
+      r_init_cmd_fsm 	= INIT_CMD_INVAL_IDLE;
+      r_init_rsp_fsm 	= INIT_RSP_IDLE;
+      r_read_fsm 	= READ_IDLE;
+      r_write_fsm 	= WRITE_IDLE;
+      r_llsc_fsm 	= LLSC_IDLE;
+      r_cleanup_fsm 	= CLEANUP_IDLE;
+      r_alloc_dir_fsm   = ALLOC_DIR_READ;
+      r_alloc_trt_fsm   = ALLOC_TRT_READ;
+      r_alloc_upt_fsm   = ALLOC_UPT_WRITE;
+      r_ixr_rsp_fsm 	= IXR_RSP_IDLE;
+      r_xram_rsp_fsm 	= XRAM_RSP_IDLE;
+      r_ixr_cmd_fsm 	= IXR_CMD_READ_IDLE;
+
+      //  Initializing Tables
+      m_cache_directory.init();
+      m_atomic_tab.init();	
+      m_transaction_tab.init();
+      m_heap_directory.init();
+
+      // initializing FIFOs and communication Buffers
+
+      m_cmd_read_addr_fifo.init();
+      m_cmd_read_length_fifo.init();
+      m_cmd_read_srcid_fifo.init();
+      m_cmd_read_trdid_fifo.init();
+      m_cmd_read_pktid_fifo.init();
+
+      m_cmd_write_addr_fifo.init();
+      m_cmd_write_eop_fifo.init();
+      m_cmd_write_srcid_fifo.init();
+      m_cmd_write_trdid_fifo.init();
+      m_cmd_write_pktid_fifo.init();
+      m_cmd_write_data_fifo.init();
+
+      m_cmd_llsc_addr_fifo.init();
+      m_cmd_llsc_srcid_fifo.init();
+      m_cmd_llsc_trdid_fifo.init();
+      m_cmd_llsc_pktid_fifo.init();
+      m_cmd_llsc_wdata_fifo.init();
+      m_cmd_llsc_sc_fifo.init();
+
+      r_read_to_tgt_rsp_req	    = false;
+      r_read_to_ixr_cmd_req	    = false;
+
+      r_write_to_tgt_rsp_req	        = false;
+      r_write_to_ixr_cmd_req	        = false;
+      r_write_to_init_cmd_multi_req	    = false;
+      r_write_to_init_cmd_brdcast_req	= false;
+      r_write_to_init_rsp_req           = false;
+      m_write_to_init_cmd_inst_fifo.init();
+      m_write_to_init_cmd_srcid_fifo.init();
+
+      r_cleanup_to_tgt_rsp_req	= false;
+
+      r_init_rsp_to_tgt_rsp_req	= false;
+
+      r_llsc_to_tgt_rsp_req	            = false;
+      r_llsc_to_ixr_cmd_req	            = false;
+      r_llsc_to_init_cmd_multi_req	    = false;
+      r_llsc_to_init_cmd_brdcast_req	= false;
+      m_llsc_to_init_cmd_inst_fifo.init();
+      m_llsc_to_init_cmd_srcid_fifo.init();
+
+      for(size_t i=0; i<TRANSACTION_TAB_LINES ; i++){
+        r_ixr_rsp_to_xram_rsp_rok[i] = false;
+      }
+
+      r_xram_rsp_to_tgt_rsp_req	            = false;
+      r_xram_rsp_to_init_cmd_multi_req      = false;
+      r_xram_rsp_to_init_cmd_brdcast_req    = false;
+      r_xram_rsp_to_ixr_cmd_req	            = false;
+      r_xram_rsp_trt_index	                = 0;
+      m_xram_rsp_to_init_cmd_inst_fifo.init();
+      m_xram_rsp_to_init_cmd_srcid_fifo.init();
+
+      r_ixr_cmd_cpt         = 0;
+
+      r_copies_limit        = 3;
+
+      // Activity counters
+      m_cpt_cycles		    = 0;
+      m_cpt_read		    = 0;
+      m_cpt_read_miss	    = 0;
+      m_cpt_write		    = 0;
+      m_cpt_write_miss	    = 0;
+      m_cpt_write_cells	    = 0;
+      m_cpt_write_dirty	    = 0;
+      m_cpt_update		    = 0;
+      m_cpt_update_mult     = 0;
+      m_cpt_inval_brdcast 	= 0;
+      m_cpt_inval 		    = 0;
+      m_cpt_inval_mult 		= 0;
+      m_cpt_cleanup		    = 0;
+      m_cpt_ll     		    = 0;
+      m_cpt_sc     		    = 0;
+
+      return;
+    }
+
+    bool    cmd_read_fifo_put = false;
+    bool    cmd_read_fifo_get = false;
+
+    bool    cmd_write_fifo_put = false;
+    bool    cmd_write_fifo_get = false;
+
+    bool    cmd_llsc_fifo_put = false;
+    bool    cmd_llsc_fifo_get = false;
+
+    bool    write_to_init_cmd_fifo_put   = false;
+    bool    write_to_init_cmd_fifo_get   = false;
+    bool    write_to_init_cmd_fifo_inst  = false;
+    size_t  write_to_init_cmd_fifo_srcid = 0;
+
+    bool    xram_rsp_to_init_cmd_fifo_put   = false;
+    bool    xram_rsp_to_init_cmd_fifo_get   = false;
+    bool    xram_rsp_to_init_cmd_fifo_inst  = false;
+    size_t  xram_rsp_to_init_cmd_fifo_srcid = 0;
+
+    bool    llsc_to_init_cmd_fifo_put   = false;
+    bool    llsc_to_init_cmd_fifo_get   = false;
+    bool    llsc_to_init_cmd_fifo_inst  = false;
+    size_t  llsc_to_init_cmd_fifo_srcid = 0;
+
+#if DEBUG_VCI_MEM_CACHE 
+    std::cout << "---------------------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
+      << " - TGT_CMD FSM    = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
+      << " - TGT_RSP FSM    = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
+      << " - INIT_CMD FSM   = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
+      << " - INIT_RSP FSM   = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
+      << " - READ FSM       = " << read_fsm_str[r_read_fsm] << std::endl
+      << " - WRITE FSM      = " << write_fsm_str[r_write_fsm] << std::endl
+      << " - LLSC FSM       = " << llsc_fsm_str[r_llsc_fsm] << std::endl
+      << " - CLEANUP FSM    = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
+      << " - IXR_CMD FSM    = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
+      << " - IXR_RSP FSM    = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
+      << " - XRAM_RSP FSM   = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
+      << " - ALLOC_DIR FSM  = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
+      << " - ALLOC_TRT FSM  = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
+      << " - ALLOC_UPT FSM  = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl
+      << " - ALLOC_HEAP FSM = " << alloc_heap_fsm_str[r_alloc_heap_fsm] << std::endl;
+#endif
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
+    //
+    // There is 4 types of packets for the m_mem_segment :
+    // - READ    : a READ request has a length of 1 VCI cell. It can be a single word 
+    //             or an entire cache line, depending on the PLEN value.
+    // - WRITE   : a WRITE request has a maximum length of 16 cells, and can only
+    //             concern words in a same line.
+    // - LL      : The LL request has a length of 1 cell.
+    // - SC      : The SC request has a length of 1 cell. 
+    //             The WDATA field contains the data to write.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_cmd_fsm.read() ) {
+
+      //////////////////
+      case TGT_CMD_IDLE:
+        {
+          if ( p_vci_tgt.cmdval ) {
+            assert( (p_vci_tgt.srcid.read() < m_initiators)
+                && "VCI_MEM_CACHE error in VCI_MEM_CACHE : The received SRCID is larger than the number of initiators");
+
+            bool reached = false;
+            for ( size_t index = 0 ; index < nseg && !reached ; index++) 
+            {
+//              if ( m_seg[index]->contains((addr_t)(p_vci_tgt.address.read())) ) {
+              if ( m_seg[index]->contains(p_vci_tgt.address.read()) ) {
+                reached = true;
+                r_index = index;
+              }
+            }
+
+
+            if ( !reached ) 
+            { 
+              std::cout << "VCI_MEM_CACHE Out of segment access in VCI_MEM_CACHE" << std::endl;
+              std::cout << "Faulty address = " << std::hex << (addr_t)(p_vci_tgt.address.read()) << std::endl;
+              std::cout << "Faulty initiator = " << std::dec << p_vci_tgt.srcid.read() << std::endl;
+              exit(0);
+            } 
+            else if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_READ;
+            } 
+            else if ( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE )
+            {  
+              r_tgt_cmd_fsm = TGT_CMD_WRITE;
+            } 
+            else if ((p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ) || 
+                (p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND) ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
+            } 
+          }
+          break;
+        }
+        //////////////////
+      case TGT_CMD_READ:
+
+        {
+          assert(((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2))<=16)
+              && "VCI_MEM_CACHE All read request to the MemCache must stay within a cache line"); 
+
+          if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) {
+            cmd_read_fifo_put = true;
+            if ( p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+            else                  r_tgt_cmd_fsm = TGT_CMD_READ_EOP;		
+          } 
+          break;
+        }
+        //////////////////////
+      case TGT_CMD_READ_EOP:
+        {
+          if ( p_vci_tgt.cmdval && p_vci_tgt.eop ){
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_CMD_WRITE:
+        {
+
+          if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() ) {
+            cmd_write_fifo_put = true;
+            if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+
+          }
+          break;
+        }
+        ////////////////////
+      case TGT_CMD_ATOMIC:
+        {
+          assert(p_vci_tgt.eop && "Memory Cache Error: LL or SC command with length > 1 ");
+
+          if ( p_vci_tgt.cmdval && m_cmd_llsc_addr_fifo.wok() ) {
+            cmd_llsc_fifo_put = true;
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+    } // end switch tgt_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////////
+    //		INIT_RSP FSM
+    /////////////////////////////////////////////////////////////////////////
+    // This FSM controls the response to the update or invalidate requests
+    // sent by the memory cache to the L1 caches :
+    //
+    // - update request initiated by the WRITE FSM.  
+    //   The FSM decrements the proper entry in the Update/Inval Table.
+    //   It sends a request to the TGT_RSP FSM to complete the pending 
+    //   write transaction (acknowledge response to the writer processor), 
+    //   and clear the UPT entry when all responses have been received.  
+    // - invalidate request initiated by the XRAM_RSP FSM.
+    //   The FSM decrements the proper entry in the Update/Inval_Table,
+    //   and clear the entry when all responses have been received.
+    //
+    // All those response packets are one word, compact
+    // packets complying with the VCI advanced format. 
+    // The index in the Table is defined in the RTRDID field, and
+    // the Transaction type is defined in the Update/Inval Table.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_rsp_fsm.read() ) {
+
+      ///////////////////
+      case INIT_RSP_IDLE:
+        {
+
+          if ( p_vci_ini.rspval ) {
+
+            assert ( ( p_vci_ini.rtrdid.read() < m_update_tab.size() )
+                && "VCI_MEM_CACHE UPT index too large in VCI response paquet received by memory cache" );
+            assert ( p_vci_ini.reop 
+                && "VCI_MEM_CACHE All response packets to update/invalidate requests must be one cell" );
+            r_init_rsp_upt_index = p_vci_ini.rtrdid.read(); 
+            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
+          } else if( r_write_to_init_rsp_req.read() ){
+            r_init_rsp_upt_index = r_write_to_init_rsp_upt_index.read();
+            r_write_to_init_rsp_req = false;
+            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_RSP_UPT_LOCK:	// decrement the number of expected responses
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) { 
+            size_t count = 0;
+            bool valid  = m_update_tab.decrement(r_init_rsp_upt_index.read(), count);
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+#endif
+            assert ( valid 
+                && "VCI_MEM_CACHE Invalid UPT entry in VCI response paquet received by memory cache" );
+
+            if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
+            else              r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_RSP_UPT_CLEAR:	// clear the UPT entry
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) {
+            r_init_rsp_srcid = m_update_tab.srcid(r_init_rsp_upt_index.read());
+            r_init_rsp_trdid = m_update_tab.trdid(r_init_rsp_upt_index.read());
+            r_init_rsp_pktid = m_update_tab.pktid(r_init_rsp_upt_index.read());
+            r_init_rsp_nline = m_update_tab.nline(r_init_rsp_upt_index.read());
+            bool need_rsp = m_update_tab.need_rsp(r_init_rsp_upt_index.read());
+            if ( need_rsp ) r_init_rsp_fsm = INIT_RSP_END;
+            else            r_init_rsp_fsm = INIT_RSP_IDLE;
+            m_update_tab.clear(r_init_rsp_upt_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_CLEAR update table : " << std::endl;
+	m_update_tab.print();
+#endif
+          }
+          break;
+        }
+        //////////////////
+      case INIT_RSP_END:
+        {
+
+          if ( !r_init_rsp_to_tgt_rsp_req ) {
+            r_init_rsp_to_tgt_rsp_req = true;
+            r_init_rsp_to_tgt_rsp_srcid = r_init_rsp_srcid.read();
+            r_init_rsp_to_tgt_rsp_trdid = r_init_rsp_trdid.read();
+            r_init_rsp_to_tgt_rsp_pktid = r_init_rsp_pktid.read();
+            r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+    } // end switch r_init_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		READ FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The READ FSM controls the read requests sent by processors.
+    // It takes the lock protecting the cache directory to check the cache line status:
+    // - In case of HIT, the fsm copies the data (one line, or one single word)
+    //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
+    //   The requesting initiator is registered in the cache directory.
+    // - In case of MISS, the READ fsm takes the lock protecting the transaction tab.
+    //   If a read transaction to the XRAM for this line already exists,
+    //   or if the transaction tab is full, the fsm is stalled.
+    //   If a transaction entry is free, the READ fsm sends a request to the XRAM.
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_read_fsm.read() ) {
+
+      ///////////////
+      case READ_IDLE:
+        {
+          if (m_cmd_read_addr_fifo.rok()) {
+            m_cpt_read++;
+            r_read_fsm = READ_DIR_LOCK;
+          }
+          break;
+        }
+        ///////////////////
+      case READ_DIR_LOCK:	// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            size_t way = 0;
+            DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
+#ifdef DDEBUG
+	   std::cout << "In READ_DIR_LOCK printing the entry of address is : " << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            r_read_is_cnt   = entry.is_cnt;
+            r_read_dirty    = entry.dirty;
+            r_read_lock	    = entry.lock;
+            r_read_inst     = entry.inst;
+            r_read_tag	    = entry.tag;
+            r_read_way	    = way;
+            r_read_count    = entry.count;
+            r_read_copy     = entry.owner.srcid; 
+            r_read_copy_inst= entry.owner.inst;
+            r_read_ptr      = entry.ptr;
+
+            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
+            // In case of hit, the read acces must be registered in the copies bit-vector
+            if(  entry.valid ) {
+              if(entry.is_cnt || (entry.count == 0) || !cached_read)  { // No new entry in the heap
+                r_read_fsm = READ_DIR_HIT;
+              } else {
+                r_read_fsm = READ_HEAP_LOCK;
+              }
+            } else {
+              r_read_fsm = READ_TRT_LOCK;
+              m_cpt_read_miss++;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_DIR_HIT:	// read hit : update the memory cache
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            // signals generation
+            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
+            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
+            bool is_cnt = r_read_is_cnt.read();
+
+            // read data in the cache
+            size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            size_t way = r_read_way.read();
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_data[i] = m_cache_data[way][set][i];
+            }
+
+            // update the cache directory (for the copies)
+            DirectoryEntry entry;
+            entry.valid	  = true;
+            entry.is_cnt  = is_cnt; 
+            entry.dirty	  = r_read_dirty.read();
+            entry.tag	  = r_read_tag.read();
+            entry.lock	  = r_read_lock.read();
+            entry.ptr     = 0;
+            if(cached_read){  // Cached read, we update the copy
+              if(!is_cnt){ // Not counter mode
+                entry.owner.srcid   = m_cmd_read_srcid_fifo.read();
+                entry.owner.inst    = inst_read;
+                entry.inst          = r_read_inst.read() || inst_read;
+                entry.count         = r_read_count.read() + 1;
+              } else { // Counter mode
+                entry.owner.srcid   = 0;
+                entry.owner.inst    = false;
+                entry.inst          = r_read_inst.read() || inst_read;
+                entry.count         = r_read_count.read() + 1;
+              } 
+            } else { // Uncached read
+              entry.owner.srcid     = r_read_copy.read();
+              entry.owner.inst      = r_read_copy_inst.read();
+              entry.inst            = r_read_inst.read();
+              entry.count           = r_read_count.read();
+            }
+#ifdef DDEBUG
+	   std::cout << "In READ_DIR_HIT printing the entry of address is : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            m_cache_directory.write(set, way, entry);
+            r_read_fsm    = READ_RSP;
+          }
+          break;
+        }
+        //////////////
+      case READ_HEAP_LOCK:
+        {
+          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ ) {
+            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
+            bool is_cnt = (r_read_count.read() >= r_copies_limit.read()) || m_heap_directory.is_full();
+            // read data in the cache
+            size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            size_t way = r_read_way.read();
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_data[i] = m_cache_data[way][set][i];
+            }
+
+            // update the cache directory (for the copies)
+            DirectoryEntry entry;
+            entry.valid	  = true;
+            entry.is_cnt  = is_cnt; // when we reach the limit of copies or the heap is full
+            entry.dirty	  = r_read_dirty.read();
+            entry.tag	  = r_read_tag.read();
+            entry.lock	  = r_read_lock.read();
+            if(!is_cnt){ // Not counter mode
+                entry.owner.srcid   = r_read_copy.read();
+                entry.owner.inst    = r_read_copy_inst.read();
+                entry.inst          = r_read_inst.read() || inst_read;
+                entry.count         = r_read_count.read() + 1;
+                entry.ptr           = m_heap_directory.next_free_ptr();
+            } else { // Counter mode
+                entry.owner.srcid   = 0;
+                entry.owner.inst    = false;
+                entry.inst          = r_read_inst.read() || inst_read;
+                entry.count         = r_read_count.read() + 1;
+                entry.ptr           = 0;
+            }
+#ifdef DDEBUG
+	   std::cout << "In READ_HEAP_LOCK printing the entry of address is : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            m_cache_directory.write(set, way, entry);
+
+            if(!is_cnt){
+              HeapEntry free_heap_entry = m_heap_directory.next_free_entry();
+              r_read_next_ptr = free_heap_entry.next;
+              if( free_heap_entry.next == m_heap_directory.next_free_ptr() ) { // Last free heap entry
+                r_read_last_free = true;
+              } else {
+                r_read_last_free = false;
+              }
+              r_read_fsm = READ_HEAP_WRITE; // we add an entry in the list of copies
+            } else {
+              if(r_read_count.read()>1) { // else there is no list of copies...
+                HeapEntry next_entry = m_heap_directory.read(r_read_ptr.read());
+                r_read_next_ptr = m_heap_directory.next_free_ptr();
+                m_heap_directory.write_free_ptr(r_read_ptr.read());
+                if( next_entry.next == r_read_ptr.read() ) { // The last list member
+                  r_read_fsm = READ_HEAP_LAST; // we erase the list of copies (counter mode)
+                } else { // Not the end of the list
+                  r_read_ptr = next_entry.next;
+                  r_read_fsm = READ_HEAP_ERASE; // we erase the list of copies (counter mode)
+                }
+              } else {
+                r_read_fsm = READ_RSP;
+              }
+            }
+          }
+          break;
+        }
+        //////////////
+      case READ_HEAP_WRITE:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
+            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
+            HeapEntry new_heap_entry;
+            new_heap_entry.owner.srcid  = m_cmd_read_srcid_fifo.read();
+            new_heap_entry.owner.inst   = inst_read;
+            if(r_read_count.read() == 1){ // creation of a new list
+              new_heap_entry.next         = m_heap_directory.next_free_ptr(); 
+            } else {                      // it is an insertion
+              new_heap_entry.next         = r_read_ptr.read();
+            }
+            m_heap_directory.write_free_entry(new_heap_entry);
+            m_heap_directory.write_free_ptr(r_read_next_ptr.read());
+            if(r_read_last_free.read()) {
+              m_heap_directory.set_full();
+            }
+
+            r_read_fsm = READ_RSP;
+          } else {
+            assert(false && "MEMCACHE Error : Bad HEAP allocation");
+          }
+          break;
+        }
+        //////////////
+      case READ_HEAP_ERASE:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
+            HeapEntry next_entry = m_heap_directory.read(r_read_ptr.read());
+            if( next_entry.next == r_read_ptr.read() ){
+              r_read_fsm = READ_HEAP_LAST;
+            } else {
+              r_read_ptr = next_entry.next;
+              r_read_fsm = READ_HEAP_ERASE;
+            }
+          } else {
+            assert(false && "MEMCACHE Error : Bad HEAP allocation");
+          }
+          break;
+        }
+        //////////////
+      case READ_HEAP_LAST:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
+            HeapEntry last_entry;
+            last_entry.owner.srcid = 0;
+            last_entry.owner.inst  = false;
+            if(m_heap_directory.is_full()){
+              last_entry.next      = r_read_ptr.read();
+              m_heap_directory.unset_full();
+            } else {
+              last_entry.next      = r_read_next_ptr.read();
+            }
+            m_heap_directory.write(r_read_ptr.read(),last_entry);
+            r_read_fsm = READ_RSP;
+          } else {
+            assert(false && "MEMCACHE Error : Bad HEAP allocation");
+          }
+          break;
+        }
+        //////////////
+      case READ_RSP: 		//  request the TGT_RSP FSM to return data
+        {
+          if( !r_read_to_tgt_rsp_req ) {	
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_to_tgt_rsp_data[i] = r_read_data[i];
+            }
+            r_read_to_tgt_rsp_word   = m_x[(vci_addr_t)m_cmd_read_addr_fifo.read()];
+            r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
+            cmd_read_fifo_get 		 = true;
+            r_read_to_tgt_rsp_req	 = true;
+            r_read_to_tgt_rsp_srcid	 = m_cmd_read_srcid_fifo.read();
+            r_read_to_tgt_rsp_trdid	 = m_cmd_read_trdid_fifo.read();
+            r_read_to_tgt_rsp_pktid	 = m_cmd_read_pktid_fifo.read();
+            r_read_fsm 			     = READ_IDLE;  
+          }
+          break;
+        }
+        ///////////////////
+      case READ_TRT_LOCK:	// read miss : check the Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t index = 0;
+            bool   hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())], index);
+            bool   hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())]);
+            bool   wok = !m_transaction_tab.full(index);
+            if( hit_read || !wok || hit_write ) {  // missing line already requested or no space
+              r_read_fsm = READ_IDLE;
+            } else {			   // missing line is requested to the XRAM
+              r_read_trt_index = index;
+              r_read_fsm       = READ_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_TRT_SET:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+            m_transaction_tab.set(r_read_trt_index.read(),
+                true,
+                m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
+                m_cmd_read_srcid_fifo.read(),
+                m_cmd_read_trdid_fifo.read(),
+                m_cmd_read_pktid_fifo.read(),
+                true,
+                m_cmd_read_length_fifo.read(),
+                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));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_read_fsm 	 = READ_XRAM_REQ;
+          }
+          break;
+        }
+        /////////////////////
+      case READ_XRAM_REQ:
+        {
+          if( !r_read_to_ixr_cmd_req ) {
+            cmd_read_fifo_get		= true;
+            r_read_to_ixr_cmd_req  	= true;
+            r_read_to_ixr_cmd_nline 	= m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            r_read_to_ixr_cmd_trdid 	= r_read_trt_index.read();
+            r_read_fsm 			          = READ_IDLE;
+          }
+          break;
+        }
+    } // end switch read_fsm
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //		WRITE FSM
+    ///////////////////////////////////////////////////////////////////////////////////
+    // The WRITE FSM handles the write bursts 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.
+    // Then the FSM takes the lock protecting the cache directory, to check
+    // if the line is in the cache.
+    //
+    // - In case of HIT, the cache is updated.
+    //   If there is no other copy, an acknowledge response is immediately
+    //   returned to the writing processor.
+    //   if the data is cached by other processoris, the FSM takes the lock
+    //   protecting the Update Table (UPT) to register this update transaction.
+    //   If the UPT is full, it releases the lock  and waits. Then, it sends 
+    //   a multi-update request to all owners of the line (but the writer), 
+    //   through the INIT_CMD FSM. In case of multi-update transaction, the WRITE FSM 
+    //   does not respond to the writing processor, as this response will be sent by 
+    //   the INIT_RSP FSM when all update responses have been received.
+    //
+    // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
+    //   table (TRT). If a read transaction to the XRAM for this line already exists, 
+    //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free, 
+    //   the WRITE FSM register a new transaction in TRT, and sends a read line request 
+    //   to the XRAM. If the TRT is full, it releases the lock, and waits.
+    //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_write_fsm.read() ) {
+
+      ////////////////
+      case WRITE_IDLE:	// copy first word of a write burst in local buffer	
+        {
+          if ( m_cmd_write_addr_fifo.rok()) {
+            m_cpt_write++;
+            m_cpt_write_cells++;
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get	= true;
+            size_t 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();
+            r_write_srcid	    = m_cmd_write_srcid_fifo.read();
+            r_write_trdid	    = m_cmd_write_trdid_fifo.read();
+            r_write_pktid	    = m_cmd_write_pktid_fifo.read();
+
+            // the be field must be set for all words 
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              if ( i == index ) r_write_be[i] = m_cmd_write_be_fifo.read();
+              else		        r_write_be[i] = 0x0;
+            }
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+                    r_write_byte=true;
+            else    r_write_byte=false;
+
+            if( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+            else                               r_write_fsm = WRITE_NEXT;
+          }
+          break;
+        }
+        ////////////////
+      case WRITE_NEXT:	// copy next word of a write burst in local buffer
+        {
+          if ( m_cmd_write_addr_fifo.rok() ) {
+            m_cpt_write_cells++;
+
+            // check that the next word is in the same cache line
+            assert( (m_nline[(vci_addr_t)(r_write_address.read())] == m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())])  
+                && "VCI_MEM_CACHE write error in vci_mem_cache : write burst over a line" );
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get=true;
+            size_t index 	        = r_write_word_index.read() + r_write_word_count.read();
+            r_write_be[index]       = m_cmd_write_be_fifo.read();
+            r_write_data[index]     = m_cmd_write_data_fifo.read();
+            r_write_word_count 	    = r_write_word_count.read() + 1;
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+              r_write_byte=true;
+            if ( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_LOCK:	// access directory to check hit/miss
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ) {
+            size_t  way = 0;
+            DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
+
+            // copy directory entry in local buffers in case of hit
+            if ( entry.valid )  {	
+              r_write_is_cnt    = entry.is_cnt;
+              r_write_lock	    = entry.lock;
+              r_write_inst      = entry.inst;
+              r_write_tag       = entry.tag;
+              r_write_copy      = entry.owner.srcid;
+              r_write_copy_inst = entry.owner.inst;
+              r_write_count     = entry.count;
+              r_write_ptr       = entry.ptr;
+              r_write_way  	    = way;
+              
+              bool owner = (entry.owner.srcid==r_write_srcid.read()) && !entry.owner.inst;
+              bool no_update = (entry.count==0) || ( owner && (entry.count==1));
+              if((entry.is_cnt && entry.count) ||
+                  entry.inst){
+                r_write_fsm      = WRITE_DIR_HIT_READ;
+              } else {
+                if(r_write_byte.read())
+                  r_write_fsm      = WRITE_DIR_HIT_READ;
+                else{ 
+                    if( no_update) r_write_fsm  = WRITE_DIR_HIT_RSP;
+                    else           r_write_fsm  = WRITE_DIR_HIT;
+                }
+              }
+            } else {
+              r_write_fsm = WRITE_TRT_LOCK;
+              m_cpt_write_miss++;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_READ:	// read the cache and complete the buffer (data, when be!=0xF)
+        {
+          // update local buffer
+          size_t set	= m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	= r_write_way.read();
+          for(size_t i=0 ; i<m_words ; i++) {
+            data_t mask      = 0;
+            if  (r_write_be[i].read() & 0x1) mask = mask | 0x000000FF;
+            if  (r_write_be[i].read() & 0x2) mask = mask | 0x0000FF00;
+            if  (r_write_be[i].read() & 0x4) mask = mask | 0x00FF0000;
+            if  (r_write_be[i].read() & 0x8) mask = mask | 0xFF000000;
+            if(r_write_be[i].read()||r_write_is_cnt.read()||r_write_inst.read()) { // complete only if mask is not null (for energy consumption)
+              r_write_data[i]  = (r_write_data[i].read() & mask) | 
+                (m_cache_data[way][set][i] & ~mask);
+            }
+          } // end for
+
+          bool owner = (r_write_copy.read()==r_write_srcid.read()) && !r_write_copy_inst.read();
+          bool no_update = (r_write_count.read()==0) || ( owner && (r_write_count.read()==1));
+          if((r_write_is_cnt.read() && r_write_count.read()) ||
+              r_write_inst.read()){
+            r_write_fsm            = WRITE_TRT_WRITE_LOCK;
+          } else {
+            if( no_update ) r_write_fsm = WRITE_DIR_HIT_RSP;
+            else            r_write_fsm = WRITE_DIR_HIT;
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT:	// update the cache (data & dirty bit)
+        {
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.dirty	    = true;
+          entry.tag	        = r_write_tag.read();
+          entry.is_cnt      = r_write_is_cnt.read();
+          entry.lock	    = r_write_lock.read();
+          entry.inst        = r_write_inst.read();
+          entry.owner.srcid = r_write_copy.read();
+          entry.owner.inst  = r_write_copy_inst.read();
+          entry.count       = r_write_count.read();
+          entry.ptr         = r_write_ptr.read();
+          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	    = r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          bool owner = (r_write_copy.read()==r_write_srcid.read()) && !r_write_copy_inst.read();
+
+          size_t count_signal   = r_write_count.read();
+          if(owner){
+            count_signal        = count_signal - 1;
+          }
+          r_write_count         = count_signal;
+          r_write_to_dec        = false;
+
+          r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_RSP:	// update the cache (data & dirty bit) no update
+        {
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.dirty	    = true;
+          entry.tag	        = r_write_tag.read();
+          entry.is_cnt      = r_write_is_cnt.read();
+          entry.lock	    = r_write_lock.read();
+          entry.inst        = r_write_inst.read();
+          entry.owner.srcid = r_write_copy.read();
+          entry.owner.inst  = r_write_copy_inst.read();
+          entry.count       = r_write_count.read();
+          entry.ptr         = r_write_ptr.read();
+          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	    = r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          bool owner = (r_write_copy.read()==r_write_srcid.read()) && !r_write_copy_inst.read();
+
+          // write data in cache
+          for(size_t i=0 ; i<m_words ; i++) {
+              if  ( r_write_be[i].read() ) {
+                  m_cache_data[way][set][i]  = r_write_data[i].read();
+              }
+          } // end for
+
+          if ( !r_write_to_tgt_rsp_req.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_fsm 		        = WRITE_IDLE;
+          } else {
+            r_write_fsm = WRITE_RSP;
+          }
+          break;
+        }
+        /////////////////////
+      case WRITE_UPT_LOCK: 	// Try to register the request in Update Table
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool        wok        = false;
+            size_t      index      = 0;
+            size_t      srcid      = r_write_srcid.read();
+            size_t      trdid      = r_write_trdid.read();
+            size_t      pktid      = r_write_pktid.read();
+            addr_t      nline      = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t      nb_copies  = r_write_count.read();
+            size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+            size_t way	    = r_write_way.read();
+
+            wok =m_update_tab.set(true,	// it's an update transaction
+                false,                  // it's not a broadcast
+                true,                   // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+            if(wok){
+              // write data in cache
+              for(size_t i=0 ; i<m_words ; i++) {
+                if  ( r_write_be[i].read() ) {
+                  m_cache_data[way][set][i]  = r_write_data[i].read();
+                }
+              } // end for
+            }
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting the Update Table and the Directory if no entry...
+            if ( wok ) r_write_fsm = WRITE_HEAP_LOCK;
+            else       r_write_fsm = WRITE_WAIT;
+          }
+          break;
+        }
+        //////////////////
+      case WRITE_HEAP_LOCK:
+        {
+          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE ){
+            r_write_fsm = WRITE_UPT_REQ;
+          }
+          break;
+        }
+        //////////////////
+      case WRITE_UPT_REQ:
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          if( !r_write_to_init_cmd_multi_req.read() && 
+              !r_write_to_init_cmd_brdcast_req.read()  ){
+            r_write_to_init_cmd_brdcast_req  = false;
+            r_write_to_init_cmd_trdid        = r_write_upt_index.read();
+            r_write_to_init_cmd_nline        = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index        = r_write_word_index.read();
+            r_write_to_init_cmd_count        = r_write_word_count.read();
+
+            for(size_t i=0; i<m_words ; i++){
+              if(r_write_be[i].read())  r_write_to_init_cmd_we[i]=true;
+              else                      r_write_to_init_cmd_we[i]=false;
+            }
+
+            size_t min = r_write_word_index.read();
+            size_t max = r_write_word_index.read() + r_write_word_count.read();
+            for (size_t i=min ; i<max ; i++) {
+              r_write_to_init_cmd_data[i] = r_write_data[i];
+            }
+            
+            if( r_write_copy.read() != r_write_srcid.read() ) {
+              // We put the first copy in the fifo
+              write_to_init_cmd_fifo_put     = true;
+              write_to_init_cmd_fifo_inst    = r_write_copy_inst.read();
+              write_to_init_cmd_fifo_srcid   = r_write_copy.read();
+              if(r_write_count.read() == 1){
+                r_write_fsm = WRITE_IDLE;
+                r_write_to_init_cmd_multi_req = true;
+              } else {
+                r_write_fsm = WRITE_UPDATE;
+              }
+            } else {
+              r_write_fsm = WRITE_UPDATE;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case WRITE_UPDATE:	// send a multi-update request to INIT_CMD fsm
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          HeapEntry entry = m_heap_directory.read(r_write_ptr.read());
+          write_to_init_cmd_fifo_inst  = entry.owner.inst;
+          write_to_init_cmd_fifo_srcid = entry.owner.srcid;
+          bool dec_upt_counter = r_write_to_dec.read();
+          if( (entry.owner.srcid != r_write_srcid.read()) || entry.owner.inst ){
+            write_to_init_cmd_fifo_put = true;
+          } else {
+            dec_upt_counter = true;
+          }
+          r_write_to_dec = dec_upt_counter;
+
+          if( m_write_to_init_cmd_inst_fifo.wok() ){
+            r_write_ptr = entry.next;
+            if( entry.next == r_write_ptr.read() ) { // last copy
+              r_write_to_init_cmd_multi_req = true;
+              if(dec_upt_counter){
+                r_write_fsm = WRITE_UPT_DEC;
+              } else {
+                r_write_fsm = WRITE_IDLE;
+              }
+            } else {
+              r_write_fsm = WRITE_UPDATE;
+            }
+          } else {
+            r_write_fsm = WRITE_UPDATE;
+          }
+          break;
+        }
+        //////////////////
+      case WRITE_UPT_DEC:
+        {
+          if(!r_write_to_init_rsp_req.read()){
+            r_write_to_init_rsp_req = true;
+            r_write_to_init_rsp_upt_index = r_write_upt_index.read();
+            r_write_fsm = WRITE_IDLE;
+          }
+          break;
+        }
+        ///////////////
+      case WRITE_RSP:		// send a request to TGT_RSP FSM to acknowledge the write
+        {
+          if ( !r_write_to_tgt_rsp_req.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_fsm 		        = WRITE_IDLE;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_LOCK:	// Miss : check Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t hit_index = 0;
+            size_t wok_index = 0;
+            bool hit_read  = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(r_write_address.read())],hit_index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(r_write_address.read())]);
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( hit_read ) {	// register the modified data in TRT 
+              r_write_trt_index = hit_index;
+              r_write_fsm       = WRITE_TRT_DATA;
+            } else if ( wok && !hit_write ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_TRT_SET;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT;
+            }
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT:	// release the lock protecting TRT
+        { 
+          r_write_fsm = WRITE_DIR_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_TRT_SET:	// register a new transaction in TRT (Write Buffer)
+        {  
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) 
+          {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) 
+            {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.set(r_write_trt_index.read(),
+                true,				// read request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                r_write_srcid.read(),
+                r_write_trdid.read(),
+                r_write_pktid.read(),
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                be_vector,
+                data_vector);
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_write_fsm = WRITE_XRAM_REQ;
+          }
+          break;
+        }  
+        ///////////////////
+      case WRITE_TRT_DATA:	// update an entry in TRT (Write Buffer)
+        { 
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.write_data_mask(r_write_trt_index.read(),
+                be_vector,
+                data_vector);
+            r_write_fsm = WRITE_RSP;
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_DATA transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_REQ:	// send a request to IXR_CMD FSM
+        {  
+
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req   = true;
+            r_write_to_ixr_cmd_write = false;
+            r_write_to_ixr_cmd_nline = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
+            r_write_fsm              = WRITE_RSP;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_WRITE_LOCK:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            size_t wok_index = 0;
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( wok ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_INVAL_LOCK;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT;
+            }
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool        wok       = false;
+            size_t      index     = 0;
+            size_t      srcid     = r_write_srcid.read();
+            size_t      trdid     = r_write_trdid.read();
+            size_t      pktid     = r_write_pktid.read();
+            addr_t	    nline     = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t      nb_copies = r_write_count.read();
+
+            wok =m_update_tab.set(false,	// it's an inval transaction
+                true,                       // it's a broadcast
+                true,                       // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_INVAL_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_write_fsm = WRITE_DIR_INVAL;
+            else       r_write_fsm = WRITE_WAIT;
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_INVAL:
+        {
+            assert(((r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) &&
+                    (r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) &&
+                    (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ))&&
+                    "MemCache ERROR : bad TRT,DIR or UPT allocation error");
+            m_transaction_tab.set(r_write_trt_index.read(),
+                false,				// write request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                0,
+                0,
+                0,
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_DIR_INVAL transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            // invalidate directory entry
+            DirectoryEntry entry;
+            entry.valid	        = false;
+            entry.dirty	        = false;
+            entry.tag	        = 0;
+            entry.is_cnt        = false;
+            entry.lock          = false;
+            entry.inst          = false;
+            entry.owner.srcid   = 0;
+            entry.owner.inst    = false;
+            entry.ptr           = 0;
+            entry.count         = 0;
+            size_t set	        = m_y[(vci_addr_t)(r_write_address.read())];
+            size_t way	        = r_write_way.read();
+            m_cache_directory.write(set, way, entry);
+
+            r_write_fsm = WRITE_INVAL;
+            break;
+        }
+        ////////////////////
+      case WRITE_INVAL:
+        {
+          if (  !r_write_to_init_cmd_multi_req.read() &&
+                !r_write_to_init_cmd_brdcast_req.read() ) {
+            r_write_to_init_cmd_multi_req   = false;
+            r_write_to_init_cmd_brdcast_req = true;
+            r_write_to_init_cmd_trdid       = r_write_upt_index.read();
+            r_write_to_init_cmd_nline       = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index       = 0;
+            r_write_to_init_cmd_count       = 0;
+
+            for(size_t i=0; i<m_words ; i++){
+              r_write_to_init_cmd_we[i]=false;
+              r_write_to_init_cmd_data[i] = 0;
+            }
+            r_write_fsm = WRITE_XRAM_SEND;
+            // all inval responses
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_SEND:
+        {
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req     = true;
+            r_write_to_ixr_cmd_write   = true;
+            r_write_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
+            for(size_t i=0; i<m_words; i++){
+              r_write_to_ixr_cmd_data[i] = r_write_data[i];
+            }
+            if(  r_write_is_cnt.read() ||
+                ((!r_write_is_cnt.read()) && (r_write_count.read()==1)) ){
+              r_write_fsm = WRITE_IDLE;
+            } else {
+              r_write_fsm = WRITE_HEAP_ERASE;
+              r_write_next_ptr = r_write_ptr.read();
+            }
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_HEAP_ERASE:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE){
+            HeapEntry next_entry = m_heap_directory.read(r_write_next_ptr.read());
+            if( next_entry.next == r_write_next_ptr.read()){
+              r_write_fsm = WRITE_HEAP_LAST;
+            } else {
+              r_write_next_ptr = next_entry.next;
+              r_write_fsm = WRITE_HEAP_ERASE;
+            }
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_HEAP_LAST:
+        {
+          assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
+                  "MemCache ERROR : bad HEAP allocation");
+          size_t free_pointer = m_heap_directory.next_free_ptr();
+
+          HeapEntry last_entry;
+          last_entry.owner.srcid = 0;
+          last_entry.owner.inst  = false;
+          if(m_heap_directory.is_full()){
+            last_entry.next     = r_write_next_ptr.read();
+            m_heap_directory.unset_full();
+          } else {
+            last_entry.next     = free_pointer;
+          }
+
+          m_heap_directory.write_free_ptr(r_write_ptr.read());
+          m_heap_directory.write(r_write_next_ptr.read(),last_entry);
+
+          r_write_fsm = WRITE_IDLE;
+          break;
+        }
+    } // end switch r_write_fsm
+
+    ///////////////////////////////////////////////////////////////////////
+    //		IXR_CMD FSM
+    ///////////////////////////////////////////////////////////////////////
+    // The IXR_CMD fsm controls the command packets to the XRAM :
+    // - It sends a single cell VCI read to the XRAM in case of MISS request
+    // posted by the READ, WRITE or LLSC FSMs : the TRDID field contains 
+    // the Transaction Tab index.
+    // The VCI response is a multi-cell packet : the N cells contain
+    // the N data words.
+    // - It sends a multi-cell VCI write when the XRAM_RSP FSM request 
+    // to save a dirty line to the XRAM. 
+    // The VCI response is a single cell packet.
+    // This FSM handles requests from the READ, WRITE, LLSC & XRAM_RSP FSMs 
+    // with a round-robin priority.
+    ////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_cmd_fsm.read() ) {
+      //////////////////////// 
+      case IXR_CMD_READ_IDLE:
+        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_WRITE_IDLE:
+        if      ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_LLSC_IDLE:
+        if      ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_XRAM_IDLE:
+        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        break;
+        /////////////////////////
+      case IXR_CMD_READ_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;		
+          r_read_to_ixr_cmd_req = false;
+        }
+        break;
+        //////////////////////////
+      case IXR_CMD_WRITE_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          if( r_write_to_ixr_cmd_write.read()){
+            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+              r_ixr_cmd_cpt = 0;
+              r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
+              r_write_to_ixr_cmd_req = false;
+            } else {
+              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+            }
+          } else {
+            r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;		
+            r_write_to_ixr_cmd_req = false;
+          }
+        }
+        break;
+        /////////////////////////
+      case IXR_CMD_LLSC_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          if( r_llsc_to_ixr_cmd_write.read()){
+            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+              r_ixr_cmd_cpt = 0;
+              r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;
+              r_llsc_to_ixr_cmd_req = false;
+            } else {
+              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+            }
+          } else {
+            r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;		
+            r_llsc_to_ixr_cmd_req = false;
+          }
+        }
+        break;
+        ////////////////////////
+      case IXR_CMD_XRAM_DATA:
+        if ( p_vci_ixr.cmdack ) {
+          if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+            r_ixr_cmd_cpt = 0;
+            r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
+            r_xram_rsp_to_ixr_cmd_req = false;
+          } else {
+            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+          }
+        }
+        break;
+
+    } // end switch r_ixr_cmd_fsm
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                IXR_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The IXR_RSP FSM receives the response packets from the XRAM,
+    // for both write transaction, and read transaction.
+    //
+    // - A response to a write request is a single-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The FSM takes the lock protecting the TRT, and the corresponding
+    // entry is erased.
+    //	
+    // - A response to a read request is a multi-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The N cells contain the N words of the cache line in the RDATA field.
+    // The FSM takes the lock protecting the TRT to store the line in the TRT
+    // (taking into account the write requests already stored in the TRT).
+    // When the line is completely written, the corresponding rok signal is set.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_rsp_fsm.read() ) {
+
+      ///////////////////
+      case IXR_RSP_IDLE:	// test if it's a read or a write transaction
+        {
+          if ( p_vci_ixr.rspval ) {
+            r_ixr_rsp_cpt   = 0;
+            r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
+            if ( p_vci_ixr.reop )  r_ixr_rsp_fsm = IXR_RSP_ACK;
+            else                   r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
+          }
+          break;  
+        }
+        ////////////////////////
+      case IXR_RSP_ACK:        // Acknowledge the vci response
+        r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
+        break;
+        ////////////////////////
+      case IXR_RSP_TRT_ERASE: 	// erase the entry in the TRT
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP ) {
+            m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
+            r_ixr_rsp_fsm = IXR_RSP_IDLE;
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_ERASE transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ///////////////////////
+      case IXR_RSP_TRT_READ:		// write data in the TRT
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval ) {
+            bool   eop  	= p_vci_ixr.reop.read();
+            data_t data 	= p_vci_ixr.rdata.read();
+            size_t index        = r_ixr_rsp_trt_index.read();
+            assert( eop == (r_ixr_rsp_cpt.read() == (m_words-1)) 
+                && "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
+            m_transaction_tab.write_rsp(index, r_ixr_rsp_cpt.read(), data);
+            r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
+            if ( eop ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_READ transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+              r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
+              r_ixr_rsp_fsm = IXR_RSP_IDLE;
+            }
+          }
+          break;
+        }
+    } // end swich r_ixr_rsp_fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                XRAM_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
+    // The cache line has been written in the TRT buffer by the IXR_FSM.
+    //
+    // When a response is available, the corresponding TRT entry 
+    // is copied in a local buffer to be written in the cache. 
+    // Then, the FSM releases the lock protecting the TRT, and takes the lock 
+    // protecting the cache directory.
+    // It selects a cache slot and writes the line in the cache.
+    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
+    // FSM to return the cache line to the registered processor.
+    // If there is no empty slot, a victim line is evicted, and
+    // invalidate requests are sent to the L1 caches containing copies.
+    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD 
+    // FSM to save the victim line to the XRAM, and register the write transaction
+    // in the TRT (using the entry previously used by the read transaction).
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_xram_rsp_fsm.read() ) {
+
+      ///////////////////
+      case XRAM_RSP_IDLE:	// test if there is a response with a round robin priority
+        {
+          size_t ptr   = r_xram_rsp_trt_index.read();
+          size_t lines = TRANSACTION_TAB_LINES;
+          for(size_t i=0; i<lines; i++){
+            size_t index=(i+ptr+1)%lines;
+            if(r_ixr_rsp_to_xram_rsp_rok[index]){
+              r_xram_rsp_trt_index=index;
+              r_ixr_rsp_to_xram_rsp_rok[index]=false;
+              r_xram_rsp_fsm           = XRAM_RSP_DIR_LOCK;
+              break;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_IDLE state" << std::endl;
+#endif
+            }
+          }
+          break;  
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_LOCK: 	// Take the lock on the directory
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) {
+            r_xram_rsp_fsm           = XRAM_RSP_TRT_COPY;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_LOCK state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_TRT_COPY:		// Copy the TRT entry in the local buffer and eviction of a cache line
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) ) {
+            size_t index = r_xram_rsp_trt_index.read();
+            TransactionTabEntry    trt_entry(m_transaction_tab.read(index));	
+
+            r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
+
+            // selects & extracts a victim line from cache
+            size_t way = 0;
+            size_t set = m_y[(vci_addr_t)(trt_entry.nline * m_words * 4)];
+            DirectoryEntry victim(m_cache_directory.select(set, way));
+
+            for (size_t i=0 ; i<m_words ; i++) r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
+
+            bool inval = (victim.count && victim.valid) ;
+
+            r_xram_rsp_victim_copy      = victim.owner.srcid;
+            r_xram_rsp_victim_copy_inst = victim.owner.inst;
+            r_xram_rsp_victim_count     = victim.count;
+            r_xram_rsp_victim_ptr       = victim.ptr;
+            r_xram_rsp_victim_way       = way;
+            r_xram_rsp_victim_set       = set;
+            r_xram_rsp_victim_nline     = victim.tag*m_sets + set;
+            r_xram_rsp_victim_is_cnt    = victim.is_cnt;
+            r_xram_rsp_victim_inval     = inval ;
+            r_xram_rsp_victim_dirty     = victim.dirty;
+
+            r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_TRT_COPY state" << std::endl;
+	std::cout << "Victim way : " << std::hex << way << " set " << std::hex << set << std::endl;
+	victim.print();
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP ) {
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state" << std::endl;
+#endif
+            size_t index;
+            if(m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index)){
+              r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+    std::cout << "A invalidation is already registered at this address" << std::endl;
+	m_update_tab.print();
+#endif
+
+            }
+	    else if(m_update_tab.is_full() && r_xram_rsp_victim_inval.read()){
+	      r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+    std::cout << "The inval tab is full" << std::endl;
+	m_update_tab.print();
+#endif
+	    }
+            else {
+              r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_DIR_UPDT state" << std::endl;
+	m_update_tab.print();
+#endif
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_WAIT:
+        {
+          r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
+          break;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_UPDT:		// updates the cache (both data & directory)
+        {
+          // signals generation
+          bool inst_read = (r_xram_rsp_trt_buf.trdid & 0x2) && r_xram_rsp_trt_buf.proc_read; // It is an instruction read
+          bool cached_read = (r_xram_rsp_trt_buf.trdid & 0x1) && r_xram_rsp_trt_buf.proc_read ;
+          // update data
+          size_t set   = r_xram_rsp_victim_set.read();
+          size_t way   = r_xram_rsp_victim_way.read();
+          for(size_t i=0; i<m_words ; i++){
+            m_cache_data[way][set][i] = r_xram_rsp_trt_buf.wdata[i];
+          }
+          // compute dirty 
+          bool dirty = false;
+          for(size_t i=0; i<m_words;i++){
+            dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
+          }
+
+          // update directory
+          DirectoryEntry entry;
+          entry.valid	  = true;
+          entry.is_cnt    = false;
+          entry.lock	  = false;
+          entry.dirty	  = dirty;
+          entry.tag	      = r_xram_rsp_trt_buf.nline / m_sets;
+          entry.ptr       = 0;
+          if(cached_read) {
+            if(inst_read) {
+              entry.inst        = true;
+              entry.owner.srcid = r_xram_rsp_trt_buf.srcid;
+              entry.owner.inst  = true;
+              entry.count       = 1;
+            } else {
+              entry.inst        = false;
+              entry.owner.srcid = r_xram_rsp_trt_buf.srcid;
+              entry.owner.inst  = false;
+              entry.count       = 1;
+            }
+          } else {
+            entry.owner.srcid = 0;
+            entry.owner.inst  = 0;
+            entry.inst        = false;
+            entry.count       = 0;
+          }
+          m_cache_directory.write(set, way, entry);
+#ifdef DDEBUG
+	   std::cout << "printing the entry : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_DIR_UPDT transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          if(r_xram_rsp_victim_inval.read()){
+            bool    brdcast = r_xram_rsp_victim_is_cnt.read();
+            size_t index;
+            size_t count_copies = r_xram_rsp_victim_count.read();
+
+            bool	 wok = m_update_tab.set(false,	// it's an inval transaction
+                brdcast,                          // set brdcast bit
+                false,  // it does not need a response
+                0,
+                0,
+                0,
+                r_xram_rsp_victim_nline.read(),
+                count_copies,
+                index);
+
+#ifdef IDEBUG
+            std::cout << "xram_rsp : record invalidation, time = " << std::dec << m_cpt_cycles << std::endl;
+            m_update_tab.print();
+#endif
+            r_xram_rsp_upt_index = index;
+            if(!wok) {
+              assert(false && "mem_cache error : xram_rsp_dir_upt, an update_tab entry was free but write unsuccessful");
+            }
+          }
+          // If the victim is not dirty, we erase the entry in the TRT
+          if      (!r_xram_rsp_victim_dirty.read()){
+	  m_transaction_tab.erase(r_xram_rsp_trt_index.read());
+
+	  }
+          // Next state
+          if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
+          else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+          else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+          else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          break;
+        }
+        ////////////////////////
+      case XRAM_RSP_TRT_DIRTY:		// set the TRT entry (write line to XRAM) if the victim is dirty
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP ) {
+            m_transaction_tab.set(r_xram_rsp_trt_index.read(),
+                false,				// write to XRAM
+                r_xram_rsp_victim_nline.read(), // line index
+                0,
+                0,
+                0,
+                false,
+                0,
+                0,
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0) );
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_TRT_DIRTY transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+          }
+          break;
+        }
+        //////////////////////
+      case XRAM_RSP_DIR_RSP:     // send a request to TGT_RSP FSM in case of read
+        {
+          if ( !r_xram_rsp_to_tgt_rsp_req.read() ) {
+            r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
+            r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
+            r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
+            for (size_t i=0; i < m_words; i++) {
+              r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
+            } 
+            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_req    = true;
+
+            if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY; 
+            else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#ifdef DDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_RSP state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ////////////////////
+      case XRAM_RSP_INVAL:	// send invalidate request to INIT_CMD FSM
+        {
+          if(   !r_xram_rsp_to_init_cmd_multi_req.read() && 
+                !r_xram_rsp_to_init_cmd_brdcast_req.read() ) {	      
+            
+            bool multi_req = !r_xram_rsp_victim_is_cnt.read();
+            bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
+            bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
+
+            r_xram_rsp_to_init_cmd_multi_req    = last_multi_req; 
+            r_xram_rsp_to_init_cmd_brdcast_req  = r_xram_rsp_victim_is_cnt.read();
+            r_xram_rsp_to_init_cmd_nline        = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_init_cmd_trdid        = r_xram_rsp_upt_index;
+            xram_rsp_to_init_cmd_fifo_srcid     = r_xram_rsp_victim_copy.read();
+            xram_rsp_to_init_cmd_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
+            xram_rsp_to_init_cmd_fifo_put       = multi_req;
+            
+            r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
+
+            if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+            else if (not_last_multi_req)    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+            else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL state" << std::endl;
+#endif
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_WRITE_DIRTY:	// send a write request to IXR_CMD FSM
+        {
+          if ( !r_xram_rsp_to_ixr_cmd_req.read() ) {
+            r_xram_rsp_to_ixr_cmd_req = true;
+            r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
+            for(size_t i=0; i<m_words ; i++) {
+              r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
+            }
+            m_cpt_write_dirty++;
+            bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
+            bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
+            if ( not_last_multi_req )   r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+            else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_WRITE_DIRTY state" << std::endl;
+#endif
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_HEAP_ERASE:	// erase the list of copies and sent invalidations
+        {
+          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP ) {
+            HeapEntry entry = m_heap_directory.read(r_xram_rsp_next_ptr.read());
+            xram_rsp_to_init_cmd_fifo_srcid = entry.owner.srcid;
+            xram_rsp_to_init_cmd_fifo_inst  = entry.owner.inst;
+            xram_rsp_to_init_cmd_fifo_put   = true;
+            if( m_xram_rsp_to_init_cmd_inst_fifo.wok() ){
+              r_xram_rsp_next_ptr = entry.next;
+              if( entry.next == r_xram_rsp_next_ptr.read() ){ // last copy
+                r_xram_rsp_to_init_cmd_multi_req = true;
+                r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
+              } else {
+                r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+              }
+            } else {
+              r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+            }
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_HEAP_LAST:	// last member of the list
+        {
+          assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP) &&
+                  "MemCache ERROR : bad HEAP allocation");
+          size_t free_pointer = m_heap_directory.next_free_ptr();
+
+          HeapEntry last_entry;
+          last_entry.owner.srcid = 0;
+          last_entry.owner.inst  = false;
+          if(m_heap_directory.is_full()){
+            last_entry.next     = r_xram_rsp_next_ptr.read();
+            m_heap_directory.unset_full();
+          } else {
+            last_entry.next     = free_pointer;
+          }
+
+          m_heap_directory.write_free_ptr(r_xram_rsp_victim_ptr.read());
+          m_heap_directory.write(r_xram_rsp_next_ptr.read(),last_entry);
+
+          r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+          break;
+        }
+    } // end swich r_xram_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		CLEANUP FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The CLEANUP FSM handles the cleanup request from L1 caches.
+    // It accesses the cache directory to update the list of copies.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+    switch ( r_cleanup_fsm.read() ) {
+
+      ///////////////////
+      case CLEANUP_IDLE:
+        {
+
+          if ( p_vci_tgt_cleanup.cmdval.read() ) {
+            assert( (p_vci_tgt_cleanup.srcid.read() < m_initiators) &&
+                "VCI_MEM_CACHE error in VCI_MEM_CACHE in the CLEANUP network : The received SRCID is larger than the number of initiators");
+            bool reached = false;
+            for ( size_t index = 0 ; index < ncseg && !reached ; index++ ){
+              if ( m_cseg[index]->contains((addr_t)(p_vci_tgt_cleanup.address.read())) ){
+                reached = true;
+              }
+            }
+            if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
+                (((addr_t)(p_vci_tgt_cleanup.address.read())) != BROADCAST_ADDR) &&
+                reached) {
+
+              m_cpt_cleanup++;
+
+              r_cleanup_nline      = (addr_t)(m_nline[(vci_addr_t)(p_vci_tgt_cleanup.address.read())]) ;
+              r_cleanup_srcid      = p_vci_tgt_cleanup.srcid.read();
+              r_cleanup_trdid      = p_vci_tgt_cleanup.trdid.read();
+              r_cleanup_pktid      = p_vci_tgt_cleanup.pktid.read();
+
+              r_cleanup_fsm        = CLEANUP_DIR_LOCK;
+            }
+          }
+          break;
+        }
+        //////////////////////
+      case CLEANUP_DIR_LOCK:
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) {
+
+            // Read the directory
+            size_t way = 0;
+	   addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
+           DirectoryEntry entry = m_cache_directory.read(cleanup_address , way);
+#ifdef DDEBUG
+	   std::cout << "In CLEANUP_DIR_LOCK printing the entry of address is : " << std::hex << cleanup_address << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+            r_cleanup_is_cnt    = entry.is_cnt;
+            r_cleanup_dirty	    = entry.dirty;
+            r_cleanup_tag	    = entry.tag;
+            r_cleanup_lock	    = entry.lock;
+            r_cleanup_inst      = entry.inst;
+            r_cleanup_way	    = way;
+            r_cleanup_copy      = entry.owner.srcid;
+            r_cleanup_copy_inst = entry.owner.inst;
+            r_cleanup_count     = entry.count;
+            r_cleanup_ptr       = entry.ptr;
+
+
+            // In case of hit, the copy must be cleaned in the copies bit-vector
+            if( entry.valid){
+              if ( (entry.count==1) || (entry.is_cnt) )  { // no access to the heap
+                r_cleanup_fsm = CLEANUP_DIR_WRITE;
+              } else {
+                r_cleanup_fsm = CLEANUP_HEAP_LOCK;
+              }
+            } else {
+              r_cleanup_fsm = CLEANUP_UPT_LOCK;
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case CLEANUP_DIR_WRITE:
+        {
+          assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) && 
+                "MemCache ERROR : Bad DIR allocation");
+          size_t way      = r_cleanup_way.read();
+#define L2 soclib::common::uint32_log2
+          size_t set      = m_y[(vci_addr_t)(r_cleanup_nline.read() << (L2(m_words) +2))];
+#undef L2
+          bool cleanup_inst  = r_cleanup_trdid.read() & 0x1; 
+          bool match_srcid   = (r_cleanup_copy.read() == r_cleanup_srcid.read());
+          bool match_inst    = (r_cleanup_copy_inst.read()  == cleanup_inst);
+          bool match         = match_srcid && match_inst;
+
+          // update the cache directory (for the copies)
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.is_cnt  = r_cleanup_is_cnt.read();
+          entry.dirty	= r_cleanup_dirty.read();
+          entry.tag	    = r_cleanup_tag.read();
+          entry.lock	= r_cleanup_lock.read();
+          entry.ptr     = r_cleanup_ptr.read();
+          if(r_cleanup_is_cnt.read()) { // Directory is a counter
+            entry.count  = r_cleanup_count.read() -1;
+            if((r_cleanup_count.read()-1) == 0){
+              entry.inst    = false;
+            } else {
+              entry.inst    = r_cleanup_inst.read();
+            }
+            entry.owner.srcid = 0;
+            entry.owner.inst  = 0;
+            // response to the cache 
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          else{                         // Directory is a list
+            if(match) { // hit
+              entry.count       = 0; // no more copy
+              entry.owner.srcid = 0;
+              entry.owner.inst  = 0;
+              entry.inst        = false;
+              r_cleanup_fsm     = CLEANUP_RSP; 
+            } else { // miss
+              entry.count       = r_cleanup_count.read();
+              entry.owner.srcid = r_cleanup_copy.read();
+              entry.owner.inst  = r_cleanup_copy_inst.read();
+              entry.inst        = r_cleanup_inst.read();
+              r_cleanup_fsm     = CLEANUP_UPT_LOCK;
+            }
+          }
+          m_cache_directory.write(set, way, entry);  
+
+          break;
+        }
+        /////////////////
+      case CLEANUP_HEAP_LOCK:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP){
+            size_t way      = r_cleanup_way.read();
+#define L2 soclib::common::uint32_log2
+            size_t set      = m_y[(vci_addr_t)(r_cleanup_nline.read() << (L2(m_words) +2))];
+#undef L2
+            HeapEntry heap_entry = m_heap_directory.read(r_cleanup_ptr.read());
+            bool last = (heap_entry.next == r_cleanup_ptr.read());
+            bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
+            bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
+            bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
+            bool match_dir          = match_dir_srcid && match_dir_inst;
+            bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+            bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
+            bool match_heap         = match_heap_srcid && match_heap_inst;
+
+            r_cleanup_prev_ptr = r_cleanup_ptr.read();
+            r_cleanup_prev_srcid = heap_entry.owner.srcid;
+            r_cleanup_prev_inst  = heap_entry.owner.inst;
+
+            if(match_dir){
+              DirectoryEntry dir_entry;
+              dir_entry.valid	    = true;
+              dir_entry.is_cnt      = r_cleanup_is_cnt.read();
+              dir_entry.dirty	    = r_cleanup_dirty.read();
+              dir_entry.tag	        = r_cleanup_tag.read();
+              dir_entry.lock	    = r_cleanup_lock.read();
+              dir_entry.ptr         = heap_entry.next;
+              dir_entry.count       = r_cleanup_count.read()-1;
+              dir_entry.owner.srcid = heap_entry.owner.srcid;
+              dir_entry.owner.inst  = heap_entry.owner.inst;
+              dir_entry.inst        = r_cleanup_inst.read();
+              m_cache_directory.write(set,way,dir_entry);
+              r_cleanup_next_ptr    = r_cleanup_ptr.read();
+              r_cleanup_fsm         = CLEANUP_HEAP_FREE;
+            }
+            else if(match_heap){
+              DirectoryEntry dir_entry;
+              dir_entry.valid	    = true;
+              dir_entry.is_cnt      = r_cleanup_is_cnt.read();
+              dir_entry.dirty	    = r_cleanup_dirty.read();
+              dir_entry.tag	        = r_cleanup_tag.read();
+              dir_entry.lock	    = r_cleanup_lock.read();
+              dir_entry.ptr         = heap_entry.next;
+              dir_entry.count       = r_cleanup_count.read()-1;
+              dir_entry.owner.srcid = r_cleanup_copy.read();
+              dir_entry.owner.inst  = r_cleanup_copy_inst.read();
+              dir_entry.inst        = r_cleanup_inst.read();
+              m_cache_directory.write(set,way,dir_entry);
+              r_cleanup_next_ptr    = r_cleanup_ptr.read();
+              r_cleanup_fsm         = CLEANUP_HEAP_FREE; 
+            }
+            else{
+              if(!last){
+                DirectoryEntry dir_entry;
+                dir_entry.valid	        = true;
+                dir_entry.is_cnt        = r_cleanup_is_cnt.read();
+                dir_entry.dirty	        = r_cleanup_dirty.read();
+                dir_entry.tag	        = r_cleanup_tag.read();
+                dir_entry.lock	        = r_cleanup_lock.read();
+                dir_entry.ptr           = r_cleanup_ptr.read();
+                dir_entry.count         = r_cleanup_count.read()-1;
+                dir_entry.owner.srcid   = r_cleanup_copy.read();
+                dir_entry.owner.inst    = r_cleanup_copy_inst.read();
+                dir_entry.inst          = r_cleanup_inst.read();
+                m_cache_directory.write(set,way,dir_entry);
+
+                r_cleanup_next_ptr = heap_entry.next;
+                r_cleanup_fsm      = CLEANUP_HEAP_SEARCH;
+
+              } else{
+                assert(false && "MemCache ERROR : CLEANUP hit but line not shared");
+              }
+            }
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_HEAP_SEARCH:
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          HeapEntry heap_entry = m_heap_directory.read(r_cleanup_next_ptr.read());
+          bool last = (heap_entry.next == r_cleanup_next_ptr.read());
+          bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
+          bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+          bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
+          bool match_heap         = match_heap_srcid && match_heap_inst;
+
+          if(match_heap){
+            r_cleanup_ptr           = heap_entry.next; // reuse ressources
+            r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
+          }
+          else{
+            if(last) {
+              assert(false && "MemCache ERROR : CLEANUP hit but line not shared");
+            } else {
+              r_cleanup_prev_ptr = r_cleanup_next_ptr.read();
+              r_cleanup_prev_srcid = heap_entry.owner.srcid;
+              r_cleanup_prev_inst  = heap_entry.owner.inst;
+              r_cleanup_next_ptr = heap_entry.next;
+              r_cleanup_fsm      = CLEANUP_HEAP_SEARCH;
+            }
+          }
+
+          break;
+        }
+        /////////////////
+      case CLEANUP_HEAP_CLEAN:
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
+          HeapEntry heap_entry; 
+          heap_entry.owner.srcid = r_cleanup_prev_srcid.read();
+          heap_entry.owner.inst  = r_cleanup_prev_inst.read();
+          if(last){ // this is the last entry of the list of copies
+            heap_entry.next     = r_cleanup_prev_ptr.read();
+          } else { // this is not the last entry
+            heap_entry.next     = r_cleanup_ptr.read();
+          }
+          m_heap_directory.write(r_cleanup_prev_ptr.read(),heap_entry);
+          r_cleanup_fsm = CLEANUP_HEAP_FREE;
+          break;
+        }
+        /////////////////
+      case CLEANUP_HEAP_FREE:
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          HeapEntry heap_entry;
+          heap_entry.owner.srcid = 0;
+          heap_entry.owner.inst  = false;
+          if(m_heap_directory.is_full()){
+            heap_entry.next     = r_cleanup_next_ptr.read();
+          } else {
+            heap_entry.next     = m_heap_directory.next_free_ptr();
+          }
+          m_heap_directory.write(r_cleanup_next_ptr.read(),heap_entry);
+          m_heap_directory.write_free_ptr(r_cleanup_next_ptr.read());
+          m_heap_directory.unset_full();
+          r_cleanup_fsm = CLEANUP_RSP;
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_LOCK:
+        {
+          if( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
+          {
+            size_t index;
+            bool hit_inval;
+            hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
+            if(!hit_inval) {
+#ifdef DEBUG_VCI_MEM_CACHE
+              std::cout << "MEM_CACHE WARNING: cleanup with no corresponding entry at address : " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::dec << std::endl;
+#endif
+              r_cleanup_fsm = CLEANUP_RSP;
+            } else {
+              r_cleanup_write_srcid = m_update_tab.srcid(index);
+              r_cleanup_write_trdid = m_update_tab.trdid(index);
+              r_cleanup_write_pktid = m_update_tab.pktid(index);
+              r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
+              r_cleanup_fsm = CLEANUP_UPT_WRITE;
+            }
+            r_cleanup_index.write(index) ; 
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_WRITE:
+        {
+          size_t count = 0;
+          m_update_tab.decrement(r_cleanup_index.read(), count); // &count
+          if(count == 0){
+            m_update_tab.clear(r_cleanup_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " CLEANUP_UPT_WRITE update table : " << std::endl;
+	m_update_tab.print();
+#endif
+
+            if(r_cleanup_need_rsp.read()){
+              r_cleanup_fsm = CLEANUP_WRITE_RSP ;
+            } else {
+              r_cleanup_fsm = CLEANUP_RSP;
+            }
+          } else {
+            r_cleanup_fsm = CLEANUP_RSP ;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_WRITE_RSP:
+        {
+          if( !r_cleanup_to_tgt_rsp_req.read()) {
+            r_cleanup_to_tgt_rsp_req     = true;
+            r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
+            r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
+            r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_RSP:
+        {
+          if(p_vci_tgt_cleanup.rspack)
+            r_cleanup_fsm = CLEANUP_IDLE;
+          break;
+        }
+    } // end switch cleanup fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		LLSC FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The LLSC FSM handles the LL & SC atomic access.
+    //
+    // For a LL :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the LL request is registered in the Atomic Table and the
+    // response is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state.
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the LL request is not consumed in the FIFO.
+    //
+    // For a SC :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the Atomic Table is checked and the proper response
+    // (true or false is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state. 
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the SC request is not consumed in the FIFO.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_llsc_fsm.read() ) {
+
+      ///////////////
+      case LLSC_IDLE:		// test LL / SC
+        {
+          if( m_cmd_llsc_addr_fifo.rok() ) {
+            if(m_cmd_llsc_sc_fifo.read()){
+              m_cpt_sc++;
+              r_llsc_fsm = SC_DIR_LOCK;
+            }
+            else{
+              m_cpt_ll++;
+              r_llsc_fsm = LL_DIR_LOCK;
+            }
+          }	
+          break;
+        }
+        /////////////////
+      case LL_DIR_LOCK:		// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+            size_t way = 0;
+            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+            r_llsc_is_cnt     = entry.is_cnt;
+            r_llsc_dirty      = entry.dirty;
+            r_llsc_inst       = entry.inst;
+            r_llsc_tag        = entry.tag;
+            r_llsc_way        = way;
+            r_llsc_copy       = entry.owner.srcid;
+            r_llsc_copy_inst  = entry.owner.inst;
+            r_llsc_count      = entry.count;
+            r_llsc_ptr        = entry.ptr;
+
+            // set Atomic Table
+            m_atomic_tab.set(m_cmd_llsc_srcid_fifo.read(), m_cmd_llsc_addr_fifo.read());
+
+            if ( entry.valid )  r_llsc_fsm = LL_DIR_HIT;
+            else                r_llsc_fsm = LLSC_TRT_LOCK;
+          }
+          break;
+        }
+        ////////////////
+      case LL_DIR_HIT:		// read hit : update the memory cache
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+
+          // update directory (lock bit & copies)
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.is_cnt      = r_llsc_is_cnt.read();
+          entry.dirty	    = r_llsc_dirty.read();
+          entry.lock	    = true;
+          entry.inst        = r_llsc_inst.read();
+          entry.tag	        = r_llsc_tag.read();
+          entry.owner.srcid = r_llsc_copy.read();
+          entry.owner.inst  = r_llsc_copy_inst.read();
+          entry.count       = r_llsc_count.read();
+          entry.ptr         = r_llsc_ptr.read();
+          m_cache_directory.write(set, way, entry);
+
+          // read data in cache
+          r_llsc_data	= m_cache_data[way][set][word];
+
+          r_llsc_fsm 	= LL_RSP;
+          break;
+        }
+        ////////////
+      case LL_RSP:		// request the TGT_RSP FSM to return data
+        {
+          if ( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_data	= r_llsc_data.read();
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_fsm = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_DIR_LOCK:
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+            size_t way = 0;
+            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+            bool ok = m_atomic_tab.isatomic(m_cmd_llsc_srcid_fifo.read(),m_cmd_llsc_addr_fifo.read());
+            if( ok ) {
+              r_llsc_is_cnt   = entry.is_cnt;
+              r_llsc_dirty    = entry.dirty;
+              r_llsc_tag      = entry.tag;
+              r_llsc_way      = way;
+              r_llsc_copy     = entry.owner.srcid;
+              r_llsc_copy_inst= entry.owner.inst;
+              r_llsc_inst     = entry.inst;
+              r_llsc_ptr      = entry.ptr;
+              r_llsc_count    = entry.count;
+              if ( entry.valid ){
+                if((entry.is_cnt && entry.count) || entry.inst) {
+                  r_llsc_fsm = SC_TRT_LOCK;
+                } else {
+                  r_llsc_fsm = SC_DIR_HIT;
+                }
+              }
+              else r_llsc_fsm = LLSC_TRT_LOCK;
+            } else {
+              r_llsc_fsm = SC_RSP_FALSE;
+            }
+          }
+          break;
+        }
+        ////////////////
+      case SC_DIR_HIT:
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+
+          // update directory (lock & dirty bits
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.is_cnt      = r_llsc_is_cnt.read();
+          entry.dirty	    = true;
+          entry.lock	    = true;
+          entry.inst        = r_llsc_inst.read();
+          entry.tag	        = r_llsc_tag.read();
+          entry.owner.srcid = r_llsc_copy.read();
+          entry.owner.inst  = r_llsc_copy_inst.read();
+          entry.count       = r_llsc_count.read();
+          entry.ptr         = r_llsc_ptr.read();
+          m_cache_directory.write(set, way, entry);
+
+          if(!r_llsc_count.read()){ // no update
+            // write data in cache
+            m_cache_data[way][set][word] = m_cmd_llsc_wdata_fifo.read();
+            // reset Atomic Table
+            m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+          }
+          
+          if(r_llsc_count.read()) {  // Shared line
+            r_llsc_fsm = SC_UPT_LOCK;
+          } else {
+            r_llsc_fsm = SC_RSP_TRUE;
+          }
+          break;
+        }
+        /////////////////////
+      case SC_UPT_LOCK: 	// Try to register the request in Update Table
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
+            size_t way	= r_llsc_way.read();
+            size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+            size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+            bool        wok        = false;
+            size_t      index      = 0;
+            size_t      srcid      = m_cmd_llsc_srcid_fifo.read();
+            size_t      trdid      = m_cmd_llsc_trdid_fifo.read();
+            size_t      pktid      = m_cmd_llsc_pktid_fifo.read();
+            addr_t	    nline      = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t      nb_copies  = r_llsc_count.read();
+
+            wok =m_update_tab.set(true,	// it's an update transaction
+                false,                  // it's not a broadcast
+                true,                   // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+            if(wok){
+              // write data in cache
+              m_cache_data[way][set][word] = m_cmd_llsc_wdata_fifo.read();
+              // reset Atomic Table
+              m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+            }
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " SC_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_llsc_upt_index = index;
+            //  releases the lock protecting the Update Table and the Directory if no entry...
+            if ( wok ) r_llsc_fsm = SC_HEAP_LOCK;
+            else       r_llsc_fsm = SC_WAIT;
+          }
+          break;
+        }
+        ////////////////////
+      case SC_WAIT: 	// release all locks
+        {
+          r_llsc_fsm = SC_DIR_LOCK;
+          break;
+        }
+        ////////////////////
+      case SC_HEAP_LOCK: 	// lock the heap
+        {
+          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC ){
+            r_llsc_fsm = SC_UPT_REQ;
+          }
+          break;
+        }
+        ////////////////////
+      case SC_UPT_REQ: 	// Request the update
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          if( !r_llsc_to_init_cmd_multi_req.read() && 
+              !r_llsc_to_init_cmd_brdcast_req.read()  ){
+            r_llsc_to_init_cmd_brdcast_req  = false;
+            r_llsc_to_init_cmd_trdid        = r_llsc_upt_index.read();
+            r_llsc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_index        = m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_wdata        = m_cmd_llsc_wdata_fifo.read();
+
+            // We put the first copy in the fifo
+            llsc_to_init_cmd_fifo_put     = true;
+            llsc_to_init_cmd_fifo_inst    = r_llsc_copy_inst.read();
+            llsc_to_init_cmd_fifo_srcid   = r_llsc_copy.read();
+            if(r_llsc_count.read() == 1){
+              r_llsc_fsm = LLSC_IDLE;
+              cmd_llsc_fifo_get            = true;
+              r_llsc_to_init_cmd_multi_req = true;
+            } else {
+              r_llsc_fsm = SC_UPDATE;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case SC_UPDATE:   	// send a multi-update request to INIT_CMD fsm
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          HeapEntry entry = m_heap_directory.read(r_llsc_ptr.read());
+          llsc_to_init_cmd_fifo_inst  = entry.owner.inst;
+          llsc_to_init_cmd_fifo_srcid = entry.owner.srcid;
+          llsc_to_init_cmd_fifo_put = true;
+
+          if( m_llsc_to_init_cmd_inst_fifo.wok() ){
+            r_llsc_ptr = entry.next;
+            if( entry.next == r_llsc_ptr.read() ) { // last copy
+              r_llsc_to_init_cmd_multi_req = true;
+              r_llsc_fsm = LLSC_IDLE; // Response will be sent after receiving
+                                      // all update responses
+              cmd_llsc_fifo_get         = true;
+            } else {
+              r_llsc_fsm = SC_UPDATE;
+            }
+          } else {
+            r_llsc_fsm = SC_UPDATE;
+          }
+          
+          break;
+        }
+        //////////////////
+      case SC_TRT_LOCK:
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            if( !r_llsc_to_ixr_cmd_req ) { // we can transfer the data to the buffer
+              size_t way	= r_llsc_way.read();
+              size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+              for(size_t i = 0; i<m_words; i++){
+                if(i==m_x[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]) {
+                  r_llsc_to_ixr_cmd_data[i] = m_cmd_llsc_wdata_fifo.read();
+                } else {
+                  r_llsc_to_ixr_cmd_data[i] = m_cache_data[way][set][i];
+                }
+              }
+              size_t wok_index = 0;
+              bool wok = !m_transaction_tab.full(wok_index);
+              if ( wok ) { // set a new entry in TRT
+                r_llsc_trt_index = wok_index;
+                r_llsc_fsm       = SC_INVAL_LOCK; 
+              } else {
+                r_llsc_fsm       = SC_WAIT;
+              }
+            } else {
+              r_llsc_fsm = SC_WAIT;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case SC_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
+            bool        wok       = false;
+            size_t      index     = 0;
+            size_t      srcid     = m_cmd_llsc_srcid_fifo.read();
+            size_t      trdid     = m_cmd_llsc_trdid_fifo.read();
+            size_t      pktid     = m_cmd_llsc_pktid_fifo.read();
+            addr_t	    nline     = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t      nb_copies = r_llsc_count.read();
+
+            wok =m_update_tab.set(false,	// it's an inval transaction
+                true,                       // it's a broadcast
+                true,                       // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " LLSC_INVAL_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_llsc_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_llsc_fsm = SC_DIR_INVAL;
+            else       r_llsc_fsm = SC_WAIT;
+          }
+          break;
+        }
+        //////////////////
+      case SC_DIR_INVAL:
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) &&
+              (r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC )  &&
+              (r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ))
+          {
+            m_transaction_tab.set(r_llsc_trt_index.read(),
+                false,				// write request to XRAM
+                m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())],
+                0,
+                0,
+                0,
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " SC_DIR_INVAL transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+            // reset Atomic Table
+            m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+
+            // invalidate directory entry
+            DirectoryEntry entry;
+            entry.valid	   = false;
+            entry.dirty	   = false;
+            entry.tag	   = 0;
+            entry.is_cnt   = false;
+            entry.lock	   = false;
+//            entry.d_copies = 0;
+//            entry.i_copies = 0;
+            entry.count    = 0;
+            size_t set	   = m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t way	   = r_llsc_way.read();
+            m_cache_directory.write(set, way, entry);
+
+            r_llsc_fsm = SC_INVAL;
+          } else {
+            assert(false && "LOCK ERROR in LLSC_FSM, STATE = LLSC_DIR_INVAL");
+          }
+
+          break;
+
+        }
+        //////////////////
+      case SC_INVAL:
+        {
+          if ( !r_llsc_to_init_cmd_multi_req.read() &&
+               !r_llsc_to_init_cmd_brdcast_req.read()) {
+            r_llsc_to_init_cmd_multi_req    = false;
+            r_llsc_to_init_cmd_brdcast_req  = true;
+            r_llsc_to_init_cmd_trdid        = r_llsc_upt_index.read();
+            r_llsc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_index        = 0;
+            r_llsc_to_init_cmd_wdata        = 0;
+
+            r_llsc_fsm = SC_XRAM_SEND;
+            // all update responses
+          }
+
+          break;
+        }
+        //////////////////
+      case SC_XRAM_SEND:
+        {
+          if ( !r_llsc_to_ixr_cmd_req ) {
+            r_llsc_to_ixr_cmd_req     = true;
+            r_llsc_to_ixr_cmd_write   = true;
+            r_llsc_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_ixr_cmd_trdid   = r_llsc_trt_index.read();
+            if(  r_llsc_is_cnt.read() ||
+                ((!r_llsc_is_cnt.read()) && (r_llsc_count.read()==1)) ){
+              r_llsc_fsm        = LLSC_IDLE;
+              cmd_llsc_fifo_get = true;
+            } else {
+              r_llsc_fsm        = SC_HEAP_ERASE;
+              r_llsc_next_ptr   = r_llsc_ptr.read();
+            }
+          } else {
+            assert( false && "MEM_CACHE, LLSC FSM : SC_XRAM_SEND state : the request should not have been previously set");
+          }
+          break;
+        }
+        //////////////////
+      case SC_HEAP_ERASE:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC){
+            HeapEntry next_entry = m_heap_directory.read(r_llsc_next_ptr.read());
+            if( next_entry.next == r_llsc_next_ptr.read()){
+              r_write_fsm = SC_HEAP_LAST;
+            } else {
+              r_llsc_next_ptr = next_entry.next;
+              r_llsc_fsm = SC_HEAP_ERASE;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case SC_HEAP_LAST:
+        {
+          assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
+                  "MemCache ERROR : bad HEAP allocation");
+          size_t free_pointer = m_heap_directory.next_free_ptr();
+
+          HeapEntry last_entry;
+          last_entry.owner.srcid = 0;
+          last_entry.owner.inst  = false;
+          if(m_heap_directory.is_full()){
+            last_entry.next     = r_llsc_next_ptr.read();
+            m_heap_directory.unset_full();
+          } else {
+            last_entry.next     = free_pointer;
+          }
+
+          m_heap_directory.write_free_ptr(r_llsc_ptr.read());
+          m_heap_directory.write(r_llsc_next_ptr.read(),last_entry);
+
+          cmd_llsc_fifo_get		= true;
+          r_llsc_fsm = LLSC_IDLE;
+          break;
+        }
+        //////////////////
+      case SC_RSP_FALSE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 1;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_RSP_TRUE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get	    = true;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 0;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_TRT_LOCK:         // read or write miss : check the Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            size_t   index = 0;
+            bool hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]);
+            bool wok = !m_transaction_tab.full(index);
+
+            if ( hit_read || !wok || hit_write ) {  // missing line already requested or no space in TRT
+              r_llsc_fsm = LLSC_IDLE;
+            } else {
+              r_llsc_trt_index = index;
+              r_llsc_fsm       = LLSC_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case LLSC_TRT_SET:	// register the XRAM transaction in Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+            bool proc_read = !m_cmd_llsc_sc_fifo.read();
+            if(proc_read){
+              m_transaction_tab.set(r_llsc_trt_index.read(),
+                  true,
+                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
+                  m_cmd_llsc_srcid_fifo.read(),
+                  m_cmd_llsc_trdid_fifo.read(),
+                  m_cmd_llsc_pktid_fifo.read(),
+                  true,
+                  1,
+                  word,
+                  std::vector<be_t>(m_words,0),
+                  std::vector<data_t>(m_words,0));
+            }else{
+              std::vector<be_t> be_vector;
+              std::vector<data_t> data_vector;
+              be_vector.clear();
+              data_vector.clear();
+              // reset Atomic Table
+              m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
+              for ( size_t i=0; i<m_words; i++ ) 
+              {   
+                if(i == word){
+                  be_vector.push_back(0xF);
+                  data_vector.push_back(m_cmd_llsc_wdata_fifo.read());
+                } else {
+                  be_vector.push_back(0);
+                  data_vector.push_back(0);
+                }
+              }
+ 
+              m_transaction_tab.set(r_llsc_trt_index.read(),
+                  true,
+                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
+                  m_cmd_llsc_srcid_fifo.read(),
+                  m_cmd_llsc_trdid_fifo.read(),
+                  m_cmd_llsc_pktid_fifo.read(),
+                  false,
+                  0,
+                  0,
+                  be_vector,
+                  data_vector);
+            }
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " LLSC_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_llsc_fsm = LLSC_XRAM_REQ;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_XRAM_REQ:	// request the IXR_CMD FSM to fetch the missing line
+        {
+          if ( !r_llsc_to_ixr_cmd_req ) {
+            r_llsc_to_ixr_cmd_req        = true;
+            r_llsc_to_ixr_cmd_write      = false;
+            r_llsc_to_ixr_cmd_trdid      = r_llsc_trt_index.read();
+            r_llsc_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()];
+            if( m_cmd_llsc_sc_fifo.read() ) {
+              r_llsc_fsm                 = SC_RSP_TRUE;
+            } else {
+              cmd_llsc_fifo_get          = true;
+              r_llsc_fsm                 = LLSC_IDLE;
+            }
+          }
+          break;
+        }
+    } // end switch r_llsc_fsm
+
+
+    //////////////////////////////////////////////////////////////////////////////
+    //		INIT_CMD FSM
+    //////////////////////////////////////////////////////////////////////////////
+    // The INIT_CMD fsm controls the VCI CMD initiator port, used to update
+    // or invalidate cache lines in L1 caches.
+    // It implements a round-robin priority between the two following requests:
+    // - r_write_to_init_cmd_req : update request from WRITE FSM 
+    // - r_xram_rsp_to_init_cmd_req : invalidate request from XRAM_RSP FSM 
+    // The inval request is a single cell VCI write command containing the 
+    // index of the line to be invalidated.
+    // The update request is a multi-cells VCI write command : The first cell 
+    // contains the index of the cache line to be updated. The second cell contains 
+    // the index of the first modified word in the line. The following cells
+    // contain the data.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      //////////////////////// 
+      case INIT_CMD_UPDT_IDLE:	// Invalidate requests have highest priority
+        {
+
+          if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
+               r_xram_rsp_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            m_cpt_inval++;
+          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_write_to_init_cmd_inst_fifo.rok() ||
+                      r_write_to_init_cmd_multi_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+            m_cpt_update++;
+          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
+                      r_llsc_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+            m_cpt_update++;
+          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_INVAL_IDLE:	// Update requests have highest priority
+        {
+          if ( m_write_to_init_cmd_inst_fifo.rok() ||
+               r_write_to_init_cmd_multi_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+            m_cpt_update++;
+          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
+                      r_llsc_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+            m_cpt_update++;
+          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
+                      r_xram_rsp_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            m_cpt_inval++;
+          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_IDLE:	// Update requests for SCs have highest priority
+        {
+          if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
+               r_llsc_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+            m_cpt_update++;
+          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
+                      r_xram_rsp_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            m_cpt_inval++;
+          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_write_to_init_cmd_inst_fifo.rok() ||
+                      r_write_to_init_cmd_multi_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+            m_cpt_update++;
+          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_INVAL_NLINE:	// send the cache line index
+        {
+          if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ){
+            if ( p_vci_ini.cmdack ) {
+              m_cpt_inval_mult++;
+              r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+              xram_rsp_to_init_cmd_fifo_get = true;
+            }
+          } else {
+            if( r_xram_rsp_to_init_cmd_multi_req.read() ){
+              r_xram_rsp_to_init_cmd_multi_req = false;
+            } 
+            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_XRAM_BRDCAST:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ) {
+            m_cpt_inval_brdcast++;
+            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+            r_xram_rsp_to_init_cmd_brdcast_req = false;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_WRITE_BRDCAST:
+        {
+          if( p_vci_ini.cmdack ) {
+            m_cpt_inval_brdcast++;
+            r_write_to_init_cmd_brdcast_req = false;
+            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_NLINE:	// send the cache line index
+        {
+          if ( m_write_to_init_cmd_inst_fifo.rok() ) {
+            if ( p_vci_ini.cmdack ){
+              m_cpt_update_mult++;
+              r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
+            }
+          } else {
+            if ( r_write_to_init_cmd_multi_req.read() ){
+              r_write_to_init_cmd_multi_req = false;
+            }
+            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_INDEX:	// send the first word index
+        {
+          r_init_cmd_cpt    = 0;
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) ) {
+              r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+              write_to_init_cmd_fifo_get = true;
+            } else {
+              r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_BRDCAST:
+        {
+          if( p_vci_ini.cmdack ) {
+            m_cpt_inval_brdcast++;
+            r_llsc_to_init_cmd_brdcast_req = false;
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_NLINE:	// send the cache line index
+        {
+          if ( m_llsc_to_init_cmd_inst_fifo.rok() ){
+            if ( p_vci_ini.cmdack ){
+              m_cpt_update_mult++;
+              r_init_cmd_fsm = INIT_CMD_SC_UPDT_INDEX;
+            }
+          } else {
+            if( r_llsc_to_init_cmd_multi_req.read() ){
+              r_llsc_to_init_cmd_multi_req = false;
+            }
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_INDEX:	// send the first word index
+        {
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_SC_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            llsc_to_init_cmd_fifo_get = true;
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+          }
+          break;
+        }
+
+    } // end switch r_init_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_RSP FSM
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_RSP fsm sends the responses on the VCI target port
+    // with a round robin priority between six requests :
+    // - r_read_to_tgt_rsp_req
+    // - r_write_to_tgt_rsp_req
+    // - r_llsc_to_tgt_rsp_req
+    // - r_cleanup_to_tgt_rsp_req
+    // - r_init_rsp_to_tgt_rsp_req
+    // - r_xram_rsp_to_tgt_rsp_req
+    // The  ordering is :  read > write > llsc > cleanup > xram > init
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      ///////////////////////
+      case TGT_RSP_READ_IDLE:		// write requests have the highest priority
+        {
+          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          break;
+        }
+        ////////////////////////
+      case TGT_RSP_WRITE_IDLE:		// llsc requests have the highest priority
+        {
+          if      ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_LLSC_IDLE:		// cleanup requests have the highest priority
+        {
+          if ( r_xram_rsp_to_tgt_rsp_req )  {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          break;
+        }
+      case TGT_RSP_XRAM_IDLE:		// init requests have the highest priority
+        {
+
+          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req )  {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_INIT_IDLE:		// cleanup requests have the highest priority
+        {
+          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_CLEANUP_IDLE:		// read requests have the highest priority
+        {
+          if      ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ:		// send the response
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) ) {
+              r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
+              r_read_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_WRITE:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
+            r_write_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_CLEANUP:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
+            r_cleanup_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        //////////////////
+      case TGT_RSP_LLSC:		// send one atomic word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_LLSC_IDLE;
+            r_llsc_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+
+        ///////////////////////
+      case TGT_RSP_XRAM:		// send the response
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1)) {
+              r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
+              r_xram_rsp_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_INIT:		// send the pending write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
+            r_init_rsp_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+    } // end switch tgt_rsp_fsm
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		NEW ALLOC_UPT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
+    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP 
+    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
+    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
+    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
+    // - The CLEANUP  FSM decrement an entry in UPT.
+    // The resource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_upt_fsm.read() ) {
+
+      ////////////////////////
+      case ALLOC_UPT_INIT_RSP:
+        if ( (r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK) && 
+             (r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR) ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_UPT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_UPT_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+        }
+        break;
+
+        ////////////////////////
+      case ALLOC_UPT_XRAM_RSP:
+        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK) 
+        { 
+          if       (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)       r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+        }
+        break;
+
+        //////////////////////////
+      case ALLOC_UPT_CLEANUP:
+        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
+        {
+          if      ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+        }
+        break;
+        
+        //////////////////////////
+      case ALLOC_UPT_LLSC:
+        if( (r_llsc_fsm.read() != SC_UPT_LOCK) && 
+            (r_llsc_fsm.read() != SC_INVAL_LOCK))
+        {
+          if      (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+        }
+        break;
+
+    } // end switch r_alloc_upt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_DIR FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_DIR FSM allocates the access to the directory and
+    // the data cache with a round robin priority between 5 user FSMs :
+    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
+    // The ressource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_dir_fsm.read() ) {
+
+      ////////////////////
+      case ALLOC_DIR_READ:
+        if ( ( (r_read_fsm.read() != READ_DIR_LOCK) &&
+              (r_read_fsm.read() != READ_TRT_LOCK)  &&
+              (r_read_fsm.read() != READ_HEAP_LOCK))
+            ||
+            ( (r_read_fsm.read()        == READ_HEAP_LOCK) &&
+              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_READ) )
+            ||
+            ( (r_read_fsm.read()      == READ_TRT_LOCK)  &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)    )  ) 
+        {
+          if        (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_DIR_WRITE:
+        if ( ( (r_write_fsm.read() != WRITE_DIR_LOCK)     &&
+              (r_write_fsm.read() != WRITE_TRT_LOCK)     &&
+              (r_write_fsm.read() != WRITE_DIR_HIT_READ) &&
+              (r_write_fsm.read() != WRITE_DIR_HIT) &&
+              (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+              (r_write_fsm.read() != WRITE_INVAL_LOCK) &&
+              (r_write_fsm.read() != WRITE_UPT_LOCK) &&
+              (r_write_fsm.read() != WRITE_HEAP_LOCK))
+            ||
+            ( (r_write_fsm.read()       == WRITE_HEAP_LOCK) &&
+              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_WRITE) )
+            ||
+            ( (r_write_fsm.read()     == WRITE_TRT_LOCK) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
+        {
+          if        ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+        }
+        break;
+
+        ////////////////////
+      case ALLOC_DIR_LLSC:
+        if ( ( (r_llsc_fsm.read() != LL_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != LL_DIR_HIT )    &&
+              (r_llsc_fsm.read() != SC_DIR_LOCK)    &&
+              (r_llsc_fsm.read() != SC_DIR_HIT )    &&
+              (r_llsc_fsm.read() != LLSC_TRT_LOCK ) &&
+              (r_llsc_fsm.read() != SC_TRT_LOCK)    &&
+              (r_llsc_fsm.read() != SC_INVAL_LOCK)  &&
+              (r_llsc_fsm.read() != SC_UPT_LOCK)    &&
+              (r_llsc_fsm.read() != SC_HEAP_LOCK))
+            ||
+            ( (r_llsc_fsm.read()       == SC_HEAP_LOCK) &&
+              (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) )
+            ||
+            ( (r_llsc_fsm.read()      == LLSC_TRT_LOCK ) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC)    ) )
+        {
+          if      (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)  r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+        }
+        break;
+
+        ///////////////////////
+      case ALLOC_DIR_CLEANUP:
+        if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
+            (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) )
+        {
+          if        (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if   (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_DIR_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)   && 
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
+        {
+          if      (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if ( (r_llsc_fsm.read() == LL_DIR_LOCK) || 
+                    (r_llsc_fsm.read() == SC_DIR_LOCK))         r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+        }
+        break;
+
+    } // end switch alloc_dir_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_TRT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
+    // with a round robin priority between 4 user FSMs :
+    // The cyclic priority is READ > WRITE > LLSC > XRAM_RSP
+    // The ressource is always allocated.
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    switch (r_alloc_trt_fsm) {
+
+      ////////////////////
+      case ALLOC_TRT_READ:
+        if ( r_read_fsm.read() != READ_TRT_LOCK ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ) )    r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+        }
+        break;
+        /////////////////////
+      case ALLOC_TRT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_TRT_LOCK) &&
+             (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+        }
+        break;
+        ////////////////////
+      case ALLOC_TRT_LLSC:
+        if ( (r_llsc_fsm.read() != LLSC_TRT_LOCK) &&
+             (r_llsc_fsm.read() != SC_TRT_LOCK) &&
+             (r_llsc_fsm.read() != SC_INVAL_LOCK))
+        { 
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)     ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT)   &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)) {
+          if      ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)    ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_IXR_RSP:
+        if ( (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
+            (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ) ) {
+          if      (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+        }
+        break;
+
+    } // end switch alloc_trt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_HEAP FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_HEAP FSM allocates the access to the heap
+    // with a round robin priority between 5 user FSMs :
+    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
+    // The ressource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_heap_fsm.read() ) {
+
+      ////////////////////
+      case ALLOC_HEAP_READ:
+        if (  (r_read_fsm.read() != READ_HEAP_LOCK) &&
+              (r_read_fsm.read() != READ_HEAP_ERASE)     ) 
+        {
+          if        ((r_write_fsm.read() == WRITE_HEAP_LOCK) ||         
+                     (r_write_fsm.read() == WRITE_HEAP_ERASE))      r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+          else if  ((r_llsc_fsm.read() == SC_HEAP_LOCK) || 
+                    (r_llsc_fsm.read() == SC_HEAP_ERASE))           r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_HEAP_WRITE:
+        if (  (r_write_fsm.read() != WRITE_HEAP_LOCK)   &&
+              (r_write_fsm.read() != WRITE_UPT_REQ)     &&
+              (r_write_fsm.read() != WRITE_UPDATE)      &&
+              (r_write_fsm.read() != WRITE_HEAP_ERASE))
+        {
+          if       ((r_llsc_fsm.read() == SC_HEAP_LOCK) || 
+                    (r_llsc_fsm.read() == SC_HEAP_ERASE))           r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_HEAP_LOCK) 	        r_alloc_heap_fsm = ALLOC_HEAP_READ;
+        }
+        break;
+
+        ////////////////////
+      case ALLOC_HEAP_LLSC:
+        if (  (r_llsc_fsm.read() != SC_HEAP_LOCK)  &&
+              (r_llsc_fsm.read() != SC_UPT_REQ )    &&
+              (r_llsc_fsm.read() != SC_UPDATE)      &&
+              (r_llsc_fsm.read() != SC_HEAP_ERASE ) )
+        {
+          if      (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+          else if (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
+          else if ((r_write_fsm.read() == WRITE_HEAP_LOCK) ||        
+                   (r_write_fsm.read() == WRITE_HEAP_ERASE))      r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+        }
+        break;
+
+        ///////////////////////
+      case ALLOC_HEAP_CLEANUP:
+        if ( (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) &&
+            (r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH)&&
+            (r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN)    )
+        {
+          if        (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
+          else if   ((r_write_fsm.read() == WRITE_HEAP_LOCK) ||        
+                     (r_write_fsm.read() == WRITE_HEAP_ERASE))      r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+          else if   ((r_llsc_fsm.read() == SC_HEAP_LOCK) || 
+                    (r_llsc_fsm.read() == SC_HEAP_ERASE))           r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_HEAP_XRAM_RSP:
+        if ( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE )
+        {
+          if        (r_read_fsm.read() == READ_HEAP_LOCK) 	        r_alloc_heap_fsm = ALLOC_HEAP_READ;
+          else if   ((r_write_fsm.read() == WRITE_HEAP_LOCK) ||        
+                     (r_write_fsm.read() == WRITE_HEAP_ERASE))      r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+          else if   ( (r_llsc_fsm.read() == SC_HEAP_LOCK) || 
+                    (r_llsc_fsm.read() == SC_HEAP_ERASE))           r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+        }
+        break;
+
+    } // end switch alloc_heap_fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to READ FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_read_fifo_put ) {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
+        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+      } else {
+        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
+        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+      }
+    } else {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.simple_get();
+        m_cmd_read_length_fifo.simple_get();
+        m_cmd_read_srcid_fifo.simple_get();
+        m_cmd_read_trdid_fifo.simple_get();
+        m_cmd_read_pktid_fifo.simple_get();
+      }
+    }
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to WRITE FIFO
+    /////////////////////////////////////////////////////////////////////
+
+    if ( cmd_write_fifo_put ) {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
+      } else {
+        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
+      }
+    } else {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.simple_get();
+        m_cmd_write_eop_fifo.simple_get();
+        m_cmd_write_srcid_fifo.simple_get();
+        m_cmd_write_trdid_fifo.simple_get();
+        m_cmd_write_pktid_fifo.simple_get();
+        m_cmd_write_data_fifo.simple_get();
+        m_cmd_write_be_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to LLSC FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_llsc_fifo_put ) {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_sc_fifo.put_and_get(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
+      } else {
+        m_cmd_llsc_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_sc_fifo.simple_put(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
+        m_cmd_llsc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
+      }
+    } else {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.simple_get();
+        m_cmd_llsc_sc_fifo.simple_get();
+        m_cmd_llsc_srcid_fifo.simple_get();
+        m_cmd_llsc_trdid_fifo.simple_get();
+        m_cmd_llsc_pktid_fifo.simple_get();
+        m_cmd_llsc_wdata_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		WRITE to INIT_CMD FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( write_to_init_cmd_fifo_put ) {
+      if ( write_to_init_cmd_fifo_get ) {
+        m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
+        m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
+      } else {
+        m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
+        m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
+      }
+    } else {
+      if ( write_to_init_cmd_fifo_get ) {
+        m_write_to_init_cmd_inst_fifo.simple_get();
+        m_write_to_init_cmd_srcid_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		XRAM_RSP to INIT_CMD FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( xram_rsp_to_init_cmd_fifo_put ) {
+      if ( xram_rsp_to_init_cmd_fifo_get ) {
+        m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
+        m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
+      } else {
+        m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
+        m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
+      }
+    } else {
+      if ( xram_rsp_to_init_cmd_fifo_get ) {
+        m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
+        m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		LLSC to INIT_CMD FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( llsc_to_init_cmd_fifo_put ) {
+      if ( llsc_to_init_cmd_fifo_get ) {
+        m_llsc_to_init_cmd_inst_fifo.put_and_get(llsc_to_init_cmd_fifo_inst);
+        m_llsc_to_init_cmd_srcid_fifo.put_and_get(llsc_to_init_cmd_fifo_srcid);
+      } else {
+        m_llsc_to_init_cmd_inst_fifo.simple_put(llsc_to_init_cmd_fifo_inst);
+        m_llsc_to_init_cmd_srcid_fifo.simple_put(llsc_to_init_cmd_fifo_srcid);
+      }
+    } else {
+      if ( llsc_to_init_cmd_fifo_get ) {
+        m_llsc_to_init_cmd_inst_fifo.simple_get();
+        m_llsc_to_init_cmd_srcid_fifo.simple_get();
+      }
+    }
+
+
+  //////////////////////////////////////////////////////////////
+    m_cpt_cycles++;
+
+  } // end transition()
+
+  /////////////////////////////
+  tmpl(void)::genMoore()
+    /////////////////////////////
+  {
+    ////////////////////////////////////////////////////////////
+    // Command signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////////////
+
+
+    p_vci_ixr.be      = 0xF;
+    p_vci_ixr.pktid   = 0;
+    p_vci_ixr.srcid   = m_srcid_ixr;
+    p_vci_ixr.cons    = false;
+    p_vci_ixr.wrap    = false;
+    p_vci_ixr.contig  = true;
+    p_vci_ixr.clen    = 0;
+    p_vci_ixr.cfixed  = false;
+
+    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_LLSC_NLINE ) {
+      if(r_llsc_to_ixr_cmd_write.read()){
+        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)((r_llsc_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = r_llsc_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+      } else {
+        p_vci_ixr.cmd     = vci_param::CMD_READ;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)(r_llsc_to_ixr_cmd_nline.read()*m_words*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = 0x00000000;
+        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = true;
+      }
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
+      if(r_write_to_ixr_cmd_write.read()){
+        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+      } else {
+        p_vci_ixr.cmd     = vci_param::CMD_READ;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = 0x00000000;
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = true;
+      }
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
+      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+    } else {
+      p_vci_ixr.cmdval  = false;
+      p_vci_ixr.address = 0;
+      p_vci_ixr.plen    = 0;
+      p_vci_ixr.wdata   = 0;
+      p_vci_ixr.trdid   = 0;
+      p_vci_ixr.eop	= false;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////
+
+    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
+          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) || 
+        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
+    else                                        p_vci_ixr.rspack = false;
+
+    ////////////////////////////////////////////////////
+    // Command signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+
+    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
+      case TGT_CMD_IDLE:
+        p_vci_tgt.cmdack  = false;
+        break;
+      case TGT_CMD_READ:
+        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
+        break;
+      case TGT_CMD_READ_EOP:
+        p_vci_tgt.cmdack  = true;
+        break;
+      case TGT_CMD_WRITE:
+        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
+        break;
+      case TGT_CMD_ATOMIC:
+        p_vci_tgt.cmdack  = m_cmd_llsc_addr_fifo.wok();
+        break;
+      default:
+        p_vci_tgt.cmdack = false;
+        break;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      case TGT_RSP_READ_IDLE:
+      case TGT_RSP_WRITE_IDLE:
+      case TGT_RSP_LLSC_IDLE:
+      case TGT_RSP_XRAM_IDLE:
+      case TGT_RSP_INIT_IDLE:
+      case TGT_RSP_CLEANUP_IDLE:
+        p_vci_tgt.rspval  = false;
+        p_vci_tgt.rsrcid  = 0;
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rpktid  = 0;
+        p_vci_tgt.rtrdid  = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = false;	
+        break;
+      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();
+        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
+        break;
+      case TGT_RSP_WRITE:
+        p_vci_tgt.rspval   = true;
+        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   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_CLEANUP:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_LLSC:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = r_llsc_to_tgt_rsp_data.read();
+        p_vci_tgt.rsrcid   = r_llsc_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_llsc_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_llsc_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      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();
+        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1));
+        break;
+      case TGT_RSP_INIT:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        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;
+        p_vci_tgt.reop     = true;	
+        break;
+    } // end switch r_tgt_rsp_fsm
+
+    ///////////////////////////////////////////////////
+    // Command signals on the p_vci_ini port
+    ///////////////////////////////////////////////////
+
+    p_vci_ini.cmd     = vci_param::CMD_WRITE;
+    p_vci_ini.srcid   = m_srcid_ini;
+    p_vci_ini.pktid   = 0;
+    p_vci_ini.cons    = true;
+    p_vci_ini.wrap    = false;
+    p_vci_ini.contig  = false;
+    p_vci_ini.clen    = 0;
+    p_vci_ini.cfixed  = false;
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      case INIT_CMD_UPDT_IDLE:
+      case INIT_CMD_INVAL_IDLE:
+      case INIT_CMD_SC_UPDT_IDLE:
+        p_vci_ini.cmdval  = false;
+        p_vci_ini.address = 0;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0;
+        p_vci_ini.plen    = 0;
+        p_vci_ini.trdid   = 0;
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_INVAL_NLINE:
+        p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
+        if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
+          if(m_xram_rsp_to_init_cmd_inst_fifo.read()) {
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_xram_rsp_to_init_cmd_srcid_fifo.read()]+8);
+          } else {
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_xram_rsp_to_init_cmd_srcid_fifo.read()]);
+          }
+        } else p_vci_ini.address = 0; // prevent segmentation faults by reading an empty fifo
+        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4;
+        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+      case INIT_CMD_XRAM_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4;
+        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+
+      case INIT_CMD_WRITE_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4 ;
+        p_vci_ini.eop     = true;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_NLINE:
+        p_vci_ini.cmdval  = m_write_to_init_cmd_inst_fifo.rok();
+        if(m_write_to_init_cmd_inst_fifo.rok()){
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 4);
+        } else {
+          p_vci_ini.address = 0;
+        }
+        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.eop     = false;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 4);
+        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 4);
+        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
+          r_write_to_init_cmd_index.read()].read();
+        if(r_write_to_init_cmd_we[r_init_cmd_cpt.read() +
+            r_write_to_init_cmd_index.read()].read())  
+          p_vci_ini.be      = 0xF;
+        else			p_vci_ini.be      = 0x0;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
+        break;
+
+      case INIT_CMD_SC_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (addr_t)r_llsc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4 ;
+        p_vci_ini.eop     = true;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_SC_UPDT_NLINE:
+        p_vci_ini.cmdval  = m_llsc_to_init_cmd_inst_fifo.rok();
+        if(m_llsc_to_init_cmd_inst_fifo.rok()){
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 4);
+        } else {
+          p_vci_ini.address = 0;
+        }
+        p_vci_ini.wdata   = (uint32_t)r_llsc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        p_vci_ini.plen    = 4 * 3;
+        p_vci_ini.eop     = false;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_SC_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 4);
+        p_vci_ini.wdata   = r_llsc_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * 3;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_SC_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 4);
+        p_vci_ini.wdata   = r_llsc_to_init_cmd_wdata.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * 3;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+
+    } // end switch r_init_cmd_fsm
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_ini port
+    //////////////////////////////////////////////////////
+
+    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
+    else                                          p_vci_ini.rspack  = false;
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt_cleanup port
+    //////////////////////////////////////////////////////
+    p_vci_tgt_cleanup.rspval = false;
+    p_vci_tgt_cleanup.rsrcid = 0;
+    p_vci_tgt_cleanup.rdata  = 0;
+    p_vci_tgt_cleanup.rpktid = 0;
+    p_vci_tgt_cleanup.rtrdid = 0;
+    p_vci_tgt_cleanup.rerror = 0;
+    p_vci_tgt_cleanup.reop   = false;
+    p_vci_tgt_cleanup.cmdack = false ;
+
+    switch(r_cleanup_fsm.read()){
+      case CLEANUP_IDLE:
+        {
+          p_vci_tgt_cleanup.cmdack = true ;
+          break;
+        }
+      case CLEANUP_RSP:
+        {
+          p_vci_tgt_cleanup.rspval = true;
+          p_vci_tgt_cleanup.rdata  = 0;
+          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
+          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
+          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
+          p_vci_tgt_cleanup.rerror = 0;
+          p_vci_tgt_cleanup.reop   = 1;
+          break;
+        }
+
+    }
+
+  } // end genMoore()
+
+}} // end name space
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// 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 2)
+++ trunk/modules/vci_mem_cache_v4/caba/metadata/vci_mem_cache_v4.sd	(revision 2)
@@ -0,0 +1,40 @@
+
+# -*- python -*-
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+
+Module('caba:vci_mem_cache_v4',
+       classname = 'soclib::caba::VciMemCacheV4',
+       tmpl_parameters = [parameter.Module('vci_param', default = 'caba:vci_param'),],
+       header_files = ['../source/include/vci_mem_cache_v4.h',
+                       '../source/include/xram_transaction_v4.h',
+                       '../source/include/mem_cache_directory_v4.h',
+                       '../source/include/update_tab_v4.h',],
+       implementation_files = ['../source/src/vci_mem_cache_v4.cpp',],
+       uses = [Uses('caba:base_module'),
+               Uses('common:loader'),
+               Uses('common:mapping_table'),
+               Uses('caba:generic_fifo'),
+               ],
+       ports = [Port('caba:vci_target', 'p_vci_tgt'),
+		Port('caba:vci_target','p_vci_tgt_cleanup'),
+		Port('caba:vci_initiator','p_vci_ini'),
+		Port('caba:vci_initiator','p_vci_ixr'),
+                Port('caba:bit_in', 'p_resetn', auto = 'resetn'),
+                Port('caba:clock_in', 'p_clk', auto = 'clock'),],
+       instance_parameters = [
+		parameter.Module('mtp', 'common:mapping_table'),
+		parameter.Module('mtc', 'common:mapping_table'),
+		parameter.Module('mtx', 'common:mapping_table'),
+		parameter.IntTab('vci_ixr_index'),
+		parameter.IntTab('vci_ini_index'),
+		parameter.IntTab('vci_tgt_index'),
+		parameter.IntTab('vci_tgt_index_cleanup'),
+    parameter.Int('nways'),
+		parameter.Int('nsets'),
+		parameter.Int('nwords'),
+		parameter.Int('heap_size'),
+		],
+       extensions = ['dsx:get_ident=initiator_index:p_vci_ini',],
+)
Index: trunk/modules/vci_mem_cache_v4/caba/source/include/mem_cache_directory_v4.h
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/include/mem_cache_directory_v4.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/mem_cache_directory_v4.h	(revision 2)
@@ -0,0 +1,533 @@
+#ifndef SOCLIB_CABA_MEM_CACHE_DIRECTORY_V4_H
+#define SOCLIB_CABA_MEM_CACHE_DIRECTORY_V4_H 
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+namespace soclib { namespace caba {
+
+  using namespace sc_core;
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A LRU entry 
+  ////////////////////////////////////////////////////////////////////////
+  class LruEntry {
+
+    public:
+
+      bool recent;            
+
+      void init()
+      {
+        recent=false;
+      }
+
+  }; // end class LruEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    An Owner
+  ////////////////////////////////////////////////////////////////////////
+  class Owner{
+    typedef uint32_t size_t;
+    
+    public:
+    // Fields
+      bool      inst;       // Is the owner an ICache ?
+      size_t    srcid;      // The SRCID of the owner
+
+    ////////////////////////
+    // Constructors
+    ////////////////////////
+      Owner(bool i_inst,size_t i_srcid){
+        inst    = i_inst;
+        srcid   = i_srcid;
+      }
+
+      Owner(const Owner &a){
+        inst    = a.inst;
+        srcid   = a.srcid;
+      }
+
+      Owner(){
+        inst    = false;
+        srcid   = 0;
+      }
+      // end constructors
+
+  }; // end class Owner
+
+
+  ////////////////////////////////////////////////////////////////////////
+  //                    A directory entry                               
+  ////////////////////////////////////////////////////////////////////////
+  class DirectoryEntry {
+
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+
+    public:
+
+    bool    valid;                  // entry valid
+    bool    is_cnt;                 // directory entry is in counter mode
+    bool    dirty;                  // entry dirty
+    bool    lock;                   // entry locked
+    tag_t   tag;                    // tag of the entry
+    size_t  count;                  // number of copies
+    Owner   owner;                  // an owner of the line 
+    size_t  ptr;                    // pointer to the next owner
+
+    DirectoryEntry()
+    {
+      valid         = false;
+      is_cnt        = false;
+      dirty         = false;
+      lock          = false;
+      tag           = 0;
+      count         = 0;
+      owner.inst    = 0;
+      owner.srcid   = 0;
+      ptr           = 0;
+    }
+
+    DirectoryEntry(const DirectoryEntry &source)
+    {
+      valid         = source.valid;
+      is_cnt        = source.is_cnt;
+      dirty         = source.dirty;
+      lock          = source.lock;
+      tag           = source.tag;
+      count         = source.count;
+      owner         = source.owner;
+      ptr           = source.ptr;
+    }          
+
+    /////////////////////////////////////////////////////////////////////
+    // The init() function initializes the entry 
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      valid     = false;
+      is_cnt    = false;
+      dirty     = false;
+      lock      = false;
+      count     = 0;
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    // The copy() function copies an existing source entry to a target 
+    /////////////////////////////////////////////////////////////////////
+    void copy(const DirectoryEntry &source)
+    {
+      valid	    = source.valid;
+      is_cnt    = source.is_cnt;
+      dirty	    = source.dirty;
+      lock	    = source.lock;
+      tag	    = source.tag;
+      count     = source.count;
+      owner     = source.owner;
+      ptr       = source.ptr;
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // The print() function prints the entry 
+    ////////////////////////////////////////////////////////////////////
+    void print()
+    {
+      std::cout << "Valid = " << valid << " ; IS COUNT = " << is_cnt << " ; Dirty = " << dirty << " ; Lock = " 
+        << lock << " ; Tag = " << std::hex << tag << std::dec << " ; Count = " << count << " ; Owner = " << owner.srcid << " " << owner.inst << " ; Pointer = " << ptr << std::endl;
+    }
+
+  }; // end class DirectoryEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                       The directory  
+  ////////////////////////////////////////////////////////////////////////
+  class CacheDirectory {
+
+    typedef sc_dt::sc_uint<40> addr_t;
+    typedef uint32_t data_t;
+    typedef uint32_t tag_t;
+    typedef uint32_t size_t;
+
+    private:
+
+    // Directory constants
+    size_t					m_ways;
+    size_t					m_sets;
+    size_t					m_words;
+    size_t					m_width;
+
+    // the directory & lru tables
+    DirectoryEntry 				**m_dir_tab;
+    LruEntry	 				**m_lru_tab;
+
+    public:
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+    CacheDirectory( size_t ways, size_t sets, size_t words, size_t address_width)	 
+    {
+      m_ways  = ways; 
+      m_sets  = sets;
+      m_words = words;
+      m_width = address_width;
+
+      m_dir_tab = new DirectoryEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_dir_tab[i] = new DirectoryEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_dir_tab[i][j].init();
+      }
+      m_lru_tab = new LruEntry*[sets];
+      for ( size_t i=0; i<sets; i++ ) {
+        m_lru_tab[i] = new LruEntry[ways];
+        for ( size_t j=0 ; j<ways ; j++) m_lru_tab[i][j].init();
+      }
+    } // end constructor
+
+    /////////////////
+    // Destructor
+    /////////////////
+    ~CacheDirectory()
+    {
+      for(size_t i=0 ; i<m_sets ; i++){
+        delete [] m_dir_tab[i];
+        delete [] m_lru_tab[i];
+      }
+      delete [] m_dir_tab;
+      delete [] m_lru_tab;
+    } // end destructor
+
+    /////////////////////////////////////////////////////////////////////
+    // The read() function reads a directory entry. In case of hit, the
+    // LRU is updated.
+    // Arguments :
+    // - address : the address of the entry 
+    // - way : (return argument) the way of the entry in case of hit
+    // The function returns a copy of a (valid or invalid) entry  
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry read(const addr_t &address,size_t &way)
+    {
+
+#define L2 soclib::common::uint32_log2
+      const size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
+      const tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
+#undef L2
+
+      bool hit       = false;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        bool equal = ( m_dir_tab[set][i].tag == tag );
+        bool valid = m_dir_tab[set][i].valid;
+        hit = equal && valid;
+        if ( hit ) {			
+          way = i;
+          break;
+        } 
+      }
+      if ( hit ) {
+        m_lru_tab[set][way].recent = true;
+        return DirectoryEntry(m_dir_tab[set][way]);
+      } else {
+        return DirectoryEntry();
+      }
+    } // end read()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write function writes a new entry, 
+    // and updates the LRU bits if necessary.
+    // Arguments :
+    // - set : the set of the entry
+    // - way : the way of the entry
+    // - entry : the entry value
+    /////////////////////////////////////////////////////////////////////
+    void write(const size_t &set, const size_t &way, const DirectoryEntry &entry)
+    {
+      assert( (set<m_sets) 
+          && "Cache Directory write : The set index is invalid");
+      assert( (way<m_ways) 
+          && "Cache Directory write : The way index is invalid");
+
+      // update Directory
+      m_dir_tab[set][way].copy(entry);
+
+      // update LRU bits
+      bool all_recent = true;
+      for ( size_t i=0 ; i<m_ways ; i++ ) {
+        if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
+      }
+      if ( all_recent ) {
+        for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
+      } else {
+        m_lru_tab[set][way].recent = true;
+      }
+    } // end write()
+
+    /////////////////////////////////////////////////////////////////////
+    // The print() function prints a selected directory entry
+    // Arguments :
+    // - set : the set of the entry to print
+    // - way : the way of the entry to print
+    /////////////////////////////////////////////////////////////////////
+    void print(const size_t &set, const size_t &way)
+    {
+      std::cout << std::dec << " set : " << set << " ; way : " << way << " ; " ;
+      m_dir_tab[set][way].print();
+    } // end print()
+
+    /////////////////////////////////////////////////////////////////////
+    // The select() function selects a directory entry to evince.
+    // Arguments :
+    // - set   : (input argument) the set to modify
+    // - way   : (return argument) the way to evince
+    /////////////////////////////////////////////////////////////////////
+    DirectoryEntry select(const size_t &set, size_t &way)
+    {
+      assert( (set < m_sets) 
+          && "Cache Directory : (select) The set index is invalid");
+
+      for(size_t i=0; i<m_ways; i++){
+        if(!m_dir_tab[set][way].valid){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if(!(m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( !(m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      for(size_t i=0; i<m_ways; i++){
+        if( (m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
+          way=i;
+          return DirectoryEntry(m_dir_tab[set][way]);
+        }
+      }
+      way = 0;
+      return DirectoryEntry(m_dir_tab[set][0]);
+    } // end select()
+
+    /////////////////////////////////////////////////////////////////////
+    // 		Global initialisation function
+    /////////////////////////////////////////////////////////////////////
+    void init()
+    {
+      for ( size_t set=0 ; set<m_sets ; set++ ) {
+        for ( size_t way=0 ; way<m_ways ; way++ ) {
+          m_dir_tab[set][way].init();
+          m_lru_tab[set][way].init();
+        }
+      }
+    } // end init()
+
+  }; // end class CacheDirectory
+
+  ///////////////////////////////////////////////////////////////////////
+  //                    A Heap Entry
+  ///////////////////////////////////////////////////////////////////////
+  class HeapEntry{
+    typedef uint32_t size_t;
+
+    public:
+    // Fields of the entry
+      Owner     owner;
+      size_t    next;
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+      HeapEntry()
+      :owner(false,0)
+      {
+        next = 0;
+      } // end constructor
+
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+      HeapEntry(const HeapEntry &entry){
+        owner.srcid = entry.owner.srcid;
+        owner.inst  = entry.owner.inst;
+        next        = entry.next;
+      } // end constructor
+
+    /////////////////////////////////////////////////////////////////////
+    // The copy() function copies an existing source entry to a target 
+    /////////////////////////////////////////////////////////////////////
+      void copy(const HeapEntry &entry){
+        owner.srcid = entry.owner.srcid;
+        owner.inst  = entry.owner.inst;
+        next        = entry.next;
+      } // end copy()
+
+    ////////////////////////////////////////////////////////////////////
+    // The print() function prints the entry 
+    ////////////////////////////////////////////////////////////////////
+      void print(){
+        std::cout 
+        << " -- owner.srcid : " << std::dec << owner.srcid << std::endl
+        << " -- owner.inst  : " << std::dec << owner.inst << std::endl
+        << " -- next        : " << std::dec << next << std::endl;
+
+      } // end print()
+
+  }; // end class HeapEntry
+
+  ////////////////////////////////////////////////////////////////////////
+  //                        The Heap 
+  ////////////////////////////////////////////////////////////////////////
+  class HeapDirectory{
+    typedef uint32_t size_t;
+    
+    private:
+    // Registers and the heap
+      size_t    ptr_free;
+      bool      full;
+      HeapEntry *m_heap_tab;
+
+    // Constants for debugging purpose
+      size_t    tab_size;
+
+    public:
+    ////////////////////////
+    // Constructor
+    ////////////////////////
+      HeapDirectory(uint32_t size){
+        assert(size>0 && "Memory Cache, HeapDirectory constructor : invalid size");
+        ptr_free    = 0;
+        full        = false;
+        m_heap_tab  = new HeapEntry[size];
+        tab_size    = size;
+      } // end constructor
+
+    /////////////////
+    // Destructor
+    /////////////////
+      ~HeapDirectory(){
+        delete [] m_heap_tab;
+      } // end destructor
+
+    /////////////////////////////////////////////////////////////////////
+    // 		Global initialisation function
+    /////////////////////////////////////////////////////////////////////
+      void init(){
+        ptr_free=0;
+        full=false;
+        for(size_t i=0; i< tab_size-1;i++){
+          m_heap_tab[i].next = i+1;
+        }
+        m_heap_tab[tab_size-1].next = tab_size-1;
+        return;
+      }
+
+    /////////////////////////////////////////////////////////////////////
+    // The print() function prints a selected directory entry
+    // Arguments :
+    // - ptr : the pointer to the entry to print
+    /////////////////////////////////////////////////////////////////////
+      void print(const size_t &ptr){
+        std::cout << "Heap, printing the entry : " << std::dec << ptr << std::endl;
+        m_heap_tab[ptr].print();
+      } // end print()
+
+    /////////////////////////////////////////////////////////////////////
+    // The is_full() function return true if the heap is full.
+    /////////////////////////////////////////////////////////////////////
+      bool is_full(){
+        return full;
+      } // end is_full()
+
+    /////////////////////////////////////////////////////////////////////
+    // The next_free_ptr() function returns the pointer 
+    // to the next free entry.
+    /////////////////////////////////////////////////////////////////////
+      size_t next_free_ptr(){
+        return ptr_free;
+      } // end next_free_ptr()
+
+    /////////////////////////////////////////////////////////////////////
+    // The next_free_entry() function returns 
+    // a copy of the next free entry.
+    /////////////////////////////////////////////////////////////////////
+      HeapEntry next_free_entry(){
+        return HeapEntry(m_heap_tab[ptr_free]);
+      } // end next_free_entry()
+   
+    /////////////////////////////////////////////////////////////////////
+    // The write_free_entry() function modify the next free entry.
+    // Arguments :
+    // - entry : the entry to write
+    /////////////////////////////////////////////////////////////////////
+      void write_free_entry(const HeapEntry &entry){
+        m_heap_tab[ptr_free].copy(entry);
+      } // end write_free_entry()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write_free_ptr() function writes the pointer
+    // to the next free entry
+    /////////////////////////////////////////////////////////////////////
+      void write_free_ptr(const size_t &ptr){
+        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
+        ptr_free = ptr;
+      } // end write_free_ptr()
+
+    /////////////////////////////////////////////////////////////////////
+    // The set_full() function sets the full bit (to true).
+    /////////////////////////////////////////////////////////////////////
+      void set_full(){
+        full = true;
+      } // end set_full()
+
+    /////////////////////////////////////////////////////////////////////
+    // The unset_full() function unsets the full bit (to false).
+    /////////////////////////////////////////////////////////////////////
+      void unset_full(){
+        full = false;
+      } // end unset_full()
+
+    /////////////////////////////////////////////////////////////////////
+    // The read() function returns a copy of
+    // the entry pointed by the argument
+    // Arguments :
+    //  - ptr : the pointer to the entry to read
+    /////////////////////////////////////////////////////////////////////
+      HeapEntry read(const size_t &ptr){
+        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
+        return HeapEntry(m_heap_tab[ptr]);
+      } // end read()
+
+    /////////////////////////////////////////////////////////////////////
+    // The write() function writes an entry in the heap
+    // Arguments :
+    //  - ptr : the pointer to the entry to replace
+    //  - entry : the entry to write
+    /////////////////////////////////////////////////////////////////////
+      void write(const size_t &ptr, const HeapEntry &entry){
+        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
+        m_heap_tab[ptr].copy(entry);
+      } // end write()
+
+  }; // end class HeapDirectory
+
+
+}} // end namespaces
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: trunk/modules/vci_mem_cache_v4/caba/source/include/update_tab_v4.h
===================================================================
--- trunk/modules/vci_mem_cache_v4/caba/source/include/update_tab_v4.h	(revision 2)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/update_tab_v4.h	(revision 2)
@@ -0,0 +1,402 @@
+#ifndef UPDATE_TAB_V4_H_
+#define UPDATE_TAB_V4_H_
+
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+////////////////////////////////////////////////////////////////////////
+//                  An update tab entry    
+////////////////////////////////////////////////////////////////////////
+class UpdateTabEntry {
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  public:
+  bool 	valid;                // It is a valid pending transaction
+  bool	update;               // It is an update transaction
+  bool  brdcast;              // It is a broadcast invalidate
+  bool  rsp;                  // It needs a response to the initiator
+  size_t 	srcid;        // The srcid of the initiator which wrote the data
+  size_t 	trdid;        // The trdid of the initiator which wrote the data
+  size_t 	pktid;        // The pktid of the initiator which wrote the data
+  addr_t	nline;	      // The identifier of the cache line
+  size_t 	count;        // The number of acknowledge responses to receive
+
+  UpdateTabEntry(){
+    valid	= false;
+    update  = false;
+    brdcast = false;
+    rsp     = false;
+    srcid	= 0;
+    trdid	= 0;
+    pktid	= 0;
+    nline	= 0;
+    count	= 0;
+  }
+
+  UpdateTabEntry(bool   i_valid, 
+      bool   i_update,
+      bool   i_brdcast,
+      bool   i_rsp,
+      size_t i_srcid, 
+      size_t i_trdid, 
+      size_t i_pktid, 
+      addr_t i_nline,
+      size_t i_count) 
+  {
+    valid		= i_valid;
+    update	    = i_update;
+    brdcast     = i_brdcast;
+    rsp         = i_rsp;
+    srcid		= i_srcid;
+    trdid		= i_trdid;
+    pktid		= i_pktid;
+    nline		= i_nline;
+    count		= i_count;
+  }
+
+  UpdateTabEntry(const UpdateTabEntry &source)
+  {
+    valid   = source.valid;
+    update  = source.update;
+    brdcast = source.brdcast;
+    rsp     = source.rsp;
+    srcid   = source.srcid;
+    trdid   = source.trdid;
+    pktid   = source.pktid;
+    nline   = source.nline;
+    count   = source.count;
+  }
+
+  ////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  ///////////////////////////////////////////////////
+  void init()
+  {
+    valid  = false;
+    update = false;
+    brdcast= false;
+    rsp    = false;
+    srcid  = 0;
+    trdid  = 0;
+    pktid  = 0;
+    nline  = 0;
+    count  = 0;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the update tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const UpdateTabEntry &source)
+  {
+    valid  = source.valid;
+    update = source.update;
+    brdcast= source.brdcast;
+    rsp    = source.rsp;
+    srcid  = source.srcid;
+    trdid  = source.trdid;
+    pktid  = source.pktid;
+    nline  = source.nline;
+    count  = source.count;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << std::dec << "valid  = " << valid  << std::endl;
+    std::cout << "update = " << update << std::endl;
+    std::cout << "brdcast= " << brdcast<< std::endl;
+    std::cout << "rsp    = " << rsp    << std::endl;
+    std::cout << "srcid  = " << srcid  << std::endl; 
+    std::cout << "trdid  = " << trdid  << std::endl; 
+    std::cout << "pktid  = " << pktid  << std::endl; 
+    std::cout << std::hex << "nline  = " << nline  << std::endl;
+    std::cout << std::dec << "count  = " << count  << std::endl;
+  }
+};
+
+////////////////////////////////////////////////////////////////////////
+//                        The update tab             
+////////////////////////////////////////////////////////////////////////
+class UpdateTab{
+
+  typedef uint32_t size_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+
+  private:
+  size_t size_tab;
+  std::vector<UpdateTabEntry> tab;
+
+  public:
+
+  UpdateTab()
+    : tab(0)
+  {
+    size_tab=0;
+  }
+
+  UpdateTab(size_t size_tab_i)
+    : tab(size_tab_i)
+  {
+    size_tab=size_tab_i;
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  const size_t size(){
+    return size_tab;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab  
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    for(size_t i=0; i<size_tab; i++) {
+      std::cout << "UPDATE TAB ENTRY " << std::dec << i << "--------" << std::endl;
+      tab[i].print();
+    }
+    return;
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the tab 
+  /////////////////////////////////////////////////////////////////////
+  void init(){
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+
+  /////////////////////////////////////////////////////////////////////
+  // The reads() function reads an entry 
+  // Arguments :
+  // - entry : the entry to read
+  // This function returns a copy of the entry.
+  /////////////////////////////////////////////////////////////////////
+  UpdateTabEntry read (size_t entry)
+  {
+    assert(entry<size_tab && "Bad Update Tab Entry");
+    return UpdateTabEntry(tab[entry]);
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // The set() function writes an entry in the Update Table
+  // Arguments :
+  // - update : transaction type (bool)
+  // - srcid : srcid of the initiator
+  // - trdid : trdid of the initiator
+  // - pktid : pktid of the initiator
+  // - count : number of expected responses
+  // - index : (return argument) index of the selected entry
+  // This function returns true if the write successed (an entry was empty).
+  ///////////////////////////////////////////////////////////////////////////
+  bool set(const bool	update,
+      const bool   brdcast,
+      const bool   rsp,
+      const size_t srcid,
+      const size_t trdid,
+      const size_t pktid,
+      const addr_t nline,
+      const size_t count,
+      size_t &index)
+  {
+    for ( size_t i=0 ; i<size_tab ; i++ ) {
+      if( !tab[i].valid ) {
+        tab[i].valid		= true;
+        tab[i].update		= update;
+        tab[i].brdcast      = brdcast;
+        tab[i].rsp          = rsp;
+        tab[i].srcid		= (size_t) srcid;
+        tab[i].trdid		= (size_t) trdid;
+        tab[i].pktid		= (size_t) pktid;
+        tab[i].nline		= (addr_t) nline;
+        tab[i].count		= (size_t) count;
+        index			    = i;
+        return true;
+      }
+    }
+    return false;
+  } // end set()
+
+  /////////////////////////////////////////////////////////////////////
+  // The decrement() function decrements the counter for a given entry.
+  // Arguments :
+  // - index   : the index of the entry
+  // - counter : (return argument) value of the counter after decrement
+  // This function returns true if the entry is valid.
+  /////////////////////////////////////////////////////////////////////
+  bool decrement( const size_t index,
+      size_t &counter ) 
+  {
+    assert((index<size_tab) && "Bad Update Tab Entry");
+    if ( tab[index].valid ) {
+      tab[index].count--;
+      counter = tab[index].count;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_full() function returns true if the table is full
+  /////////////////////////////////////////////////////////////////////
+  bool is_full()
+  {
+    for(size_t i = 0 ; i < size_tab ; i++){
+      if(!tab[i].valid){
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The need_rsp() function returns the need of a response
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool need_rsp(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].rsp;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_brdcast(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].brdcast;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The is_update() function returns the transaction type
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  bool is_update(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].update;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The srcid() function returns the srcid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t srcid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].srcid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The trdid() function returns the trdid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t trdid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].trdid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The pktid() function returns the pktid value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  size_t pktid(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].pktid;	
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The nline() function returns the nline value
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////
+  addr_t nline(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    return tab[index].nline;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The search_inval() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool search_inval(const addr_t nline,size_t &index)
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        if(!tab[i].update){
+          index = i ;
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read_nline() function returns the index of the entry in UPT
+  // Arguments :
+  // - nline : the line number of the entry in the directory
+  /////////////////////////////////////////////////////////////////////
+  bool read_nline(const addr_t nline,size_t &index) 
+  {
+    size_t i ;
+
+    for (i = 0 ; i < size_tab ; i++){
+      if((tab[i].nline == nline) && tab[i].valid){
+        index = i ;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The clear() function erases an entry of the tab
+  // Arguments :
+  // - index : the index of the entry
+  /////////////////////////////////////////////////////////////////////       
+  void clear(const size_t index)
+  {
+    assert(index<size_tab && "Bad Update Tab Entry");
+    tab[index].valid=false;
+    return;	
+  }
+
+};
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
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 2)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/vci_mem_cache_v4.h	(revision 2)
@@ -0,0 +1,707 @@
+/* -*- c++ -*-
+ * File         : vci_mem_cache_v4.h
+ * Date         : 26/10/2008
+ * Copyright    : UPMC / LIP6
+ * Authors      : Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+/*
+ *
+ * Modifications done by Christophe Choichillon on the 7/04/2009:
+ * - Adding new states in the CLEANUP FSM : CLEANUP_UPT_LOCK and CLEANUP_UPT_WRITE
+ * - Adding a new VCI target port for the CLEANUP network
+ * - Adding new state in the ALLOC_UPT_FSM : ALLOC_UPT_CLEANUP
+ * 
+ * Modifications to do :
+ * - Adding new variables used by the CLEANUP FSM
+ *
+ */
+
+#ifndef SOCLIB_CABA_MEM_CACHE_V4_H
+#define SOCLIB_CABA_MEM_CACHE_V4_H
+
+#include <inttypes.h>
+#include <systemc>
+#include <list>
+#include <cassert>
+#include "arithmetics.h"
+#include "alloc_elems.h"
+#include "caba_base_module.h"
+#include "vci_target.h"
+#include "vci_initiator.h"
+#include "generic_fifo.h"
+#include "mapping_table.h"
+#include "int_tab.h"
+#include "mem_cache_directory_v4.h"
+#include "xram_transaction_v4.h"
+#include "update_tab_v4.h"
+
+#define TRANSACTION_TAB_LINES 4     // Number of lines in the transaction tab
+#define UPDATE_TAB_LINES 4          // Number of lines in the update tab
+#define BROADCAST_ADDR 0x0000000003 // Address to send the broadcast invalidate
+
+namespace soclib {  namespace caba {
+  using namespace sc_core;
+
+  template<typename vci_param>
+    class VciMemCacheV4
+    : public soclib::caba::BaseModule
+    {
+      typedef sc_dt::sc_uint<40> addr_t;
+      typedef typename vci_param::fast_addr_t vci_addr_t;
+      typedef uint32_t data_t;
+      typedef uint32_t tag_t;
+      typedef uint32_t size_t;
+      typedef uint32_t be_t;
+      typedef uint32_t copy_t;
+
+      /* States of the TGT_CMD fsm */
+      enum tgt_cmd_fsm_state_e{
+        TGT_CMD_IDLE,
+        TGT_CMD_READ,
+        TGT_CMD_READ_EOP,
+        TGT_CMD_WRITE,
+        TGT_CMD_ATOMIC,
+      };
+
+      /* States of the TGT_RSP fsm */
+      enum tgt_rsp_fsm_state_e{
+        TGT_RSP_READ_IDLE,
+        TGT_RSP_WRITE_IDLE,
+        TGT_RSP_LLSC_IDLE,
+        TGT_RSP_XRAM_IDLE,
+        TGT_RSP_INIT_IDLE,
+        TGT_RSP_CLEANUP_IDLE,
+        TGT_RSP_READ,
+        TGT_RSP_WRITE,
+        TGT_RSP_LLSC,
+        TGT_RSP_XRAM,
+        TGT_RSP_INIT,
+        TGT_RSP_CLEANUP,
+      };
+
+      /* States of the INIT_CMD fsm */
+      enum init_cmd_fsm_state_e{
+        INIT_CMD_INVAL_IDLE,
+        INIT_CMD_INVAL_NLINE,
+        INIT_CMD_XRAM_BRDCAST,
+        INIT_CMD_UPDT_IDLE,
+        INIT_CMD_WRITE_BRDCAST,
+        INIT_CMD_UPDT_NLINE,
+        INIT_CMD_UPDT_INDEX,
+        INIT_CMD_UPDT_DATA,
+        INIT_CMD_SC_UPDT_IDLE,
+        INIT_CMD_SC_BRDCAST,
+        INIT_CMD_SC_UPDT_NLINE,
+        INIT_CMD_SC_UPDT_INDEX,
+        INIT_CMD_SC_UPDT_DATA,
+        INIT_CMD_SC_UPDT_DATA_HIGH,
+      };
+
+      /* States of the INIT_RSP fsm */
+      enum init_rsp_fsm_state_e{
+        INIT_RSP_IDLE,
+        INIT_RSP_UPT_LOCK,
+        INIT_RSP_UPT_CLEAR,
+        INIT_RSP_END,
+      };
+
+      /* States of the READ fsm */
+      enum read_fsm_state_e{
+        READ_IDLE,
+        READ_DIR_LOCK,
+        READ_DIR_HIT,
+        READ_HEAP_LOCK,
+        READ_HEAP_WRITE,
+        READ_HEAP_ERASE,
+        READ_HEAP_LAST,
+        READ_RSP,
+        READ_TRT_LOCK,
+        READ_TRT_SET,
+        READ_XRAM_REQ,
+      };
+
+      /* States of the WRITE fsm */
+      enum write_fsm_state_e{
+        WRITE_IDLE,
+        WRITE_NEXT,
+        WRITE_DIR_LOCK,
+        WRITE_DIR_HIT_READ,
+        WRITE_DIR_HIT,
+        WRITE_UPT_LOCK,
+        WRITE_HEAP_LOCK,
+        WRITE_UPT_REQ,
+        WRITE_UPDATE,
+        WRITE_UPT_DEC,
+        WRITE_RSP,
+        WRITE_TRT_LOCK,
+        WRITE_TRT_DATA,
+        WRITE_TRT_SET,
+        WRITE_WAIT,
+        WRITE_XRAM_REQ,
+        WRITE_TRT_WRITE_LOCK,
+        WRITE_INVAL_LOCK,
+        WRITE_DIR_INVAL,
+        WRITE_INVAL,
+        WRITE_XRAM_SEND,
+      };
+
+      /* States of the IXR_RSP fsm */
+      enum ixr_rsp_fsm_state_e{
+        IXR_RSP_IDLE,
+        IXR_RSP_ACK,
+        IXR_RSP_TRT_ERASE,
+        IXR_RSP_TRT_READ,
+      };
+
+      /* States of the XRAM_RSP fsm */
+      enum xram_rsp_fsm_state_e{
+        XRAM_RSP_IDLE,
+        XRAM_RSP_TRT_COPY,
+        XRAM_RSP_TRT_DIRTY,
+        XRAM_RSP_DIR_LOCK,
+        XRAM_RSP_DIR_UPDT,
+        XRAM_RSP_DIR_RSP,
+        XRAM_RSP_INVAL_LOCK,
+        XRAM_RSP_INVAL_WAIT,
+        XRAM_RSP_INVAL,
+        XRAM_RSP_WRITE_DIRTY,
+        XRAM_RSP_HEAP_ERASE,
+        XRAM_RSP_HEAP_LAST,
+      };
+
+      /* States of the IXR_CMD fsm */
+      enum ixr_cmd_fsm_state_e{
+        IXR_CMD_READ_IDLE,
+        IXR_CMD_WRITE_IDLE,
+        IXR_CMD_LLSC_IDLE,
+        IXR_CMD_XRAM_IDLE,
+        IXR_CMD_READ_NLINE,
+        IXR_CMD_WRITE_NLINE,
+        IXR_CMD_LLSC_NLINE,
+        IXR_CMD_XRAM_DATA,
+      };
+
+      /* States of the LLSC fsm */
+      enum llsc_fsm_state_e{
+        LLSC_IDLE,
+        SC_DIR_LOCK,
+        SC_DIR_HIT_READ,
+        SC_DIR_HIT_WRITE,
+        SC_UPT_LOCK,
+        SC_WAIT,
+        SC_HEAP_LOCK,
+        SC_UPT_REQ,
+        SC_UPDATE,
+        SC_TRT_LOCK,
+        SC_INVAL_LOCK,
+        SC_DIR_INVAL,
+        SC_INVAL,
+        SC_XRAM_SEND,
+        SC_RSP_FALSE,
+        SC_RSP_TRUE,
+        LLSC_TRT_LOCK,
+        LLSC_TRT_SET,
+        LLSC_XRAM_REQ,
+      };
+
+      /* States of the CLEANUP fsm */
+      enum cleanup_fsm_state_e{
+        CLEANUP_IDLE,
+        CLEANUP_DIR_LOCK,
+        CLEANUP_DIR_WRITE,
+        CLEANUP_HEAP_LOCK,
+        CLEANUP_HEAP_SEARCH,
+        CLEANUP_HEAP_CLEAN,
+        CLEANUP_HEAP_FREE,
+        CLEANUP_UPT_LOCK,
+        CLEANUP_UPT_WRITE,
+        CLEANUP_WRITE_RSP,
+        CLEANUP_RSP,
+      };
+
+      /* States of the ALLOC_DIR fsm */
+      enum alloc_dir_fsm_state_e{
+        ALLOC_DIR_READ,
+        ALLOC_DIR_WRITE,
+        ALLOC_DIR_LLSC,
+        ALLOC_DIR_CLEANUP,
+        ALLOC_DIR_XRAM_RSP,
+      };
+
+      /* States of the ALLOC_TRT fsm */
+      enum alloc_trt_fsm_state_e{
+        ALLOC_TRT_READ,
+        ALLOC_TRT_WRITE,
+        ALLOC_TRT_LLSC,
+        ALLOC_TRT_XRAM_RSP,
+        ALLOC_TRT_IXR_RSP,
+      };
+
+      /* States of the ALLOC_UPT fsm */
+      enum alloc_upt_fsm_state_e{
+        ALLOC_UPT_WRITE,
+        ALLOC_UPT_XRAM_RSP,
+        ALLOC_UPT_INIT_RSP,
+        ALLOC_UPT_CLEANUP,
+        ALLOC_UPT_LLSC,
+      };
+
+      /* States of the ALLOC_HEAP fsm */
+      enum alloc_heap_fsm_state_e{
+        ALLOC_HEAP_READ,
+        ALLOC_HEAP_WRITE,
+        ALLOC_HEAP_LLSC,
+        ALLOC_HEAP_CLEANUP,
+        ALLOC_HEAP_XRAM_RSP,
+      };
+
+      uint32_t	   m_cpt_cycles;            // Counter of cycles 
+      uint32_t	   m_cpt_read;              // Number of READ transactions
+      uint32_t	   m_cpt_read_miss;         // Number of MISS READ 
+      uint32_t	   m_cpt_write;             // Number of WRITE transactions
+      uint32_t	   m_cpt_write_miss;        // Number of MISS WRITE
+      uint32_t     m_cpt_write_cells;	    // Cumulated length for WRITE transactions
+      uint32_t     m_cpt_write_dirty;	    // Cumulated length for WRITE transactions
+      uint32_t	   m_cpt_update;            // Number of UPDATE transactions
+      uint32_t	   m_cpt_update_mult;       // Number of targets for UPDATE
+      uint32_t	   m_cpt_inval;             // Number of INVAL  transactions
+      uint32_t	   m_cpt_inval_mult;        // Number of targets for INVAL  
+      uint32_t	   m_cpt_inval_brdcast;     // Number of BROADCAST INVAL  
+      uint32_t	   m_cpt_cleanup;           // Number of CLEANUP transactions
+      uint32_t	   m_cpt_ll;                // Number of LL transactions
+      uint32_t	   m_cpt_sc;                // Number of SC transactions
+
+      protected:
+
+      SC_HAS_PROCESS(VciMemCacheV4);
+
+      public:
+      sc_in<bool> 			  	p_clk;
+      sc_in<bool> 			  	p_resetn;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt;
+      soclib::caba::VciTarget<vci_param>    	p_vci_tgt_cleanup;
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ini;	
+      soclib::caba::VciInitiator<vci_param> 	p_vci_ixr;
+
+      VciMemCacheV4(
+          sc_module_name name,                              // Instance Name 
+          const soclib::common::MappingTable &mtp,          // Mapping table for primary requets
+          const soclib::common::MappingTable &mtc,          // Mapping table for coherence requets
+          const soclib::common::MappingTable &mtx,          // Mapping table for XRAM
+          const soclib::common::IntTab &vci_ixr_index,      // VCI port to XRAM (initiator)
+          const soclib::common::IntTab &vci_ini_index,      // VCI port to PROC (initiator)
+          const soclib::common::IntTab &vci_tgt_index,      // VCI port to PROC (target)
+          const soclib::common::IntTab &vci_tgt_index_cleanup,    // VCI port to PROC (target) for cleanup
+          size_t nways,                                     // Number of ways per set 
+          size_t nsets,                                     // Number of sets
+          size_t nwords,                                    // Number of words per line
+          size_t heap_size=1024);                           // Size of the heap
+
+      ~VciMemCacheV4();
+
+      void transition();
+
+      void genMoore();
+
+      void print_stats();
+
+      private:
+
+      // Component attributes
+      const size_t              m_initiators;           // Number of initiators
+      const size_t              m_heap_size;            // Size of the heap
+      const size_t              m_ways;                 // Number of ways in a set
+      const size_t              m_sets;                 // Number of cache sets
+      const size_t              m_words;		        // Number of words in a line
+      const size_t              m_srcid_ixr;		    // Srcid for requests to XRAM 
+      const size_t              m_srcid_ini;		    // Srcid for requests to processors
+      std::list<soclib::common::Segment>  m_seglist;    // memory cached into the cache
+      std::list<soclib::common::Segment>  m_cseglist;   // coherence segment for the cache
+      vci_addr_t        		*m_coherence_table; 	// address(srcid)
+      TransactionTab      		m_transaction_tab;	    // xram transaction table
+      UpdateTab                 m_update_tab;		    // pending update & invalidate 
+      CacheDirectory			m_cache_directory;	    // data cache directory
+      HeapDirectory             m_heap_directory;       // heap directory
+
+      data_t	        	       ***m_cache_data;		// data array[set][way][word]
+
+      // adress masks
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_x;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_y;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_z;
+      const soclib::common::AddressMaskingTable<vci_addr_t>   m_nline; 
+
+      //////////////////////////////////////////////////
+      // Others registers
+      //////////////////////////////////////////////////
+      sc_signal<size_t>   r_copies_limit; // Limit of the number of copies for one line
+
+      //////////////////////////////////////////////////
+      // Registers controlled by the TGT_CMD fsm
+      //////////////////////////////////////////////////
+
+      // Fifo between TGT_CMD fsm and READ fsm
+      GenericFifo<uint64_t>  m_cmd_read_addr_fifo;
+      GenericFifo<size_t>    m_cmd_read_length_fifo;
+      GenericFifo<size_t>    m_cmd_read_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_read_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_read_pktid_fifo;
+
+      // Fifo between TGT_CMD fsm and WRITE fsm    
+      GenericFifo<uint64_t>  m_cmd_write_addr_fifo;
+      GenericFifo<bool>      m_cmd_write_eop_fifo;
+      GenericFifo<size_t>    m_cmd_write_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_write_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_write_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_write_data_fifo;
+      GenericFifo<be_t>	     m_cmd_write_be_fifo;
+
+      // Fifo between TGT_CMD fsm and LLSC fsm
+      GenericFifo<uint64_t>  m_cmd_llsc_addr_fifo;
+      GenericFifo<bool>      m_cmd_llsc_eop_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_srcid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_trdid_fifo;
+      GenericFifo<size_t>    m_cmd_llsc_pktid_fifo;
+      GenericFifo<data_t>    m_cmd_llsc_wdata_fifo;
+
+      sc_signal<int>         r_tgt_cmd_fsm;
+
+      sc_signal<size_t>	     r_index;
+      size_t nseg;
+      size_t ncseg;
+      soclib::common::Segment  **m_seg;
+      soclib::common::Segment  **m_cseg;
+      ///////////////////////////////////////////////////////
+      // Registers controlled by the READ fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>         r_read_fsm;        // FSM state 
+      sc_signal<size_t>      r_read_copy;       // Srcid of the first copy
+      sc_signal<bool>        r_read_copy_inst;  // Type of the first copy
+      sc_signal<tag_t>       r_read_tag;	    // cache line tag (in directory)
+      sc_signal<bool>        r_read_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>        r_read_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_read_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>      r_read_count;      // number of copies
+      sc_signal<size_t>      r_read_ptr;        // pointer to the heap
+      sc_signal<data_t>     *r_read_data;       // data (one cache line)
+      sc_signal<size_t>      r_read_way;        // associative way (in cache)
+      sc_signal<size_t>      r_read_trt_index;  // Transaction Table index
+      sc_signal<size_t>      r_read_next_ptr;   // Next entry to point to
+      sc_signal<bool>        r_read_last_free;  // Last free entry
+
+      // Buffer between READ fsm and IXR_CMD fsm (ask a missing cache line to XRAM)   
+      sc_signal<bool>        r_read_to_ixr_cmd_req;     // valid request
+      sc_signal<addr_t>      r_read_to_ixr_cmd_nline;   // cache line index
+      sc_signal<size_t>      r_read_to_ixr_cmd_trdid;   // index in Transaction Table
+
+      // Buffer between READ fsm and TGT_RSP fsm (send a hit read response to L1 cache)
+      sc_signal<bool>	   r_read_to_tgt_rsp_req;       // valid request
+      sc_signal<size_t>	   r_read_to_tgt_rsp_srcid;	    // Transaction srcid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_trdid;	    // Transaction trdid
+      sc_signal<size_t>	   r_read_to_tgt_rsp_pktid;	    // Transaction pktid
+      sc_signal<data_t>   *r_read_to_tgt_rsp_data;	    // data (one cache line)
+      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
+
+      ///////////////////////////////////////////////////////////////
+      // Registers controlled by the WRITE fsm
+      ///////////////////////////////////////////////////////////////
+
+      sc_signal<int>       r_write_fsm;             // FSM state
+      sc_signal<addr_t>	   r_write_address;         // first word address
+      sc_signal<size_t>    r_write_word_index;      // first word index in line
+      sc_signal<size_t>    r_write_word_count;      // number of words in line
+      sc_signal<size_t>    r_write_srcid;           // transaction srcid
+      sc_signal<size_t>    r_write_trdid;           // transaction trdid
+      sc_signal<size_t>    r_write_pktid;           // transaction pktid
+      sc_signal<data_t>	  *r_write_data;            // data (one cache line)	
+      sc_signal<be_t>     *r_write_be;              // one byte enable per word
+      sc_signal<bool>      r_write_byte;            // is it a byte write
+      sc_signal<bool>      r_write_is_cnt;          // is_cnt bit (in directory)
+      sc_signal<bool>      r_write_lock;            // lock bit (in directory)
+      sc_signal<tag_t>     r_write_tag;             // cache line tag (in directory)
+      sc_signal<size_t>    r_write_copy;            // first owner of the line
+      sc_signal<bool>      r_write_copy_inst;       // is this owner a ICache ?
+      sc_signal<size_t>	   r_write_count;           // number of copies
+      sc_signal<size_t>    r_write_ptr;             // pointer to the heap
+      sc_signal<size_t>    r_write_next_ptr;        // next pointer to the heap
+      sc_signal<bool>      r_write_to_dec;          // need to decrement update counter
+      sc_signal<size_t>	   r_write_way;		        // way of the line
+      sc_signal<size_t>    r_write_trt_index;	    // index in Transaction Table
+      sc_signal<size_t>    r_write_upt_index;	    // index in Update Table
+
+      // 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
+
+      // Buffer between WRITE fsm and IXR_CMD fsm (ask a missing cache line to XRAM) 
+      sc_signal<bool>	   r_write_to_ixr_cmd_req;      // valid request
+      sc_signal<bool>	   r_write_to_ixr_cmd_write;    // write request
+      sc_signal<addr_t>    r_write_to_ixr_cmd_nline; 	// cache line index
+      sc_signal<data_t>	  *r_write_to_ixr_cmd_data;	    // cache line data
+      sc_signal<size_t>    r_write_to_ixr_cmd_trdid;	// index in Transaction Table
+
+      // Buffer between WRITE fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>	   r_write_to_init_cmd_multi_req;   // valid multicast request
+      sc_signal<bool>	   r_write_to_init_cmd_brdcast_req; // valid brdcast request
+      sc_signal<addr_t>	   r_write_to_init_cmd_nline;	    // cache line index
+      sc_signal<size_t>	   r_write_to_init_cmd_trdid;	    // index in Update Table
+      sc_signal<data_t>   *r_write_to_init_cmd_data;	    // data (one cache line)
+      sc_signal<be_t>     *r_write_to_init_cmd_be;	        // word enable
+      sc_signal<size_t>	   r_write_to_init_cmd_count;	    // number of words in line
+      sc_signal<size_t>	   r_write_to_init_cmd_index;	    // index of first word in line
+      GenericFifo<bool>    m_write_to_init_cmd_inst_fifo;   // fifo for the L1 type
+      GenericFifo<size_t>  m_write_to_init_cmd_srcid_fifo;  // fifo for srcids
+
+      // Buffer between WRITE fsm and INIT_RSP fsm (Decrement UPT entry)
+      sc_signal<bool>      r_write_to_init_rsp_req;         // valid request
+      sc_signal<size_t>    r_write_to_init_rsp_upt_index;   // index in update table
+
+      /////////////////////////////////////////////////////////
+      // Registers controlled by INIT_RSP fsm
+      //////////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_init_rsp_fsm;        // FSM state
+      sc_signal<size_t>	   r_init_rsp_upt_index;  // index in the Update Table
+      sc_signal<size_t>	   r_init_rsp_srcid;	  // pending write srcid      
+      sc_signal<size_t>	   r_init_rsp_trdid;	  // pending write trdid      
+      sc_signal<size_t>	   r_init_rsp_pktid;	  // pending write pktid      
+      sc_signal<addr_t>	   r_init_rsp_nline;	  // pending write nline      
+
+      // Buffer between INIT_RSP fsm and TGT_RSP fsm (complete write/update transaction)
+      sc_signal<bool>	     r_init_rsp_to_tgt_rsp_req;   	// valid request
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_srcid;		// Transaction srcid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_trdid;		// Transaction trdid
+      sc_signal<size_t>	   r_init_rsp_to_tgt_rsp_pktid;		// Transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by CLEANUP fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int> 	     r_cleanup_fsm;         // FSM state
+      sc_signal<size_t>      r_cleanup_srcid;       // transaction srcid
+      sc_signal<size_t>      r_cleanup_trdid;       // transaction trdid
+      sc_signal<size_t>      r_cleanup_pktid;       // transaction pktid
+      sc_signal<addr_t>      r_cleanup_nline;       // cache line index
+
+      sc_signal<copy_t>      r_cleanup_copy;        // first copy
+      sc_signal<size_t>      r_cleanup_copy_inst;   // type of the first copy
+      sc_signal<copy_t>      r_cleanup_count;       // number of copies 
+      sc_signal<size_t>      r_cleanup_ptr;         // pointer to the heap
+      sc_signal<size_t>      r_cleanup_prev_ptr;    // previous pointer to the heap
+      sc_signal<size_t>      r_cleanup_prev_srcid;  // srcid of previous heap entry
+      sc_signal<bool>        r_cleanup_prev_inst;   // inst bit of previous heap entry
+      sc_signal<size_t>      r_cleanup_next_ptr;    // next pointer to the heap
+      sc_signal<tag_t>       r_cleanup_tag;	        // cache line tag (in directory)
+      sc_signal<bool>        r_cleanup_is_cnt;      // inst bit (in directory)
+      sc_signal<bool>        r_cleanup_lock;	    // lock bit (in directory)
+      sc_signal<bool>        r_cleanup_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>      r_cleanup_way;	        // associative way (in cache)
+
+      sc_signal<size_t>      r_cleanup_write_srcid; // srcid of write response
+      sc_signal<size_t>      r_cleanup_write_trdid; // trdid of write rsp
+      sc_signal<size_t>      r_cleanup_write_pktid; // pktid of write rsp
+      sc_signal<bool>        r_cleanup_need_rsp;    // needs a write rsp
+
+      sc_signal<size_t>      r_cleanup_index;	    // index of the INVAL line (in the UPT)
+
+      // Buffer between CLEANUP fsm and TGT_RSP fsm (acknowledge a write command from L1)
+      sc_signal<bool>      r_cleanup_to_tgt_rsp_req;    // valid request
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_srcid;  // transaction srcid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_trdid;	// transaction trdid
+      sc_signal<size_t>    r_cleanup_to_tgt_rsp_pktid;	// transaction pktid
+
+      ///////////////////////////////////////////////////////
+      // Registers controlled by LLSC fsm
+      ///////////////////////////////////////////////////////
+
+      sc_signal<int>       r_llsc_fsm;          // FSM state
+      sc_signal<data_t>	   r_llsc_wdata;		// write data word
+      sc_signal<data_t>	   *r_llsc_rdata;		// read data word
+      sc_signal<uint32_t>  r_llsc_lfsr;         // lfsr for random introducing
+      sc_signal<size_t>    r_llsc_cpt;  	    // size of command
+      sc_signal<copy_t>    r_llsc_copy; 	    // Srcid of the first copy
+      sc_signal<bool>      r_llsc_copy_inst;	// Type of the first copy
+      sc_signal<size_t>    r_llsc_count;	    // number of copies
+      sc_signal<size_t>    r_llsc_ptr;  	    // pointer to the heap
+      sc_signal<size_t>    r_llsc_next_ptr;  	// next pointer to the heap
+      sc_signal<bool>      r_llsc_is_cnt;	    // is_cnt bit (in directory)
+      sc_signal<bool>      r_llsc_dirty;	    // dirty bit (in directory)
+      sc_signal<size_t>    r_llsc_way;		    // way in directory
+      sc_signal<size_t>    r_llsc_set;		    // set in directory
+      sc_signal<data_t>    r_llsc_tag;		    // cache line tag (in directory)
+      sc_signal<size_t>    r_llsc_trt_index;    // Transaction Table index
+      sc_signal<size_t>    r_llsc_upt_index;    // Update Table index
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (XRAM read)	
+      sc_signal<bool>	   r_llsc_to_ixr_cmd_req;   // valid request
+      sc_signal<addr_t>	   r_llsc_to_ixr_cmd_nline; // cache line index
+      sc_signal<size_t>	   r_llsc_to_ixr_cmd_trdid; // index in Transaction Table
+      sc_signal<bool>	   r_llsc_to_ixr_cmd_write; // write request
+      sc_signal<data_t>	  *r_llsc_to_ixr_cmd_data;  // cache line data
+
+
+      // Buffer between LLSC fsm and TGT_RSP fsm
+      sc_signal<bool>	   r_llsc_to_tgt_rsp_req;   // valid request
+      sc_signal<data_t>    r_llsc_to_tgt_rsp_data;  // read data word
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_srcid; // Transaction srcid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_trdid; // Transaction trdid
+      sc_signal<size_t>	   r_llsc_to_tgt_rsp_pktid; // Transaction pktid
+
+      // Buffer between LLSC fsm and INIT_CMD fsm (Update/Invalidate L1 caches)
+      sc_signal<bool>	   r_llsc_to_init_cmd_multi_req;    // valid request
+      sc_signal<bool>	   r_llsc_to_init_cmd_brdcast_req;  // brdcast request
+      sc_signal<addr_t>	   r_llsc_to_init_cmd_nline;	    // cache line index
+      sc_signal<size_t>	   r_llsc_to_init_cmd_trdid;	    // index in Update Table
+      sc_signal<data_t>    r_llsc_to_init_cmd_wdata;        // data (one word)
+      sc_signal<bool>      r_llsc_to_init_cmd_is_long;      // it is a 64 bits SC
+      sc_signal<data_t>    r_llsc_to_init_cmd_wdata_high;   // data high (one word)
+      sc_signal<size_t>	   r_llsc_to_init_cmd_index;	    // index of the word in line
+      GenericFifo<bool>    m_llsc_to_init_cmd_inst_fifo;    // fifo for the L1 type
+      GenericFifo<size_t>  m_llsc_to_init_cmd_srcid_fifo;   // fifo for srcids
+
+      // Buffer between LLSC fsm and INIT_RSP fsm (Decrement UPT entry)
+      sc_signal<bool>      r_llsc_to_init_rsp_req;          // valid request
+      sc_signal<size_t>    r_llsc_to_init_rsp_upt_index;    // index in update table
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_rsp_fsm;       // FSM state
+      sc_signal<size_t>	   r_ixr_rsp_trt_index;	// TRT entry index
+      sc_signal<size_t>    r_ixr_rsp_cpt;	    // word counter
+
+      // Buffer between IXR_RSP fsm and XRAM_RSP fsm  (response from the XRAM)
+      sc_signal<bool>	  *r_ixr_rsp_to_xram_rsp_rok;	// A xram response is ready
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the XRAM_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_xram_rsp_fsm;		        // FSM state
+      sc_signal<size_t>	   r_xram_rsp_trt_index;	    // TRT entry index
+      TransactionTabEntry  r_xram_rsp_trt_buf;		    // TRT entry local buffer
+      sc_signal<bool>	   r_xram_rsp_victim_inval;	    // victim line invalidate 
+      sc_signal<bool>	   r_xram_rsp_victim_is_cnt;    // victim line inst bit
+      sc_signal<bool>	   r_xram_rsp_victim_dirty;	    // victim line dirty bit
+      sc_signal<size_t>    r_xram_rsp_victim_way;	    // victim line way
+      sc_signal<size_t>    r_xram_rsp_victim_set;	    // victim line set
+      sc_signal<addr_t>    r_xram_rsp_victim_nline;     // victim line index
+      sc_signal<copy_t>    r_xram_rsp_victim_copy;  	// victim line first copy
+      sc_signal<bool>      r_xram_rsp_victim_copy_inst;	// victim line type of first copy
+      sc_signal<size_t>    r_xram_rsp_victim_count;	    // victim line number of copies
+      sc_signal<size_t>    r_xram_rsp_victim_ptr;       // victim line pointer to the heap
+      sc_signal<data_t>	  *r_xram_rsp_victim_data;	    // victim line data
+      sc_signal<size_t>	   r_xram_rsp_upt_index;	    // UPT entry index
+      sc_signal<size_t>    r_xram_rsp_next_ptr;         // Next pointer to the heap
+
+      // Buffer between XRAM_RSP fsm and TGT_RSP fsm  (response to L1 cache)
+      sc_signal<bool>	   r_xram_rsp_to_tgt_rsp_req;	// Valid request
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_srcid;	// Transaction srcid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_trdid;	// Transaction trdid
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_pktid;	// Transaction pktid
+      sc_signal<data_t>   *r_xram_rsp_to_tgt_rsp_data;	// data (one cache line)
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_word;  // first word index
+      sc_signal<size_t>    r_xram_rsp_to_tgt_rsp_length;// length of the response
+
+      // Buffer between XRAM_RSP fsm and INIT_CMD fsm (Inval L1 Caches) 
+      sc_signal<bool>	    r_xram_rsp_to_init_cmd_multi_req;       // Valid request
+      sc_signal<bool>       r_xram_rsp_to_init_cmd_brdcast_req;     // Broadcast request
+      sc_signal<addr_t>     r_xram_rsp_to_init_cmd_nline;           // cache line index;
+      sc_signal<size_t>	    r_xram_rsp_to_init_cmd_trdid;           // index of UPT entry
+      GenericFifo<bool>     m_xram_rsp_to_init_cmd_inst_fifo;       // fifo for the L1 type
+      GenericFifo<size_t>   m_xram_rsp_to_init_cmd_srcid_fifo;      // fifo for srcids
+
+      // Buffer between XRAM_RSP fsm and IXR_CMD fsm (XRAM write)
+      sc_signal<bool>	   r_xram_rsp_to_ixr_cmd_req;	// Valid request
+      sc_signal<addr_t>	   r_xram_rsp_to_ixr_cmd_nline;	// cache line index
+      sc_signal<data_t>	  *r_xram_rsp_to_ixr_cmd_data;	// cache line data
+      sc_signal<size_t>	   r_xram_rsp_to_ixr_cmd_trdid;	// index in transaction table
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by the IXR_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_ixr_cmd_fsm;
+      sc_signal<size_t>	   r_ixr_cmd_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by TGT_RSP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	   r_tgt_rsp_fsm;
+      sc_signal<size_t>    r_tgt_rsp_cpt;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by INIT_CMD fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 	  r_init_cmd_fsm;
+      sc_signal<size_t>   r_init_cmd_cpt;
+      sc_signal<bool>     r_init_cmd_inst;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_DIR fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_dir_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_TRT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_trt_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_UPT fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_upt_fsm;
+
+      ////////////////////////////////////////////////////
+      // Registers controlled by ALLOC_HEAP fsm
+      ////////////////////////////////////////////////////
+
+      sc_signal<int> 		r_alloc_heap_fsm;
+
+    }; // end class VciMemCacheV4
+
+}}
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
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 2)
+++ trunk/modules/vci_mem_cache_v4/caba/source/include/xram_transaction_v4.h	(revision 2)
@@ -0,0 +1,404 @@
+#ifndef XRAM_TRANSACTION_V4_H_
+#define XRAM_TRANSACTION_V4_H_
+ 
+#include <inttypes.h>
+#include <systemc>
+#include <cassert>
+#include "arithmetics.h"
+
+#define DEBUG_XRAM_TRANSACTION 0
+
+////////////////////////////////////////////////////////////////////////
+//                  A transaction tab entry         
+////////////////////////////////////////////////////////////////////////
+
+class TransactionTabEntry {
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ public:
+  bool 		      valid;     	    // entry valid 
+  bool 		      xram_read; 	    // read request to XRAM
+  addr_t   	      nline;    	    // index (zy) of the requested line
+  size_t 	      srcid;     	    // processor requesting the transaction
+  size_t 	      trdid;     	    // processor requesting the transaction
+  size_t 	      pktid;     	    // processor requesting the transaction
+  bool 		      proc_read;	    // read request from processor
+  size_t 		  read_length;      // length of the read (for the response)
+  size_t 	      word_index;    	// index of the first read word (for the response)
+  std::vector<data_t> wdata;        // write buffer (one cache line)
+  std::vector<be_t>   wdata_be;    	// be for each data in the write buffer
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the entry 
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    valid		= false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The alloc() function initializes the vectors of an entry
+  // Its arguments are :
+  // - n_words : number of words per line in the cache
+  /////////////////////////////////////////////////////////////////////
+  void alloc(size_t n_words)
+  {
+    wdata_be.reserve( (int)n_words );
+    wdata.reserve( (int)n_words );
+    for(size_t i=0; i<n_words; i++){
+      wdata_be.push_back(false);
+      wdata.push_back(0);
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The copy() function copies an existing entry
+  // Its arguments are :
+  // - source : the transaction tab entry to copy
+  ////////////////////////////////////////////////////////////////////
+  void copy(const TransactionTabEntry &source)
+  {
+    valid	    = source.valid;
+    xram_read 	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read 	= source.proc_read;
+    read_length = source.read_length;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+  ////////////////////////////////////////////////////////////////////
+  // The print() function prints the entry 
+  ////////////////////////////////////////////////////////////////////
+  void print(){
+    std::cout << "valid       = " << valid        << std::endl;
+    std::cout << "xram_read   = " << xram_read    << std::endl;
+    std::cout << "nline       = " << std::hex << nline << std::endl;
+    std::cout << "srcid       = " << srcid        << std::endl;
+    std::cout << "trdid       = " << trdid        << std::endl;
+    std::cout << "pktid       = " << pktid        << std::endl;
+    std::cout << "proc_read   = " << proc_read    << std::endl;
+    std::cout << "read_length = " << read_length  << std::endl;
+    std::cout << "word_index  = " << word_index   << std::endl; 
+    for(size_t i=0; i<wdata_be.size() ; i++){
+      std::cout << "wdata_be [" << i <<"] = " << wdata_be[i] << std::endl;
+    }
+    for(size_t i=0; i<wdata.size() ; i++){
+      std::cout << "wdata [" << i <<"] = " << wdata[i] << std::endl;
+    }
+    std::cout << std::endl;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // 		Constructors
+  /////////////////////////////////////////////////////////////////////
+
+  TransactionTabEntry()
+    {
+      wdata_be.clear();
+      wdata.clear();
+      valid=false;
+    }
+
+  TransactionTabEntry(const TransactionTabEntry &source){
+    valid	    = source.valid;
+    xram_read	= source.xram_read;
+    nline	    = source.nline;
+    srcid	    = source.srcid;
+    trdid	    = source.trdid;
+    pktid	    = source.pktid;
+    proc_read	= source.proc_read;
+    read_length = source.read_length;
+    word_index	= source.word_index;
+    wdata_be.assign(source.wdata_be.begin(),source.wdata_be.end());
+    wdata.assign(source.wdata.begin(),source.wdata.end());	
+  }
+
+}; // end class TransactionTabEntry
+
+////////////////////////////////////////////////////////////////////////
+//                  The transaction tab                              
+////////////////////////////////////////////////////////////////////////
+class TransactionTab{
+  typedef uint32_t size_t;
+  typedef uint32_t data_t;
+  typedef sc_dt::sc_uint<40> addr_t;
+  typedef uint32_t be_t;
+
+ private:
+  size_t size_tab;                // The size of the tab
+
+  data_t be_to_mask(be_t be)
+  {
+    data_t ret = 0;
+    if ( be&0x1 ) {
+      ret = ret | 0x000000FF;
+    }
+    if ( be&0x2 ) {
+      ret = ret | 0x0000FF00;
+    }
+    if ( be&0x4 ) {
+      ret = ret | 0x00FF0000;
+    }
+    if ( be&0x8 ) {
+      ret = ret | 0xFF000000;
+    }
+    return ret;
+  }
+
+ public:
+  TransactionTabEntry *tab;       // The transaction tab
+
+  ////////////////////////////////////////////////////////////////////
+  //		Constructors
+  ////////////////////////////////////////////////////////////////////
+  TransactionTab()
+    {
+      size_tab=0;
+      tab=NULL;
+    }
+
+  TransactionTab(size_t n_entries, size_t n_words)
+    {
+      size_tab = n_entries;
+      tab = new TransactionTabEntry[size_tab];
+      for ( size_t i=0; i<size_tab; i++) {
+	tab[i].alloc(n_words);
+      }
+    }
+
+  ~TransactionTab()
+    {
+      delete [] tab;
+    }
+
+  /////////////////////////////////////////////////////////////////////
+  // The size() function returns the size of the tab
+  /////////////////////////////////////////////////////////////////////
+  size_t size()
+  {
+    return size_tab;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The init() function initializes the transaction tab entries
+  /////////////////////////////////////////////////////////////////////
+  void init()
+  {
+    for ( size_t i=0; i<size_tab; i++) {
+      tab[i].init();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The print() function prints a transaction tab entry
+  // Arguments :
+  // - index : the index of the entry to print
+  /////////////////////////////////////////////////////////////////////
+  void print(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    tab[index].print();
+    return;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The read() function returns a transaction tab entry.
+  // Arguments :
+  // - index : the index of the entry to read
+  /////////////////////////////////////////////////////////////////////
+  TransactionTabEntry read(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    return tab[index];
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The full() function returns the state of the transaction tab
+  // Arguments :
+  // - index : (return argument) the index of an empty entry 
+  // The function returns true if the transaction tab is full
+  /////////////////////////////////////////////////////////////////////
+  bool full(size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(!tab[i].valid){
+	    index=i;
+	    return false;	
+      }
+    }
+    return true;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The hit_read() function checks if an XRAM read transaction exists 
+  // for a given cache line.
+  // Arguments :
+  // - index : (return argument) the index of the hit entry, if there is 
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a read request has already been sent
+  //////////////////////////////////////////////////////////////////////
+  bool hit_read(const addr_t nline,size_t &index)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if((tab[i].valid && (nline==tab[i].nline)) && (tab[i].xram_read)) {
+	    index=i;
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  ///////////////////////////////////////////////////////////////////////
+  // The hit_write() function looks if an XRAM write transaction exists 
+  // for a given line.
+  // Arguments :
+  // - nline : the index (zy) of the requested line
+  // The function returns true if a write request has already been sent
+  ///////////////////////////////////////////////////////////////////////
+  bool hit_write(const addr_t nline)
+  {
+    for(size_t i=0; i<size_tab; i++){
+      if(tab[i].valid && (nline==tab[i].nline) && !(tab[i].xram_read)) {
+	    return true;	
+      }
+    }
+    return false;
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_data_mask() function writes a vector of data (a line).
+  // The data is written only if the corresponding bits are set
+  // in the be vector. 
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  // - be   : vector of be 
+  // - data : vector of data
+  /////////////////////////////////////////////////////////////////////
+  void write_data_mask(const size_t index, 
+		       const std::vector<be_t> &be, 
+		       const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "Invalid Transaction Tab Entry");
+    assert(be.size()==tab[index].wdata_be.size() 
+	   && "Bad data mask in write_data_mask in TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data in write_data_mask in TransactionTab");
+
+    for(size_t i=0; i<tab[index].wdata_be.size() ; i++) {
+      tab[index].wdata_be[i] = tab[index].wdata_be[i] | be[i];
+      data_t mask = be_to_mask(be[i]);
+      tab[index].wdata[i] = (tab[index].wdata[i] & ~mask) | (data[i] & mask);
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The set() function registers a transaction (read or write)
+  // to the XRAM in the transaction tab.
+  // Arguments :
+  // - index : index in the transaction tab
+  // - xram_read : transaction type (read or write a cache line)
+  // - nline : the index (zy) of the cache line
+  // - srcid : srcid of the initiator that caused the transaction
+  // - trdid : trdid of the initiator that caused the transaction
+  // - pktid : pktid of the initiator that caused the transaction
+  // - proc_read : does the initiator want a copy
+  // - read_length : length of read (in case of processor read)
+  // - word_index : index in the line (in case of single word read)
+  // - data : the data to write (in case of write)
+  // - data_be : the mask of the data to write (in case of write)
+  /////////////////////////////////////////////////////////////////////
+  void set(const size_t index,
+	   const bool xram_read,
+	   const addr_t nline,
+	   const size_t srcid,
+	   const size_t trdid,
+	   const size_t pktid,
+	   const bool proc_read,
+	   const size_t read_length,
+	   const size_t word_index,
+	   const std::vector<be_t> &data_be,
+	   const std::vector<data_t> &data) 
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in set() Transaction Tab");
+    assert(data_be.size()==tab[index].wdata_be.size() 
+	   && "Bad data_be argument in set() TransactionTab");
+    assert(data.size()==tab[index].wdata.size() 
+	   && "Bad data argument in set() TransactionTab");
+
+    tab[index].valid	        = true;
+    tab[index].xram_read        = xram_read;
+    tab[index].nline	        = nline;
+    tab[index].srcid	        = srcid;
+    tab[index].trdid	        = trdid;
+    tab[index].pktid	        = pktid;
+    tab[index].proc_read	    = proc_read;
+    tab[index].read_length	    = read_length;
+    tab[index].word_index	    = word_index;
+    for(size_t i=0; i<tab[index].wdata.size(); i++) {
+      tab[index].wdata_be[i]    = data_be[i];
+      tab[index].wdata[i]       = data[i];
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The write_rsp() function writes a word of the response to an 
+  // XRAM read transaction.
+  // The data is only written when the corresponding BE field is Ox0.
+  // Arguments :
+  // - index : the index of the transaction in the transaction tab
+  // - word_index : the index of the data in the line
+  // - data : the data to write
+  /////////////////////////////////////////////////////////////////////
+  void write_rsp(const size_t index,
+		 const size_t word,
+		 const data_t data)
+  {
+    assert( (index < size_tab) 
+	    && "Selected entry  out of range in write_rsp() Transaction Tab");
+    assert( (word <= tab[index].wdata_be.size()) 
+	    && "Bad word_index in write_rsp() in TransactionTab");
+    assert( tab[index].valid 
+	    && "Transaction Tab Entry invalid in write_rsp()");
+    assert( tab[index].xram_read 
+	    && "Selected entry is not an XRAM read transaction in write_rsp()");
+
+    data_t mask = be_to_mask(tab[index].wdata_be[word]);
+    tab[index].wdata[word] = (tab[index].wdata[word] & mask) | (data & ~mask);
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // The erase() function erases an entry in the transaction tab.
+  // Arguments :
+  // - index : the index of the request in the transaction tab
+  /////////////////////////////////////////////////////////////////////
+  void erase(const size_t index)
+  {
+    assert( (index < size_tab) 
+	    && "The selected entry is out of range in erase() Transaction Tab");
+    tab[index].valid	= false;
+  }
+}; // end class TransactionTab
+
+#endif
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
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 2)
+++ trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp	(revision 2)
@@ -0,0 +1,4441 @@
+/* -*- c++ -*-
+ * File 	: vci_mem_cache_v4.cpp
+ * Date 	: 30/10/2008
+ * Copyright 	: UPMC / LIP6
+ * Authors 	: Alain Greiner / Eric Guthmuller
+ *
+ * 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
+ *
+ * Maintainers: alain eric.guthmuller@polytechnique.edu
+ */
+#include "../include/vci_mem_cache_v4.h"
+
+//#define TDEBUG // Transaction tab debug
+//#define IDEBUG // Update tab debug
+//#define DDEBUG // Directory debug
+//#define DEBUG_VCI_MEM_CACHE 1
+#define RANDOMIZE_SC
+namespace soclib { namespace caba {
+
+#ifdef DEBUG_VCI_MEM_CACHE 
+  const char *tgt_cmd_fsm_str[] = {
+    "TGT_CMD_IDLE",
+    "TGT_CMD_READ",
+    "TGT_CMD_READ_EOP",
+    "TGT_CMD_WRITE",
+    "TGT_CMD_ATOMIC",
+  };
+  const char *tgt_rsp_fsm_str[] = {
+    "TGT_RSP_READ_IDLE",
+    "TGT_RSP_WRITE_IDLE",
+    "TGT_RSP_LLSC_IDLE",
+    "TGT_RSP_XRAM_IDLE",
+    "TGT_RSP_INIT_IDLE",
+    "TGT_RSP_CLEANUP_IDLE",
+    "TGT_RSP_READ",
+    "TGT_RSP_WRITE",
+    "TGT_RSP_LLSC",
+    "TGT_RSP_XRAM",
+    "TGT_RSP_INIT",
+    "TGT_RSP_CLEANUP",
+  };
+  const char *init_cmd_fsm_str[] = {
+    "INIT_CMD_INVAL_IDLE",
+    "INIT_CMD_INVAL_NLINE",
+    "INIT_CMD_XRAM_BRDCAST",
+    "INIT_CMD_UPDT_IDLE",
+    "INIT_CMD_WRITE_BRDCAST",
+    "INIT_CMD_UPDT_NLINE",
+    "INIT_CMD_UPDT_INDEX",
+    "INIT_CMD_UPDT_DATA",
+    "INIT_CMD_SC_UPDT_IDLE",
+    "INIT_CMD_SC_BRDCAST",
+    "INIT_CMD_SC_UPDT_NLINE",
+    "INIT_CMD_SC_UPDT_INDEX",
+    "INIT_CMD_SC_UPDT_DATA",
+    "INIT_CMD_SC_UPDT_DATA_HIGH",
+  };
+  const char *init_rsp_fsm_str[] = {
+    "INIT_RSP_IDLE",
+    "INIT_RSP_UPT_LOCK",
+    "INIT_RSP_UPT_CLEAR",
+    "INIT_RSP_END",
+  };
+  const char *read_fsm_str[] = {
+    "READ_IDLE",
+    "READ_DIR_LOCK",
+    "READ_DIR_HIT",
+    "READ_HEAP_LOCK",
+    "READ_HEAP_WRITE",
+    "READ_HEAP_ERASE",
+    "READ_HEAP_LAST",
+    "READ_RSP",
+    "READ_TRT_LOCK",
+    "READ_TRT_SET",
+    "READ_XRAM_REQ",
+  };
+  const char *write_fsm_str[] = {
+    "WRITE_IDLE",
+    "WRITE_NEXT",
+    "WRITE_DIR_LOCK",
+    "WRITE_DIR_HIT_READ",
+    "WRITE_DIR_HIT",
+    "WRITE_UPT_LOCK",
+    "WRITE_HEAP_LOCK",
+    "WRITE_UPT_REQ",
+    "WRITE_UPDATE",
+    "WRITE_UPT_DEC",
+    "WRITE_RSP",
+    "WRITE_TRT_LOCK",
+    "WRITE_TRT_DATA",
+    "WRITE_TRT_SET",
+    "WRITE_WAIT",
+    "WRITE_XRAM_REQ",
+    "WRITE_TRT_WRITE_LOCK",
+    "WRITE_INVAL_LOCK",
+    "WRITE_DIR_INVAL",
+    "WRITE_INVAL",
+    "WRITE_XRAM_SEND",
+  };
+  const char *ixr_rsp_fsm_str[] = {
+    "IXR_RSP_IDLE",
+    "IXR_RSP_ACK",
+    "IXR_RSP_TRT_ERASE",
+    "IXR_RSP_TRT_READ",
+  };
+  const char *xram_rsp_fsm_str[] = {
+    "XRAM_RSP_IDLE",
+    "XRAM_RSP_TRT_COPY",
+    "XRAM_RSP_TRT_DIRTY",
+    "XRAM_RSP_DIR_LOCK",
+    "XRAM_RSP_DIR_UPDT",
+    "XRAM_RSP_DIR_RSP",
+    "XRAM_RSP_INVAL_LOCK",
+    "XRAM_RSP_INVAL_WAIT",
+    "XRAM_RSP_INVAL",
+    "XRAM_RSP_WRITE_DIRTY",
+  };
+  const char *ixr_cmd_fsm_str[] = {
+    "IXR_CMD_READ_IDLE",
+    "IXR_CMD_WRITE_IDLE",
+    "IXR_CMD_LLSC_IDLE",
+    "IXR_CMD_XRAM_IDLE",
+    "IXR_CMD_READ_NLINE",
+    "IXR_CMD_WRITE_NLINE",
+    "IXR_CMD_LLSC_NLINE",
+    "IXR_CMD_XRAM_DATA",
+  };
+  const char *llsc_fsm_str[] = {
+    "LLSC_IDLE",
+    "SC_DIR_LOCK",
+    "SC_DIR_HIT_READ",
+    "SC_DIR_HIT_WRITE",
+    "SC_UPT_LOCK",
+    "SC_WAIT",
+    "SC_HEAP_LOCK",
+    "SC_UPT_REQ",
+    "SC_UPDATE",
+    "SC_TRT_LOCK",
+    "SC_INVAL_LOCK",
+    "SC_DIR_INVAL",
+    "SC_INVAL",
+    "SC_XRAM_SEND",
+    "SC_RSP_FALSE",
+    "SC_RSP_TRUE",
+    "LLSC_TRT_LOCK",
+    "LLSC_TRT_SET",
+    "LLSC_XRAM_REQ",
+  };
+  const char *cleanup_fsm_str[] = {
+    "CLEANUP_IDLE",
+    "CLEANUP_DIR_LOCK",
+    "CLEANUP_DIR_WRITE",
+    "CLEANUP_HEAP_LOCK",
+    "CLEANUP_HEAP_SEARCH",
+    "CLEANUP_HEAP_CLEAN",
+    "CLEANUP_HEAP_FREE",
+    "CLEANUP_UPT_LOCK",
+    "CLEANUP_UPT_WRITE",
+    "CLEANUP_WRITE_RSP",
+    "CLEANUP_RSP",
+  };
+  const char *alloc_dir_fsm_str[] = {
+    "ALLOC_DIR_READ",
+    "ALLOC_DIR_WRITE",
+    "ALLOC_DIR_LLSC",
+    "ALLOC_DIR_CLEANUP",
+    "ALLOC_DIR_XRAM_RSP",
+  };
+  const char *alloc_trt_fsm_str[] = {
+    "ALLOC_TRT_READ",
+    "ALLOC_TRT_WRITE",
+    "ALLOC_TRT_LLSC",
+    "ALLOC_TRT_XRAM_RSP",
+    "ALLOC_TRT_IXR_RSP",
+  };
+  const char *alloc_upt_fsm_str[] = {
+    "ALLOC_UPT_WRITE",
+    "ALLOC_UPT_XRAM_RSP",
+    "ALLOC_UPT_INIT_RSP",
+    "ALLOC_UPT_CLEANUP",
+  };
+  const char *alloc_heap_fsm_str[] = {
+    "ALLOC_HEAP_READ",
+    "ALLOC_HEAP_WRITE",
+    "ALLOC_HEAP_LLSC",
+    "ALLOC_HEAP_CLEANUP",
+    "ALLOC_HEAP_XRAM_RSP",
+  };
+
+#endif
+
+#define tmpl(x) template<typename vci_param> x VciMemCacheV4<vci_param>
+
+  using soclib::common::uint32_log2;
+
+  ////////////////////////////////
+  // 	Constructor 
+  ////////////////////////////////
+
+  tmpl(/**/)::VciMemCacheV4( 
+      sc_module_name name,
+      const soclib::common::MappingTable &mtp,
+      const soclib::common::MappingTable &mtc,
+      const soclib::common::MappingTable &mtx,
+      const soclib::common::IntTab &vci_ixr_index,
+      const soclib::common::IntTab &vci_ini_index,
+      const soclib::common::IntTab &vci_tgt_index,
+      const soclib::common::IntTab &vci_tgt_index_cleanup,
+      size_t nways,
+      size_t nsets,
+      size_t nwords,
+      size_t heap_size)
+
+    : soclib::caba::BaseModule(name),
+
+    p_clk("clk"),
+    p_resetn("resetn"),
+    p_vci_tgt("vci_tgt"),
+    p_vci_tgt_cleanup("vci_tgt_cleanup"),
+    p_vci_ini("vci_ini"),
+    p_vci_ixr("vci_ixr"),
+
+    m_initiators( 1 << vci_param::S ),
+    m_heap_size( heap_size ),
+    m_ways( nways ),
+    m_sets( nsets ),
+    m_words( nwords ),
+    m_srcid_ixr( mtx.indexForId(vci_ixr_index) ),
+    m_srcid_ini( mtc.indexForId(vci_ini_index) ),
+    m_seglist(mtp.getSegmentList(vci_tgt_index)),
+    m_cseglist(mtc.getSegmentList(vci_tgt_index_cleanup)),
+    m_coherence_table( mtc.getCoherenceTable<vci_addr_t>() ),
+    m_transaction_tab( TRANSACTION_TAB_LINES, nwords ),
+    m_update_tab( UPDATE_TAB_LINES ),
+    m_cache_directory( nways, nsets, nwords, vci_param::N ),
+    m_heap_directory( m_heap_size ),
+#define L2 soclib::common::uint32_log2
+    m_x( L2(m_words), 2),
+    m_y( L2(m_sets), L2(m_words) + 2),
+    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
+    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
+#undef L2
+
+    //  FIFOs 
+    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
+    m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
+    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
+    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
+    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
+
+    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
+    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
+    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
+    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
+    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
+    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
+    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
+
+    m_cmd_llsc_addr_fifo("m_cmd_llsc_addr_fifo",4),
+    m_cmd_llsc_eop_fifo("m_cmd_llsc_eop_fifo",4),
+    m_cmd_llsc_srcid_fifo("m_cmd_llsc_srcid_fifo",4),
+    m_cmd_llsc_trdid_fifo("m_cmd_llsc_trdid_fifo",4),
+    m_cmd_llsc_pktid_fifo("m_cmd_llsc_pktid_fifo",4),
+    m_cmd_llsc_wdata_fifo("m_cmd_llsc_wdata_fifo",4),
+
+    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
+    
+    nseg(0),	
+
+    r_read_fsm("r_read_fsm"),
+    r_write_fsm("r_write_fsm"),
+    m_write_to_init_cmd_inst_fifo("m_write_to_init_cmd_inst_fifo",8),
+    m_write_to_init_cmd_srcid_fifo("m_write_to_init_cmd_srcid_fifo",8),
+    r_init_rsp_fsm("r_init_rsp_fsm"),
+    r_cleanup_fsm("r_cleanup_fsm"),
+    r_llsc_fsm("r_llsc_fsm"),
+    m_llsc_to_init_cmd_inst_fifo("m_llsc_to_init_cmd_inst_fifo",8),
+    m_llsc_to_init_cmd_srcid_fifo("m_llsc_to_init_cmd_srcid_fifo",8),
+    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
+    r_xram_rsp_fsm("r_xram_rsp_fsm"),
+    m_xram_rsp_to_init_cmd_inst_fifo("m_xram_rsp_to_init_cmd_inst_fifo",8),
+    m_xram_rsp_to_init_cmd_srcid_fifo("m_xram_rsp_to_init_cmd_srcid_fifo",8),
+    r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
+    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
+    r_init_cmd_fsm("r_init_cmd_fsm"),
+    r_alloc_dir_fsm("r_alloc_dir_fsm"),
+    r_alloc_trt_fsm("r_alloc_trt_fsm"),
+    r_alloc_upt_fsm("r_alloc_upt_fsm")
+    {
+      assert(IS_POW_OF_2(nsets));
+      assert(IS_POW_OF_2(nwords));
+      assert(IS_POW_OF_2(nways));
+      assert(nsets);
+      assert(nwords);
+      assert(nways);
+      assert(nsets <= 1024);
+      assert(nwords <= 32);
+      assert(nways <= 32);
+
+
+      // Get the segments associated to the MemCache 
+      std::list<soclib::common::Segment>::iterator seg;
+
+      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
+        nseg++;
+      }
+      for(seg = m_cseglist.begin(); seg != m_cseglist.end() ; seg++) {
+        ncseg++;
+      }
+
+      m_seg = new soclib::common::Segment*[nseg];
+      size_t i = 0;
+      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) { 
+        m_seg[i] = &(*seg);
+        i++;
+      }
+      m_cseg = new soclib::common::Segment*[ncseg];
+      i = 0;
+      for ( seg = m_cseglist.begin() ; seg != m_cseglist.end() ; seg++ ) { 
+          m_cseg[i] = &(*seg);
+          i++;
+      }
+
+      // Memory cache allocation & initialisation
+      m_cache_data = new data_t**[nways];
+      for ( size_t i=0 ; i<nways ; ++i ) {
+        m_cache_data[i] = new data_t*[nsets];
+      }
+      for ( size_t i=0; i<nways; ++i ) {
+        for ( size_t j=0; j<nsets; ++j ) {
+          m_cache_data[i][j] = new data_t[nwords];
+          for ( size_t k=0; k<nwords; k++){
+            m_cache_data[i][j][k]=0;
+          }	
+        }
+      }
+
+      // Allocation for IXR_RSP FSM
+      r_ixr_rsp_to_xram_rsp_rok	    = new sc_signal<bool>[TRANSACTION_TAB_LINES];
+
+      // Allocation for XRAM_RSP FSM
+      r_xram_rsp_victim_data        = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_tgt_rsp_data    = new sc_signal<data_t>[nwords];
+      r_xram_rsp_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
+
+      // Allocation for READ FSM
+      r_read_data 			        = new sc_signal<data_t>[nwords];
+      r_read_to_tgt_rsp_data 		= new sc_signal<data_t>[nwords];
+
+      // Allocation for WRITE FSM
+      r_write_data 			        = new sc_signal<data_t>[nwords];
+      r_write_be 			        = new sc_signal<be_t>[nwords];
+      r_write_to_init_cmd_data 		= new sc_signal<data_t>[nwords];
+      r_write_to_init_cmd_be		= new sc_signal<be_t>[nwords];
+      r_write_to_ixr_cmd_data	    = new sc_signal<data_t>[nwords];
+
+      // Allocation for LLSC FSM
+      r_llsc_to_ixr_cmd_data	    = new sc_signal<data_t>[nwords];
+      r_llsc_rdata                  = new sc_signal<data_t>[2];
+
+
+      // Simulation
+
+      SC_METHOD(transition);
+      dont_initialize();
+      sensitive << p_clk.pos();
+
+      SC_METHOD(genMoore);
+      dont_initialize();
+      sensitive << p_clk.neg();
+
+    } // end constructor
+
+  /////////////////////////////////////////
+  // This function prints the statistics 
+  /////////////////////////////////////////
+
+  tmpl(void)::print_stats()
+  {
+    std::cout << "----------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
+      << "- READ RATE            = " << (double)m_cpt_read/m_cpt_cycles << std::endl
+      << "- READ MISS RATE       = " << (double)m_cpt_read_miss/m_cpt_read << std::endl
+      << "- WRITE RATE           = " << (double)m_cpt_write/m_cpt_cycles << std::endl
+      << "- WRITE MISS RATE      = " << (double)m_cpt_write_miss/m_cpt_write << std::endl
+      << "- WRITE BURST LENGTH   = " << (double)m_cpt_write_cells/m_cpt_write << std::endl
+      << "- UPDATE RATE          = " << (double)m_cpt_update/m_cpt_cycles << std::endl
+      << "- UPDATE ARITY         = " << (double)m_cpt_update_mult/m_cpt_update << std::endl
+      << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
+      << "- INVAL MULTICAST ARITY= " << (double)m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
+      << "- INVAL BROADCAST RATE = " << (double)m_cpt_inval_brdcast/m_cpt_cycles << std::endl
+      << "- SAVE DIRTY RATE      = " << (double)m_cpt_write_dirty/m_cpt_cycles << std::endl
+      << "- CLEANUP RATE         = " << (double)m_cpt_cleanup/m_cpt_cycles << std::endl
+      << "- LL RATE              = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
+      << "- SC RATE              = " << (double)m_cpt_sc/m_cpt_cycles << std::endl;
+  }
+
+  /////////////////////////////////
+  tmpl(/**/)::~VciMemCacheV4()
+    /////////////////////////////////
+  {
+    for(size_t i=0; i<m_ways ; i++){
+      for(size_t j=0; j<m_sets ; j++){
+        delete [] m_cache_data[i][j];
+      }
+    }
+    for(size_t i=0; i<m_ways ; i++){
+      delete [] m_cache_data[i];
+    }
+    delete [] m_cache_data;
+    delete [] m_coherence_table;
+
+    delete [] r_ixr_rsp_to_xram_rsp_rok;
+
+    delete [] r_xram_rsp_victim_data;
+    delete [] r_xram_rsp_to_tgt_rsp_data;
+    delete [] r_xram_rsp_to_ixr_cmd_data;
+
+    delete [] r_read_data;
+    delete [] r_read_to_tgt_rsp_data;
+
+    delete [] r_write_data;
+    delete [] r_write_be;
+    delete [] r_write_to_init_cmd_data;
+  }
+
+  //////////////////////////////////
+  tmpl(void)::transition()
+    //////////////////////////////////
+  {
+    using soclib::common::uint32_log2;
+    //  RESET          
+    if ( ! p_resetn.read() ) {
+
+      //     Initializing FSMs
+      r_tgt_cmd_fsm 	= TGT_CMD_IDLE;
+      r_tgt_rsp_fsm 	= TGT_RSP_READ_IDLE;
+      r_init_cmd_fsm 	= INIT_CMD_INVAL_IDLE;
+      r_init_rsp_fsm 	= INIT_RSP_IDLE;
+      r_read_fsm 	= READ_IDLE;
+      r_write_fsm 	= WRITE_IDLE;
+      r_llsc_fsm 	= LLSC_IDLE;
+      r_cleanup_fsm 	= CLEANUP_IDLE;
+      r_alloc_dir_fsm   = ALLOC_DIR_READ;
+      r_alloc_trt_fsm   = ALLOC_TRT_READ;
+      r_alloc_upt_fsm   = ALLOC_UPT_WRITE;
+      r_ixr_rsp_fsm 	= IXR_RSP_IDLE;
+      r_xram_rsp_fsm 	= XRAM_RSP_IDLE;
+      r_ixr_cmd_fsm 	= IXR_CMD_READ_IDLE;
+
+      //  Initializing Tables
+      m_cache_directory.init();
+      m_transaction_tab.init();
+      m_heap_directory.init();
+
+      // initializing FIFOs and communication Buffers
+
+      m_cmd_read_addr_fifo.init();
+      m_cmd_read_length_fifo.init();
+      m_cmd_read_srcid_fifo.init();
+      m_cmd_read_trdid_fifo.init();
+      m_cmd_read_pktid_fifo.init();
+
+      m_cmd_write_addr_fifo.init();
+      m_cmd_write_eop_fifo.init();
+      m_cmd_write_srcid_fifo.init();
+      m_cmd_write_trdid_fifo.init();
+      m_cmd_write_pktid_fifo.init();
+      m_cmd_write_data_fifo.init();
+
+      m_cmd_llsc_addr_fifo.init();
+      m_cmd_llsc_srcid_fifo.init();
+      m_cmd_llsc_trdid_fifo.init();
+      m_cmd_llsc_pktid_fifo.init();
+      m_cmd_llsc_wdata_fifo.init();
+      m_cmd_llsc_eop_fifo.init();
+
+      r_read_to_tgt_rsp_req	    = false;
+      r_read_to_ixr_cmd_req	    = false;
+
+      r_write_to_tgt_rsp_req	        = false;
+      r_write_to_ixr_cmd_req	        = false;
+      r_write_to_init_cmd_multi_req	    = false;
+      r_write_to_init_cmd_brdcast_req	= false;
+      r_write_to_init_rsp_req           = false;
+      m_write_to_init_cmd_inst_fifo.init();
+      m_write_to_init_cmd_srcid_fifo.init();
+
+      r_cleanup_to_tgt_rsp_req	= false;
+
+      r_init_rsp_to_tgt_rsp_req	= false;
+
+      r_llsc_to_tgt_rsp_req	            = false;
+      r_llsc_cpt                        = 0;
+      r_llsc_lfsr                       = -1;
+      r_llsc_to_ixr_cmd_req	            = false;
+      r_llsc_to_init_cmd_multi_req	    = false;
+      r_llsc_to_init_cmd_brdcast_req	= false;
+      m_llsc_to_init_cmd_inst_fifo.init();
+      m_llsc_to_init_cmd_srcid_fifo.init();
+
+      for(size_t i=0; i<TRANSACTION_TAB_LINES ; i++){
+        r_ixr_rsp_to_xram_rsp_rok[i] = false;
+      }
+
+      r_xram_rsp_to_tgt_rsp_req	            = false;
+      r_xram_rsp_to_init_cmd_multi_req      = false;
+      r_xram_rsp_to_init_cmd_brdcast_req    = false;
+      r_xram_rsp_to_ixr_cmd_req	            = false;
+      r_xram_rsp_trt_index	                = 0;
+      m_xram_rsp_to_init_cmd_inst_fifo.init();
+      m_xram_rsp_to_init_cmd_srcid_fifo.init();
+
+      r_ixr_cmd_cpt         = 0;
+
+      r_copies_limit        = 3;
+
+      // Activity counters
+      m_cpt_cycles		    = 0;
+      m_cpt_read		    = 0;
+      m_cpt_read_miss	    = 0;
+      m_cpt_write		    = 0;
+      m_cpt_write_miss	    = 0;
+      m_cpt_write_cells	    = 0;
+      m_cpt_write_dirty	    = 0;
+      m_cpt_update		    = 0;
+      m_cpt_update_mult     = 0;
+      m_cpt_inval_brdcast 	= 0;
+      m_cpt_inval 		    = 0;
+      m_cpt_inval_mult 		= 0;
+      m_cpt_cleanup		    = 0;
+      m_cpt_ll     		    = 0;
+      m_cpt_sc     		    = 0;
+
+      return;
+    }
+
+    bool    cmd_read_fifo_put = false;
+    bool    cmd_read_fifo_get = false;
+
+    bool    cmd_write_fifo_put = false;
+    bool    cmd_write_fifo_get = false;
+
+    bool    cmd_llsc_fifo_put = false;
+    bool    cmd_llsc_fifo_get = false;
+
+    bool    write_to_init_cmd_fifo_put   = false;
+    bool    write_to_init_cmd_fifo_get   = false;
+    bool    write_to_init_cmd_fifo_inst  = false;
+    size_t  write_to_init_cmd_fifo_srcid = 0;
+
+    bool    xram_rsp_to_init_cmd_fifo_put   = false;
+    bool    xram_rsp_to_init_cmd_fifo_get   = false;
+    bool    xram_rsp_to_init_cmd_fifo_inst  = false;
+    size_t  xram_rsp_to_init_cmd_fifo_srcid = 0;
+
+    bool    llsc_to_init_cmd_fifo_put   = false;
+    bool    llsc_to_init_cmd_fifo_get   = false;
+    bool    llsc_to_init_cmd_fifo_inst  = false;
+    size_t  llsc_to_init_cmd_fifo_srcid = 0;
+
+#if DEBUG_VCI_MEM_CACHE 
+    std::cout << "---------------------------------------------" << std::dec << std::endl;
+    std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
+      << " - TGT_CMD FSM    = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
+      << " - TGT_RSP FSM    = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
+      << " - INIT_CMD FSM   = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
+      << " - INIT_RSP FSM   = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
+      << " - READ FSM       = " << read_fsm_str[r_read_fsm] << std::endl
+      << " - WRITE FSM      = " << write_fsm_str[r_write_fsm] << std::endl
+      << " - LLSC FSM       = " << llsc_fsm_str[r_llsc_fsm] << std::endl
+      << " - CLEANUP FSM    = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
+      << " - IXR_CMD FSM    = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
+      << " - IXR_RSP FSM    = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
+      << " - XRAM_RSP FSM   = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
+      << " - ALLOC_DIR FSM  = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
+      << " - ALLOC_TRT FSM  = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
+      << " - ALLOC_UPT FSM  = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl
+      << " - ALLOC_HEAP FSM = " << alloc_heap_fsm_str[r_alloc_heap_fsm] << std::endl;
+#endif
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
+    //
+    // There is 4 types of packets for the m_mem_segment :
+    // - READ    : a READ request has a length of 1 VCI cell. It can be a single word 
+    //             or an entire cache line, depending on the PLEN value.
+    // - WRITE   : a WRITE request has a maximum length of 16 cells, and can only
+    //             concern words in a same line.
+    // - LL      : The LL request has a length of 1 cell.
+    // - SC      : The SC request has a length of 1 cell. 
+    //             The WDATA field contains the data to write.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_cmd_fsm.read() ) {
+
+      //////////////////
+      case TGT_CMD_IDLE:
+        {
+          if ( p_vci_tgt.cmdval ) {
+            assert( (p_vci_tgt.srcid.read() < m_initiators)
+                && "VCI_MEM_CACHE error in VCI_MEM_CACHE : The received SRCID is larger than the number of initiators");
+
+            bool reached = false;
+            for ( size_t index = 0 ; index < nseg && !reached ; index++) 
+            {
+//              if ( m_seg[index]->contains((addr_t)(p_vci_tgt.address.read())) ) {
+              if ( m_seg[index]->contains(p_vci_tgt.address.read()) ) {
+                reached = true;
+                r_index = index;
+              }
+            }
+
+
+            if ( !reached ) 
+            { 
+              std::cout << "VCI_MEM_CACHE Out of segment access in VCI_MEM_CACHE" << std::endl;
+              std::cout << "Faulty address = " << std::hex << (addr_t)(p_vci_tgt.address.read()) << std::endl;
+              std::cout << "Faulty initiator = " << std::dec << p_vci_tgt.srcid.read() << std::endl;
+              exit(0);
+            } 
+            else if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_READ;
+            } 
+            else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ) && ( p_vci_tgt.trdid.read() == 0x0 ))
+            {  
+              r_tgt_cmd_fsm = TGT_CMD_WRITE;
+            } 
+            else if ( p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND ) 
+            {
+              r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
+            } else {
+                std::cout << "MemCache error : wrong command " << std::endl;
+                exit(0);
+            }
+          }
+          break;
+        }
+        //////////////////
+      case TGT_CMD_READ:
+
+        {
+          assert(((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2))<=16)
+              && "VCI_MEM_CACHE All read request to the MemCache must stay within a cache line"); 
+
+          if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) {
+            cmd_read_fifo_put = true;
+            if ( p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+            else                  r_tgt_cmd_fsm = TGT_CMD_READ_EOP;		
+          } 
+          break;
+        }
+        //////////////////////
+      case TGT_CMD_READ_EOP:
+        {
+          if ( p_vci_tgt.cmdval && p_vci_tgt.eop ){
+            r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_CMD_WRITE:
+        {
+
+          if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() ) {
+            cmd_write_fifo_put = true;
+            if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
+
+          }
+          break;
+        }
+        ////////////////////
+      case TGT_CMD_ATOMIC:
+        {
+          if ( p_vci_tgt.cmdval && m_cmd_llsc_addr_fifo.wok() ) {
+            cmd_llsc_fifo_put = true;
+            if( p_vci_tgt.eop ) r_tgt_cmd_fsm = TGT_CMD_IDLE;
+          }
+          break;
+        }
+    } // end switch tgt_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////////
+    //		INIT_RSP FSM
+    /////////////////////////////////////////////////////////////////////////
+    // This FSM controls the response to the update or invalidate requests
+    // sent by the memory cache to the L1 caches :
+    //
+    // - update request initiated by the WRITE FSM.  
+    //   The FSM decrements the proper entry in the Update/Inval Table.
+    //   It sends a request to the TGT_RSP FSM to complete the pending 
+    //   write transaction (acknowledge response to the writer processor), 
+    //   and clear the UPT entry when all responses have been received.  
+    // - invalidate request initiated by the XRAM_RSP FSM.
+    //   The FSM decrements the proper entry in the Update/Inval_Table,
+    //   and clear the entry when all responses have been received.
+    //
+    // All those response packets are one word, compact
+    // packets complying with the VCI advanced format. 
+    // The index in the Table is defined in the RTRDID field, and
+    // the Transaction type is defined in the Update/Inval Table.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_rsp_fsm.read() ) {
+
+      ///////////////////
+      case INIT_RSP_IDLE:
+        {
+
+          if ( p_vci_ini.rspval ) {
+
+            assert ( ( p_vci_ini.rtrdid.read() < m_update_tab.size() )
+                && "VCI_MEM_CACHE UPT index too large in VCI response paquet received by memory cache" );
+            assert ( p_vci_ini.reop 
+                && "VCI_MEM_CACHE All response packets to update/invalidate requests must be one cell" );
+            r_init_rsp_upt_index = p_vci_ini.rtrdid.read(); 
+            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
+          } else if( r_write_to_init_rsp_req.read() ){
+            r_init_rsp_upt_index = r_write_to_init_rsp_upt_index.read();
+            r_write_to_init_rsp_req = false;
+            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
+          }
+          break;
+        }
+        ///////////////////////
+      case INIT_RSP_UPT_LOCK:	// decrement the number of expected responses
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) { 
+            size_t count = 0;
+            bool valid  = m_update_tab.decrement(r_init_rsp_upt_index.read(), count);
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+#endif
+            assert ( valid 
+                && "VCI_MEM_CACHE Invalid UPT entry in VCI response paquet received by memory cache" );
+
+            if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
+            else              r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_RSP_UPT_CLEAR:	// clear the UPT entry
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) {
+            r_init_rsp_srcid = m_update_tab.srcid(r_init_rsp_upt_index.read());
+            r_init_rsp_trdid = m_update_tab.trdid(r_init_rsp_upt_index.read());
+            r_init_rsp_pktid = m_update_tab.pktid(r_init_rsp_upt_index.read());
+            r_init_rsp_nline = m_update_tab.nline(r_init_rsp_upt_index.read());
+            bool need_rsp = m_update_tab.need_rsp(r_init_rsp_upt_index.read());
+            if ( need_rsp ) r_init_rsp_fsm = INIT_RSP_END;
+            else            r_init_rsp_fsm = INIT_RSP_IDLE;
+            m_update_tab.clear(r_init_rsp_upt_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " INIT_RSP_UPT_CLEAR update table : " << std::endl;
+	m_update_tab.print();
+#endif
+          }
+          break;
+        }
+        //////////////////
+      case INIT_RSP_END:
+        {
+
+          if ( !r_init_rsp_to_tgt_rsp_req ) {
+            r_init_rsp_to_tgt_rsp_req = true;
+            r_init_rsp_to_tgt_rsp_srcid = r_init_rsp_srcid.read();
+            r_init_rsp_to_tgt_rsp_trdid = r_init_rsp_trdid.read();
+            r_init_rsp_to_tgt_rsp_pktid = r_init_rsp_pktid.read();
+            r_init_rsp_fsm = INIT_RSP_IDLE;
+          }
+          break;
+        }
+    } // end switch r_init_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		READ FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The READ FSM controls the read requests sent by processors.
+    // It takes the lock protecting the cache directory to check the cache line status:
+    // - In case of HIT, the fsm copies the data (one line, or one single word)
+    //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
+    //   The requesting initiator is registered in the cache directory.
+    // - In case of MISS, the READ fsm takes the lock protecting the transaction tab.
+    //   If a read transaction to the XRAM for this line already exists,
+    //   or if the transaction tab is full, the fsm is stalled.
+    //   If a transaction entry is free, the READ fsm sends a request to the XRAM.
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_read_fsm.read() ) {
+
+      ///////////////
+      case READ_IDLE:
+        {
+          if (m_cmd_read_addr_fifo.rok()) {
+            m_cpt_read++;
+            r_read_fsm = READ_DIR_LOCK;
+          }
+          break;
+        }
+        ///////////////////
+      case READ_DIR_LOCK:	// check directory for hit / miss
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            size_t way = 0;
+            DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
+#ifdef DDEBUG
+	   std::cout << "In READ_DIR_LOCK printing the entry of address is : " << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            r_read_is_cnt   = entry.is_cnt;
+            r_read_dirty    = entry.dirty;
+            r_read_lock	    = entry.lock;
+            r_read_tag	    = entry.tag;
+            r_read_way	    = way;
+            r_read_count    = entry.count;
+            r_read_copy     = entry.owner.srcid; 
+            r_read_copy_inst= entry.owner.inst;
+            r_read_ptr      = entry.ptr;
+
+            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
+            // In case of hit, the read acces must be registered in the copies bit-vector
+            if(  entry.valid ) {
+              if(entry.is_cnt || (entry.count == 0) || !cached_read)  { // No new entry in the heap
+                r_read_fsm = READ_DIR_HIT;
+              } else {
+                r_read_fsm = READ_HEAP_LOCK;
+              }
+            } else {
+              r_read_fsm = READ_TRT_LOCK;
+              m_cpt_read_miss++;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_DIR_HIT:	// read hit : update the memory cache
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
+            // signals generation
+            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
+            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
+            bool is_cnt = r_read_is_cnt.read();
+
+            // read data in the cache
+            size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            size_t way = r_read_way.read();
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_data[i] = m_cache_data[way][set][i];
+            }
+
+            // update the cache directory (for the copies)
+            DirectoryEntry entry;
+            entry.valid	  = true;
+            entry.is_cnt  = is_cnt; 
+            entry.dirty	  = r_read_dirty.read();
+            entry.tag	  = r_read_tag.read();
+            entry.lock	  = r_read_lock.read();
+            entry.ptr     = 0;
+            if(cached_read){  // Cached read, we update the copy
+              if(!is_cnt){ // Not counter mode
+                entry.owner.srcid   = m_cmd_read_srcid_fifo.read();
+                entry.owner.inst    = inst_read;
+                entry.count         = r_read_count.read() + 1;
+              } else { // Counter mode
+                entry.owner.srcid   = 0;
+                entry.owner.inst    = false;
+                entry.count         = r_read_count.read() + 1;
+              } 
+            } else { // Uncached read
+              entry.owner.srcid     = r_read_copy.read();
+              entry.owner.inst      = r_read_copy_inst.read();
+              entry.count           = r_read_count.read();
+            }
+#ifdef DDEBUG
+	   std::cout << "In READ_DIR_HIT printing the entry of address is : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            m_cache_directory.write(set, way, entry);
+            r_read_fsm    = READ_RSP;
+          }
+          break;
+        }
+        //////////////
+      case READ_HEAP_LOCK:
+        {
+          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ ) {
+            bool is_cnt = (r_read_count.read() >= r_copies_limit.read()) || m_heap_directory.is_full();
+            // read data in the cache
+            size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            size_t way = r_read_way.read();
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_data[i] = m_cache_data[way][set][i];
+            }
+
+            // update the cache directory (for the copies)
+            DirectoryEntry entry;
+            entry.valid	  = true;
+            entry.is_cnt  = is_cnt; // when we reach the limit of copies or the heap is full
+            entry.dirty	  = r_read_dirty.read();
+            entry.tag	  = r_read_tag.read();
+            entry.lock	  = r_read_lock.read();
+            if(!is_cnt){ // Not counter mode
+                entry.owner.srcid   = r_read_copy.read();
+                entry.owner.inst    = r_read_copy_inst.read();
+                entry.count         = r_read_count.read() + 1;
+                entry.ptr           = m_heap_directory.next_free_ptr();
+            } else { // Counter mode
+                entry.owner.srcid   = 0;
+                entry.owner.inst    = false;
+                entry.count         = r_read_count.read() + 1;
+                entry.ptr           = 0;
+            }
+#ifdef DDEBUG
+	   std::cout << "In READ_HEAP_LOCK printing the entry of address is : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+            m_cache_directory.write(set, way, entry);
+
+            if(!is_cnt){
+              HeapEntry free_heap_entry = m_heap_directory.next_free_entry();
+              r_read_next_ptr = free_heap_entry.next;
+              if( free_heap_entry.next == m_heap_directory.next_free_ptr() ) { // Last free heap entry
+                r_read_last_free = true;
+              } else {
+                r_read_last_free = false;
+              }
+              r_read_fsm = READ_HEAP_WRITE; // we add an entry in the list of copies
+            } else {
+              if(r_read_count.read()>1) { // else there is no list of copies...
+                HeapEntry next_entry = m_heap_directory.read(r_read_ptr.read());
+                r_read_next_ptr = m_heap_directory.next_free_ptr();
+                m_heap_directory.write_free_ptr(r_read_ptr.read());
+                if( next_entry.next == r_read_ptr.read() ) { // The last list member
+                  r_read_fsm = READ_HEAP_LAST; // we erase the list of copies (counter mode)
+                } else { // Not the end of the list
+                  r_read_ptr = next_entry.next;
+                  r_read_fsm = READ_HEAP_ERASE; // we erase the list of copies (counter mode)
+                }
+              } else {
+                r_read_fsm = READ_RSP;
+              }
+            }
+          }
+          break;
+        }
+        //////////////
+      case READ_HEAP_WRITE:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
+            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
+            HeapEntry new_heap_entry;
+            new_heap_entry.owner.srcid  = m_cmd_read_srcid_fifo.read();
+            new_heap_entry.owner.inst   = inst_read;
+            if(r_read_count.read() == 1){ // creation of a new list
+              new_heap_entry.next         = m_heap_directory.next_free_ptr(); 
+            } else {                      // it is an insertion
+              new_heap_entry.next         = r_read_ptr.read();
+            }
+            m_heap_directory.write_free_entry(new_heap_entry);
+            m_heap_directory.write_free_ptr(r_read_next_ptr.read());
+            if(r_read_last_free.read()) {
+              m_heap_directory.set_full();
+            }
+
+            r_read_fsm = READ_RSP;
+          } else {
+            assert(false && "MEMCACHE Error : Bad HEAP allocation");
+          }
+          break;
+        }
+        //////////////
+      case READ_HEAP_ERASE:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
+            HeapEntry next_entry = m_heap_directory.read(r_read_ptr.read());
+            if( next_entry.next == r_read_ptr.read() ){
+              r_read_fsm = READ_HEAP_LAST;
+            } else {
+              r_read_ptr = next_entry.next;
+              r_read_fsm = READ_HEAP_ERASE;
+            }
+          } else {
+            assert(false && "MEMCACHE Error : Bad HEAP allocation");
+          }
+          break;
+        }
+        //////////////
+      case READ_HEAP_LAST:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
+            HeapEntry last_entry;
+            last_entry.owner.srcid = 0;
+            last_entry.owner.inst  = false;
+            if(m_heap_directory.is_full()){
+              last_entry.next      = r_read_ptr.read();
+              m_heap_directory.unset_full();
+            } else {
+              last_entry.next      = r_read_next_ptr.read();
+            }
+            m_heap_directory.write(r_read_ptr.read(),last_entry);
+            r_read_fsm = READ_RSP;
+          } else {
+            assert(false && "MEMCACHE Error : Bad HEAP allocation");
+          }
+          break;
+        }
+        //////////////
+      case READ_RSP: 		//  request the TGT_RSP FSM to return data
+        {
+          if( !r_read_to_tgt_rsp_req ) {	
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              r_read_to_tgt_rsp_data[i] = r_read_data[i];
+            }
+            r_read_to_tgt_rsp_word   = m_x[(vci_addr_t)m_cmd_read_addr_fifo.read()];
+            r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
+            cmd_read_fifo_get 		 = true;
+            r_read_to_tgt_rsp_req	 = true;
+            r_read_to_tgt_rsp_srcid	 = m_cmd_read_srcid_fifo.read();
+            r_read_to_tgt_rsp_trdid	 = m_cmd_read_trdid_fifo.read();
+            r_read_to_tgt_rsp_pktid	 = m_cmd_read_pktid_fifo.read();
+            r_read_fsm 			     = READ_IDLE;  
+          }
+          break;
+        }
+        ///////////////////
+      case READ_TRT_LOCK:	// read miss : check the Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t index = 0;
+            bool   hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())], index);
+            bool   hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())]);
+            bool   wok = !m_transaction_tab.full(index);
+            if( hit_read || !wok || hit_write ) {  // missing line already requested or no space
+              r_read_fsm = READ_IDLE;
+            } else {			   // missing line is requested to the XRAM
+              r_read_trt_index = index;
+              r_read_fsm       = READ_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case READ_TRT_SET:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
+            m_transaction_tab.set(r_read_trt_index.read(),
+                true,
+                m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
+                m_cmd_read_srcid_fifo.read(),
+                m_cmd_read_trdid_fifo.read(),
+                m_cmd_read_pktid_fifo.read(),
+                true,
+                m_cmd_read_length_fifo.read(),
+                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));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_read_fsm 	 = READ_XRAM_REQ;
+          }
+          break;
+        }
+        /////////////////////
+      case READ_XRAM_REQ:
+        {
+          if( !r_read_to_ixr_cmd_req ) {
+            cmd_read_fifo_get		= true;
+            r_read_to_ixr_cmd_req  	= true;
+            r_read_to_ixr_cmd_nline 	= m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
+            r_read_to_ixr_cmd_trdid 	= r_read_trt_index.read();
+            r_read_fsm 			          = READ_IDLE;
+          }
+          break;
+        }
+    } // end switch read_fsm
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //		WRITE FSM
+    ///////////////////////////////////////////////////////////////////////////////////
+    // The WRITE FSM handles the write bursts 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.
+    // Then the FSM takes the lock protecting the cache directory, to check
+    // if the line is in the cache.
+    //
+    // - In case of HIT, the cache is updated.
+    //   If there is no other copy, an acknowledge response is immediately
+    //   returned to the writing processor.
+    //   if the data is cached by other processoris, the FSM takes the lock
+    //   protecting the Update Table (UPT) to register this update transaction.
+    //   If the UPT is full, it releases the lock  and waits. Then, it sends 
+    //   a multi-update request to all owners of the line (but the writer), 
+    //   through the INIT_CMD FSM. In case of multi-update transaction, the WRITE FSM 
+    //   does not respond to the writing processor, as this response will be sent by 
+    //   the INIT_RSP FSM when all update responses have been received.
+    //
+    // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
+    //   table (TRT). If a read transaction to the XRAM for this line already exists, 
+    //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free, 
+    //   the WRITE FSM register a new transaction in TRT, and sends a read line request 
+    //   to the XRAM. If the TRT is full, it releases the lock, and waits.
+    //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_write_fsm.read() ) {
+
+      ////////////////
+      case WRITE_IDLE:	// copy first word of a write burst in local buffer	
+        {
+          if ( m_cmd_write_addr_fifo.rok()) {
+            m_cpt_write++;
+            m_cpt_write_cells++;
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get	= true;
+            size_t 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();
+            r_write_srcid	    = m_cmd_write_srcid_fifo.read();
+            r_write_trdid	    = m_cmd_write_trdid_fifo.read();
+            r_write_pktid	    = m_cmd_write_pktid_fifo.read();
+
+            // the be field must be set for all words 
+            for ( size_t i=0 ; i<m_words ; i++ ) {
+              if ( i == index ) r_write_be[i] = m_cmd_write_be_fifo.read();
+              else		        r_write_be[i] = 0x0;
+            }
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+                    r_write_byte=true;
+            else    r_write_byte=false;
+
+            if( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+            else                               r_write_fsm = WRITE_NEXT;
+          }
+          break;
+        }
+        ////////////////
+      case WRITE_NEXT:	// copy next word of a write burst in local buffer
+        {
+          if ( m_cmd_write_addr_fifo.rok() ) {
+            m_cpt_write_cells++;
+
+            // check that the next word is in the same cache line
+            assert( (m_nline[(vci_addr_t)(r_write_address.read())] == m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())])  
+                && "VCI_MEM_CACHE write error in vci_mem_cache : write burst over a line" );
+            // consume a word in the FIFO & write it in the local buffer 
+            cmd_write_fifo_get=true;
+            size_t index 	        = r_write_word_index.read() + r_write_word_count.read();
+            r_write_be[index]       = m_cmd_write_be_fifo.read();
+            r_write_data[index]     = m_cmd_write_data_fifo.read();
+            r_write_word_count 	    = r_write_word_count.read() + 1;
+            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
+              r_write_byte=true;
+            if ( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_LOCK:	// access directory to check hit/miss
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ) {
+            size_t  way = 0;
+            DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
+
+            // copy directory entry in local buffers in case of hit
+            if ( entry.valid )  {	
+              r_write_is_cnt    = entry.is_cnt;
+              r_write_lock	    = entry.lock;
+              r_write_tag       = entry.tag;
+              r_write_copy      = entry.owner.srcid;
+              r_write_copy_inst = entry.owner.inst;
+              r_write_count     = entry.count;
+              r_write_ptr       = entry.ptr;
+              r_write_way  	    = way;
+              if( entry.is_cnt && entry.count ) {
+                r_write_fsm      = WRITE_DIR_HIT_READ;
+              } else {
+                if(r_write_byte.read())
+                  r_write_fsm      = WRITE_DIR_HIT_READ;
+                else  r_write_fsm  = WRITE_DIR_HIT;
+              }
+            } else {
+              r_write_fsm = WRITE_TRT_LOCK;
+              m_cpt_write_miss++;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT_READ:	// read the cache and complete the buffer (data, when be!=0xF)
+        {
+          // update local buffer
+          size_t set	= m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	= r_write_way.read();
+          for(size_t i=0 ; i<m_words ; i++) {
+            data_t mask      = 0;
+            if  (r_write_be[i].read() & 0x1) mask = mask | 0x000000FF;
+            if  (r_write_be[i].read() & 0x2) mask = mask | 0x0000FF00;
+            if  (r_write_be[i].read() & 0x4) mask = mask | 0x00FF0000;
+            if  (r_write_be[i].read() & 0x8) mask = mask | 0xFF000000;
+            if(r_write_be[i].read()||r_write_is_cnt.read()) { // complete only if mask is not null (for energy consumption)
+              r_write_data[i]  = (r_write_data[i].read() & mask) | 
+                (m_cache_data[way][set][i] & ~mask);
+            }
+          } // end for
+
+          if( r_write_is_cnt.read() && r_write_count.read() ) {
+            r_write_fsm            = WRITE_TRT_WRITE_LOCK;
+          } else {
+            r_write_fsm            = WRITE_DIR_HIT;
+          }
+          break;
+        }
+        ///////////////////
+      case WRITE_DIR_HIT:	// update the cache (data & dirty bit)
+        {
+          // update directory with Dirty bit
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.dirty	    = true;
+          entry.tag	        = r_write_tag.read();
+          entry.is_cnt      = r_write_is_cnt.read();
+          entry.lock	    = r_write_lock.read();
+          entry.owner.srcid = r_write_copy.read();
+          entry.owner.inst  = r_write_copy_inst.read();
+          entry.count       = r_write_count.read();
+          entry.ptr         = r_write_ptr.read();
+          size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+          size_t way	    = r_write_way.read();
+          m_cache_directory.write(set, way, entry);
+
+          bool owner = (r_write_copy.read()==r_write_srcid.read()) && !r_write_copy_inst.read();
+          bool no_update = (r_write_count.read()==0) || ( owner && (r_write_count.read()==1));
+
+          if( no_update ) // no update
+          {
+            // write data in cache
+            for(size_t i=0 ; i<m_words ; i++) {
+              if  ( r_write_be[i].read() ) {
+                m_cache_data[way][set][i]  = r_write_data[i].read();
+              }
+            } // end for
+          }
+
+          size_t count_signal   = r_write_count.read();
+          if(owner){
+            count_signal        = count_signal - 1;
+          }
+          r_write_count         = count_signal;
+          r_write_to_dec        = false;
+
+          if ( no_update )      r_write_fsm = WRITE_RSP;
+          else                  r_write_fsm = WRITE_UPT_LOCK;
+          break;
+        }
+        /////////////////////
+      case WRITE_UPT_LOCK: 	// Try to register the request in Update Table
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool        wok        = false;
+            size_t      index      = 0;
+            size_t      srcid      = r_write_srcid.read();
+            size_t      trdid      = r_write_trdid.read();
+            size_t      pktid      = r_write_pktid.read();
+            addr_t      nline      = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t      nb_copies  = r_write_count.read();
+            size_t set	    = m_y[(vci_addr_t)(r_write_address.read())];
+            size_t way	    = r_write_way.read();
+
+            wok =m_update_tab.set(true,	// it's an update transaction
+                false,                  // it's not a broadcast
+                true,                   // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+            if(wok){
+              // write data in cache
+              for(size_t i=0 ; i<m_words ; i++) {
+                if  ( r_write_be[i].read() ) {
+                  m_cache_data[way][set][i]  = r_write_data[i].read();
+                }
+              } // end for
+            }
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting the Update Table and the Directory if no entry...
+            if ( wok ) r_write_fsm = WRITE_HEAP_LOCK;
+            else       r_write_fsm = WRITE_WAIT;
+          }
+          break;
+        }
+        //////////////////
+      case WRITE_HEAP_LOCK:
+        {
+          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE ){
+            r_write_fsm = WRITE_UPT_REQ;
+          }
+          break;
+        }
+        //////////////////
+      case WRITE_UPT_REQ:
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          if( !r_write_to_init_cmd_multi_req.read() && 
+              !r_write_to_init_cmd_brdcast_req.read()  ){
+            r_write_to_init_cmd_brdcast_req  = false;
+            r_write_to_init_cmd_trdid        = r_write_upt_index.read();
+            r_write_to_init_cmd_nline        = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index        = r_write_word_index.read();
+            r_write_to_init_cmd_count        = r_write_word_count.read();
+
+            for(size_t i=0; i<m_words ; i++){
+              r_write_to_init_cmd_be[i]=r_write_be[i].read();
+            }
+
+            size_t min = r_write_word_index.read();
+            size_t max = r_write_word_index.read() + r_write_word_count.read();
+            for (size_t i=min ; i<max ; i++) {
+              r_write_to_init_cmd_data[i] = r_write_data[i];
+            }
+            
+            if( (r_write_copy.read() != r_write_srcid.read()) || r_write_copy_inst.read() ) {
+              // We put the first copy in the fifo
+              write_to_init_cmd_fifo_put     = true;
+              write_to_init_cmd_fifo_inst    = r_write_copy_inst.read();
+              write_to_init_cmd_fifo_srcid   = r_write_copy.read();
+              if(r_write_count.read() == 1){
+                r_write_fsm = WRITE_IDLE;
+                r_write_to_init_cmd_multi_req = true;
+              } else {
+                r_write_fsm = WRITE_UPDATE;
+              }
+            } else {
+              r_write_fsm = WRITE_UPDATE;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case WRITE_UPDATE:	// send a multi-update request to INIT_CMD fsm
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          HeapEntry entry = m_heap_directory.read(r_write_ptr.read());
+          write_to_init_cmd_fifo_inst  = entry.owner.inst;
+          write_to_init_cmd_fifo_srcid = entry.owner.srcid;
+          bool dec_upt_counter = r_write_to_dec.read();
+          if( (entry.owner.srcid != r_write_srcid.read()) || entry.owner.inst ){
+            write_to_init_cmd_fifo_put = true;
+          } else {
+            dec_upt_counter = true;
+          }
+          r_write_to_dec = dec_upt_counter;
+
+          if( m_write_to_init_cmd_inst_fifo.wok() ){
+            r_write_ptr = entry.next;
+            if( entry.next == r_write_ptr.read() ) { // last copy
+              r_write_to_init_cmd_multi_req = true;
+              if(dec_upt_counter){
+                r_write_fsm = WRITE_UPT_DEC;
+              } else {
+                r_write_fsm = WRITE_IDLE;
+              }
+            } else {
+              r_write_fsm = WRITE_UPDATE;
+            }
+          } else {
+            r_write_fsm = WRITE_UPDATE;
+          }
+          break;
+        }
+        //////////////////
+      case WRITE_UPT_DEC:
+        {
+          if(!r_write_to_init_rsp_req.read()){
+            r_write_to_init_rsp_req = true;
+            r_write_to_init_rsp_upt_index = r_write_upt_index.read();
+            r_write_fsm = WRITE_IDLE;
+          }
+          break;
+        }
+        ///////////////
+      case WRITE_RSP:		// send a request to TGT_RSP FSM to acknowledge the write
+        {
+          if ( !r_write_to_tgt_rsp_req.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_fsm 		        = WRITE_IDLE;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_LOCK:	// Miss : check Transaction Table
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " READ_TRT_LOCK " << std::endl;
+#endif
+            size_t hit_index = 0;
+            size_t wok_index = 0;
+            bool hit_read  = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(r_write_address.read())],hit_index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(r_write_address.read())]);
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( hit_read ) {	// register the modified data in TRT 
+              r_write_trt_index = hit_index;
+              r_write_fsm       = WRITE_TRT_DATA;
+            } else if ( wok && !hit_write ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_TRT_SET;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT;
+            }
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_WAIT:	// release the lock protecting TRT
+        { 
+          r_write_fsm = WRITE_DIR_LOCK;
+          break;
+        }
+        ///////////////////
+      case WRITE_TRT_SET:	// register a new transaction in TRT (Write Buffer)
+        {  
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) 
+          {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) 
+            {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.set(r_write_trt_index.read(),
+                true,				// read request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                r_write_srcid.read(),
+                r_write_trdid.read(),
+                r_write_pktid.read(),
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                be_vector,
+                data_vector);
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            r_write_fsm = WRITE_XRAM_REQ;
+          }
+          break;
+        }  
+        ///////////////////
+      case WRITE_TRT_DATA:	// update an entry in TRT (Write Buffer)
+        { 
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            std::vector<be_t> be_vector;
+            std::vector<data_t> data_vector;
+            be_vector.clear();
+            data_vector.clear();
+            for ( size_t i=0; i<m_words; i++ ) {
+              be_vector.push_back(r_write_be[i]);
+              data_vector.push_back(r_write_data[i]);
+            }
+            m_transaction_tab.write_data_mask(r_write_trt_index.read(),
+                be_vector,
+                data_vector);
+            r_write_fsm = WRITE_RSP;
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_TRT_DATA transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_REQ:	// send a request to IXR_CMD FSM
+        {  
+
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req   = true;
+            r_write_to_ixr_cmd_write = false;
+            r_write_to_ixr_cmd_nline = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
+            r_write_fsm              = WRITE_RSP;
+          }
+          break;
+        }
+        ////////////////////
+      case WRITE_TRT_WRITE_LOCK:
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
+            size_t wok_index = 0;
+            bool wok = !m_transaction_tab.full(wok_index);
+            if ( wok ) {	// set a new entry in TRT
+              r_write_trt_index = wok_index;
+              r_write_fsm       = WRITE_INVAL_LOCK;
+            } else {		// wait an empty entry in TRT
+              r_write_fsm       = WRITE_WAIT;
+            }
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
+            bool        wok       = false;
+            size_t      index     = 0;
+            size_t      srcid     = r_write_srcid.read();
+            size_t      trdid     = r_write_trdid.read();
+            size_t      pktid     = r_write_pktid.read();
+            addr_t	    nline     = m_nline[(vci_addr_t)(r_write_address.read())];
+            size_t      nb_copies = r_write_count.read();
+
+            wok =m_update_tab.set(false,	// it's an inval transaction
+                true,                       // it's a broadcast
+                true,                       // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_INVAL_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_write_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_write_fsm = WRITE_DIR_INVAL;
+            else       r_write_fsm = WRITE_WAIT;
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_DIR_INVAL:
+        {
+            assert(((r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) &&
+                    (r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) &&
+                    (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ))&&
+                    "MemCache ERROR : bad TRT,DIR or UPT allocation error");
+            m_transaction_tab.set(r_write_trt_index.read(),
+                false,				// write request to XRAM
+                m_nline[(vci_addr_t)(r_write_address.read())],
+                0,
+                0,
+                0,
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " WRITE_DIR_INVAL transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            // invalidate directory entry
+            DirectoryEntry entry;
+            entry.valid	        = false;
+            entry.dirty	        = false;
+            entry.tag	        = 0;
+            entry.is_cnt        = false;
+            entry.lock          = false;
+            entry.owner.srcid   = 0;
+            entry.owner.inst    = false;
+            entry.ptr           = 0;
+            entry.count         = 0;
+            size_t set	        = m_y[(vci_addr_t)(r_write_address.read())];
+            size_t way	        = r_write_way.read();
+            m_cache_directory.write(set, way, entry);
+
+            r_write_fsm = WRITE_INVAL;
+            break;
+        }
+        ////////////////////
+      case WRITE_INVAL:
+        {
+          if (  !r_write_to_init_cmd_multi_req.read() &&
+                !r_write_to_init_cmd_brdcast_req.read() ) {
+            r_write_to_init_cmd_multi_req   = false;
+            r_write_to_init_cmd_brdcast_req = true;
+            r_write_to_init_cmd_trdid       = r_write_upt_index.read();
+            r_write_to_init_cmd_nline       = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_init_cmd_index       = 0;
+            r_write_to_init_cmd_count       = 0;
+
+            for(size_t i=0; i<m_words ; i++){
+              r_write_to_init_cmd_be[i]=0;
+              r_write_to_init_cmd_data[i] = 0;
+            }
+            r_write_fsm = WRITE_XRAM_SEND;
+            // all inval responses
+          }
+
+          break;
+        }
+        ////////////////////
+      case WRITE_XRAM_SEND:
+        {
+          if ( !r_write_to_ixr_cmd_req ) {
+            r_write_to_ixr_cmd_req     = true;
+            r_write_to_ixr_cmd_write   = true;
+            r_write_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(r_write_address.read())];
+            r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
+            for(size_t i=0; i<m_words; i++){
+              r_write_to_ixr_cmd_data[i] = r_write_data[i];
+            }
+            r_write_fsm = WRITE_IDLE;
+          }
+          break;
+        }
+    } // end switch r_write_fsm
+
+    ///////////////////////////////////////////////////////////////////////
+    //		IXR_CMD FSM
+    ///////////////////////////////////////////////////////////////////////
+    // The IXR_CMD fsm controls the command packets to the XRAM :
+    // - It sends a single cell VCI read to the XRAM in case of MISS request
+    // posted by the READ, WRITE or LLSC FSMs : the TRDID field contains 
+    // the Transaction Tab index.
+    // The VCI response is a multi-cell packet : the N cells contain
+    // the N data words.
+    // - It sends a multi-cell VCI write when the XRAM_RSP FSM request 
+    // to save a dirty line to the XRAM. 
+    // The VCI response is a single cell packet.
+    // This FSM handles requests from the READ, WRITE, LLSC & XRAM_RSP FSMs 
+    // with a round-robin priority.
+    ////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_cmd_fsm.read() ) {
+      //////////////////////// 
+      case IXR_CMD_READ_IDLE:
+        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_WRITE_IDLE:
+        if      ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_LLSC_IDLE:
+        if      ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        break;
+        //////////////////////// 
+      case IXR_CMD_XRAM_IDLE:
+        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
+        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
+        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
+        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
+        break;
+        /////////////////////////
+      case IXR_CMD_READ_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;		
+          r_read_to_ixr_cmd_req = false;
+        }
+        break;
+        //////////////////////////
+      case IXR_CMD_WRITE_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          if( r_write_to_ixr_cmd_write.read()){
+            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+              r_ixr_cmd_cpt = 0;
+              r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
+              r_write_to_ixr_cmd_req = false;
+            } else {
+              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+            }
+          } else {
+            r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;		
+            r_write_to_ixr_cmd_req = false;
+          }
+        }
+        break;
+        /////////////////////////
+      case IXR_CMD_LLSC_NLINE:
+        if ( p_vci_ixr.cmdack ) {
+          if( r_llsc_to_ixr_cmd_write.read()){
+            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+              r_ixr_cmd_cpt = 0;
+              r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;
+              r_llsc_to_ixr_cmd_req = false;
+            } else {
+              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+            }
+          } else {
+            r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;		
+            r_llsc_to_ixr_cmd_req = false;
+          }
+        }
+        break;
+        ////////////////////////
+      case IXR_CMD_XRAM_DATA:
+        if ( p_vci_ixr.cmdack ) {
+          if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
+            r_ixr_cmd_cpt = 0;
+            r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
+            r_xram_rsp_to_ixr_cmd_req = false;
+          } else {
+            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
+          }
+        }
+        break;
+
+    } // end switch r_ixr_cmd_fsm
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                IXR_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The IXR_RSP FSM receives the response packets from the XRAM,
+    // for both write transaction, and read transaction.
+    //
+    // - A response to a write request is a single-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The FSM takes the lock protecting the TRT, and the corresponding
+    // entry is erased.
+    //	
+    // - A response to a read request is a multi-cell VCI packet.
+    // The Transaction Tab index is contained in the RTRDID field.
+    // The N cells contain the N words of the cache line in the RDATA field.
+    // The FSM takes the lock protecting the TRT to store the line in the TRT
+    // (taking into account the write requests already stored in the TRT).
+    // When the line is completely written, the corresponding rok signal is set.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_ixr_rsp_fsm.read() ) {
+
+      ///////////////////
+      case IXR_RSP_IDLE:	// test if it's a read or a write transaction
+        {
+          if ( p_vci_ixr.rspval ) {
+            r_ixr_rsp_cpt   = 0;
+            r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
+            if ( p_vci_ixr.reop )  r_ixr_rsp_fsm = IXR_RSP_ACK;
+            else                   r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
+          }
+          break;  
+        }
+        ////////////////////////
+      case IXR_RSP_ACK:        // Acknowledge the vci response
+        r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
+        break;
+        ////////////////////////
+      case IXR_RSP_TRT_ERASE: 	// erase the entry in the TRT
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP ) {
+            m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
+            r_ixr_rsp_fsm = IXR_RSP_IDLE;
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_ERASE transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          }
+          break;
+        }
+        ///////////////////////
+      case IXR_RSP_TRT_READ:		// write data in the TRT
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval ) {
+            bool   eop  	= p_vci_ixr.reop.read();
+            data_t data 	= p_vci_ixr.rdata.read();
+            size_t index        = r_ixr_rsp_trt_index.read();
+            assert( eop == (r_ixr_rsp_cpt.read() == (m_words-1)) 
+                && "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
+            m_transaction_tab.write_rsp(index, r_ixr_rsp_cpt.read(), data);
+            r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
+            if ( eop ) {
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " IXR_RSP_TRT_READ transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+              r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
+              r_ixr_rsp_fsm = IXR_RSP_IDLE;
+            }
+          }
+          break;
+        }
+    } // end swich r_ixr_rsp_fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                XRAM_RSP FSM
+    ////////////////////////////////////////////////////////////////////////////
+    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
+    // The cache line has been written in the TRT buffer by the IXR_FSM.
+    //
+    // When a response is available, the corresponding TRT entry 
+    // is copied in a local buffer to be written in the cache. 
+    // Then, the FSM releases the lock protecting the TRT, and takes the lock 
+    // protecting the cache directory.
+    // It selects a cache slot and writes the line in the cache.
+    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
+    // FSM to return the cache line to the registered processor.
+    // If there is no empty slot, a victim line is evicted, and
+    // invalidate requests are sent to the L1 caches containing copies.
+    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD 
+    // FSM to save the victim line to the XRAM, and register the write transaction
+    // in the TRT (using the entry previously used by the read transaction).
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_xram_rsp_fsm.read() ) {
+
+      ///////////////////
+      case XRAM_RSP_IDLE:	// test if there is a response with a round robin priority
+        {
+          size_t ptr   = r_xram_rsp_trt_index.read();
+          size_t lines = TRANSACTION_TAB_LINES;
+          for(size_t i=0; i<lines; i++){
+            size_t index=(i+ptr+1)%lines;
+            if(r_ixr_rsp_to_xram_rsp_rok[index]){
+              r_xram_rsp_trt_index=index;
+              r_ixr_rsp_to_xram_rsp_rok[index]=false;
+              r_xram_rsp_fsm           = XRAM_RSP_DIR_LOCK;
+              break;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_IDLE state" << std::endl;
+#endif
+            }
+          }
+          break;  
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_LOCK: 	// Take the lock on the directory
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) {
+            r_xram_rsp_fsm           = XRAM_RSP_TRT_COPY;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_LOCK state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_TRT_COPY:		// Copy the TRT entry in the local buffer and eviction of a cache line
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) ) {
+            size_t index = r_xram_rsp_trt_index.read();
+            TransactionTabEntry    trt_entry(m_transaction_tab.read(index));	
+
+            r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
+
+            // selects & extracts a victim line from cache
+            size_t way = 0;
+            size_t set = m_y[(vci_addr_t)(trt_entry.nline * m_words * 4)];
+            DirectoryEntry victim(m_cache_directory.select(set, way));
+
+            for (size_t i=0 ; i<m_words ; i++) r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
+
+            bool inval = (victim.count && victim.valid) ;
+
+            r_xram_rsp_victim_copy      = victim.owner.srcid;
+            r_xram_rsp_victim_copy_inst = victim.owner.inst;
+            r_xram_rsp_victim_count     = victim.count;
+            r_xram_rsp_victim_ptr       = victim.ptr;
+            r_xram_rsp_victim_way       = way;
+            r_xram_rsp_victim_set       = set;
+            r_xram_rsp_victim_nline     = victim.tag*m_sets + set;
+            r_xram_rsp_victim_is_cnt    = victim.is_cnt;
+            r_xram_rsp_victim_inval     = inval ;
+            r_xram_rsp_victim_dirty     = victim.dirty;
+
+            r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_TRT_COPY state" << std::endl;
+	std::cout << "Victim way : " << std::hex << way << " set " << std::hex << set << std::endl;
+	victim.print();
+#endif
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP ) {
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state" << std::endl;
+#endif
+            size_t index;
+            if(m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index)){
+              r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+    std::cout << "A invalidation is already registered at this address" << std::endl;
+	m_update_tab.print();
+#endif
+
+            }
+	    else if(m_update_tab.is_full() && r_xram_rsp_victim_inval.read()){
+	      r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl;
+    std::cout << "The inval tab is full" << std::endl;
+	m_update_tab.print();
+#endif
+	    }
+            else {
+              r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_DIR_UPDT state" << std::endl;
+	m_update_tab.print();
+#endif
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case XRAM_RSP_INVAL_WAIT:
+        {
+          r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
+          break;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL_WAIT state" << std::endl;
+#endif
+        }
+        ///////////////////////
+      case XRAM_RSP_DIR_UPDT:		// updates the cache (both data & directory)
+        {
+          // signals generation
+          bool inst_read = (r_xram_rsp_trt_buf.trdid & 0x2) && r_xram_rsp_trt_buf.proc_read; // It is an instruction read
+          bool cached_read = (r_xram_rsp_trt_buf.trdid & 0x1) && r_xram_rsp_trt_buf.proc_read ;
+          // update data
+          size_t set   = r_xram_rsp_victim_set.read();
+          size_t way   = r_xram_rsp_victim_way.read();
+          for(size_t i=0; i<m_words ; i++){
+            m_cache_data[way][set][i] = r_xram_rsp_trt_buf.wdata[i];
+          }
+          // compute dirty 
+          bool dirty = false;
+          for(size_t i=0; i<m_words;i++){
+            dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
+          }
+
+          // update directory
+          DirectoryEntry entry;
+          entry.valid	  = true;
+          entry.is_cnt    = false;
+          entry.lock	  = false;
+          entry.dirty	  = dirty;
+          entry.tag	      = r_xram_rsp_trt_buf.nline / m_sets;
+          entry.ptr       = 0;
+          if(cached_read) {
+            if(inst_read) {
+              entry.owner.srcid = r_xram_rsp_trt_buf.srcid;
+              entry.owner.inst  = true;
+              entry.count       = 1;
+            } else {
+              entry.owner.srcid = r_xram_rsp_trt_buf.srcid;
+              entry.owner.inst  = false;
+              entry.count       = 1;
+            }
+          } else {
+            entry.owner.srcid = 0;
+            entry.owner.inst  = 0;
+            entry.count       = 0;
+          }
+          m_cache_directory.write(set, way, entry);
+#ifdef DDEBUG
+	   std::cout << "printing the entry : " << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_DIR_UPDT transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+          if(r_xram_rsp_victim_inval.read()){
+            bool    brdcast = r_xram_rsp_victim_is_cnt.read();
+            size_t index;
+            size_t count_copies = r_xram_rsp_victim_count.read();
+
+            bool	 wok = m_update_tab.set(false,	// it's an inval transaction
+                brdcast,                          // set brdcast bit
+                false,  // it does not need a response
+                0,
+                0,
+                0,
+                r_xram_rsp_victim_nline.read(),
+                count_copies,
+                index);
+
+#ifdef IDEBUG
+            std::cout << "xram_rsp : record invalidation, time = " << std::dec << m_cpt_cycles << std::endl;
+            m_update_tab.print();
+#endif
+            r_xram_rsp_upt_index = index;
+            if(!wok) {
+              assert(false && "mem_cache error : xram_rsp_dir_upt, an update_tab entry was free but write unsuccessful");
+            }
+          }
+          // If the victim is not dirty, we erase the entry in the TRT
+          if      (!r_xram_rsp_victim_dirty.read()){
+	  m_transaction_tab.erase(r_xram_rsp_trt_index.read());
+
+	  }
+          // Next state
+          if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
+          else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+          else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+          else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+          break;
+        }
+        ////////////////////////
+      case XRAM_RSP_TRT_DIRTY:		// set the TRT entry (write line to XRAM) if the victim is dirty
+        {
+          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP ) {
+            m_transaction_tab.set(r_xram_rsp_trt_index.read(),
+                false,				// write to XRAM
+                r_xram_rsp_victim_nline.read(), // line index
+                0,
+                0,
+                0,
+                false,
+                0,
+                0,
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0) );
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " XRAM_RSP_TRT_DIRTY transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
+            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+          }
+          break;
+        }
+        //////////////////////
+      case XRAM_RSP_DIR_RSP:     // send a request to TGT_RSP FSM in case of read
+        {
+          if ( !r_xram_rsp_to_tgt_rsp_req.read() ) {
+            r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
+            r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
+            r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
+            for (size_t i=0; i < m_words; i++) {
+              r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
+            } 
+            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_req    = true;
+
+            if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_INVAL;
+            else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY; 
+            else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+#ifdef DDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_DIR_RSP state" << std::endl;
+#endif
+          }
+          break;
+        }
+        ////////////////////
+      case XRAM_RSP_INVAL:	// send invalidate request to INIT_CMD FSM
+        {
+          if(   !r_xram_rsp_to_init_cmd_multi_req.read() && 
+                !r_xram_rsp_to_init_cmd_brdcast_req.read() ) {	      
+            
+            bool multi_req = !r_xram_rsp_victim_is_cnt.read();
+            bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
+            bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
+
+            r_xram_rsp_to_init_cmd_multi_req    = last_multi_req; 
+            r_xram_rsp_to_init_cmd_brdcast_req  = r_xram_rsp_victim_is_cnt.read();
+            r_xram_rsp_to_init_cmd_nline        = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_init_cmd_trdid        = r_xram_rsp_upt_index;
+            xram_rsp_to_init_cmd_fifo_srcid     = r_xram_rsp_victim_copy.read();
+            xram_rsp_to_init_cmd_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
+            xram_rsp_to_init_cmd_fifo_put       = multi_req;
+            
+            r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
+
+            if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
+            else if (not_last_multi_req)    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+            else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef IDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_INVAL state" << std::endl;
+#endif
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_WRITE_DIRTY:	// send a write request to IXR_CMD FSM
+        {
+          if ( !r_xram_rsp_to_ixr_cmd_req.read() ) {
+            r_xram_rsp_to_ixr_cmd_req = true;
+            r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
+            r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
+            for(size_t i=0; i<m_words ; i++) {
+              r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
+            }
+            m_cpt_write_dirty++;
+            bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
+            bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
+            if ( not_last_multi_req )   r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+            else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
+#ifdef TDEBUG
+	std::cout << "XRAM_RSP FSM in XRAM_RSP_WRITE_DIRTY state" << std::endl;
+#endif
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_HEAP_ERASE:	// erase the list of copies and sent invalidations
+        {
+          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP ) {
+            HeapEntry entry = m_heap_directory.read(r_xram_rsp_next_ptr.read());
+            xram_rsp_to_init_cmd_fifo_srcid = entry.owner.srcid;
+            xram_rsp_to_init_cmd_fifo_inst  = entry.owner.inst;
+            xram_rsp_to_init_cmd_fifo_put   = true;
+            if( m_xram_rsp_to_init_cmd_inst_fifo.wok() ){
+              r_xram_rsp_next_ptr = entry.next;
+              if( entry.next == r_xram_rsp_next_ptr.read() ){ // last copy
+                r_xram_rsp_to_init_cmd_multi_req = true;
+                r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
+              } else {
+                r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+              }
+            } else {
+              r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
+            }
+          }
+          break;
+        }
+        //////////////////////////
+      case XRAM_RSP_HEAP_LAST:	// last member of the list
+        {
+          assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP) &&
+                  "MemCache ERROR : bad HEAP allocation");
+          size_t free_pointer = m_heap_directory.next_free_ptr();
+
+          HeapEntry last_entry;
+          last_entry.owner.srcid = 0;
+          last_entry.owner.inst  = false;
+          if(m_heap_directory.is_full()){
+            last_entry.next     = r_xram_rsp_next_ptr.read();
+            m_heap_directory.unset_full();
+          } else {
+            last_entry.next     = free_pointer;
+          }
+
+          m_heap_directory.write_free_ptr(r_xram_rsp_victim_ptr.read());
+          m_heap_directory.write(r_xram_rsp_next_ptr.read(),last_entry);
+
+          r_xram_rsp_fsm = XRAM_RSP_IDLE;
+
+          break;
+        }
+    } // end swich r_xram_rsp_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		CLEANUP FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The CLEANUP FSM handles the cleanup request from L1 caches.
+    // It accesses the cache directory to update the list of copies.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+    switch ( r_cleanup_fsm.read() ) {
+
+      ///////////////////
+      case CLEANUP_IDLE:
+        {
+
+          if ( p_vci_tgt_cleanup.cmdval.read() ) {
+            assert( (p_vci_tgt_cleanup.srcid.read() < m_initiators) &&
+                "VCI_MEM_CACHE error in VCI_MEM_CACHE in the CLEANUP network : The received SRCID is larger than the number of initiators");
+            bool reached = false;
+            for ( size_t index = 0 ; index < ncseg && !reached ; index++ ){
+              if ( m_cseg[index]->contains((addr_t)(p_vci_tgt_cleanup.address.read())) ){
+                reached = true;
+              }
+            }
+            if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
+                (((addr_t)(p_vci_tgt_cleanup.address.read())) != BROADCAST_ADDR) &&
+                reached) {
+
+              m_cpt_cleanup++;
+
+              r_cleanup_nline      = (addr_t)(m_nline[(vci_addr_t)(p_vci_tgt_cleanup.address.read())]) ;
+              r_cleanup_srcid      = p_vci_tgt_cleanup.srcid.read();
+              r_cleanup_trdid      = p_vci_tgt_cleanup.trdid.read();
+              r_cleanup_pktid      = p_vci_tgt_cleanup.pktid.read();
+
+              r_cleanup_fsm        = CLEANUP_DIR_LOCK;
+            }
+          }
+          break;
+        }
+        //////////////////////
+      case CLEANUP_DIR_LOCK:
+        {
+          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) {
+
+            // Read the directory
+            size_t way = 0;
+	   addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
+           DirectoryEntry entry = m_cache_directory.read(cleanup_address , way);
+#ifdef DDEBUG
+	   std::cout << "In CLEANUP_DIR_LOCK printing the entry of address is : " << std::hex << cleanup_address << std::endl;
+	   entry.print();
+	   std::cout << "done" << std::endl;
+#endif
+            r_cleanup_is_cnt    = entry.is_cnt;
+            r_cleanup_dirty	    = entry.dirty;
+            r_cleanup_tag	    = entry.tag;
+            r_cleanup_lock	    = entry.lock;
+            r_cleanup_way	    = way;
+            r_cleanup_copy      = entry.owner.srcid;
+            r_cleanup_copy_inst = entry.owner.inst;
+            r_cleanup_count     = entry.count;
+            r_cleanup_ptr       = entry.ptr;
+
+
+            // In case of hit, the copy must be cleaned in the copies bit-vector
+            if( entry.valid){
+              if ( (entry.count==1) || (entry.is_cnt) )  { // no access to the heap
+                r_cleanup_fsm = CLEANUP_DIR_WRITE;
+              } else {
+                r_cleanup_fsm = CLEANUP_HEAP_LOCK;
+              }
+            } else {
+              r_cleanup_fsm = CLEANUP_UPT_LOCK;
+            }
+          }
+          break;
+        }
+        ///////////////////////
+      case CLEANUP_DIR_WRITE:
+        {
+          assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) && 
+                "MemCache ERROR : Bad DIR allocation");
+          size_t way      = r_cleanup_way.read();
+#define L2 soclib::common::uint32_log2
+          size_t set      = m_y[(vci_addr_t)(r_cleanup_nline.read() << (L2(m_words) +2))];
+#undef L2
+          bool cleanup_inst  = r_cleanup_trdid.read() & 0x1; 
+          bool match_srcid   = (r_cleanup_copy.read() == r_cleanup_srcid.read());
+          bool match_inst    = (r_cleanup_copy_inst.read()  == cleanup_inst);
+          bool match         = match_srcid && match_inst;
+
+          // update the cache directory (for the copies)
+          DirectoryEntry entry;
+          entry.valid	= true;
+          entry.is_cnt  = r_cleanup_is_cnt.read();
+          entry.dirty	= r_cleanup_dirty.read();
+          entry.tag	    = r_cleanup_tag.read();
+          entry.lock	= r_cleanup_lock.read();
+          entry.ptr     = r_cleanup_ptr.read();
+          if(r_cleanup_is_cnt.read()) { // Directory is a counter
+            entry.count  = r_cleanup_count.read() -1;
+            entry.owner.srcid = 0;
+            entry.owner.inst  = 0;
+            // response to the cache 
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          else{                         // Directory is a list
+            if(match) { // hit
+              entry.count       = 0; // no more copy
+              entry.owner.srcid = 0;
+              entry.owner.inst  = 0;
+              r_cleanup_fsm     = CLEANUP_RSP; 
+            } else { // miss
+              entry.count       = r_cleanup_count.read();
+              entry.owner.srcid = r_cleanup_copy.read();
+              entry.owner.inst  = r_cleanup_copy_inst.read();
+              r_cleanup_fsm     = CLEANUP_UPT_LOCK;
+            }
+          }
+          m_cache_directory.write(set, way, entry);  
+
+          break;
+        }
+        /////////////////
+      case CLEANUP_HEAP_LOCK:
+        {
+          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP){
+            size_t way      = r_cleanup_way.read();
+#define L2 soclib::common::uint32_log2
+            size_t set      = m_y[(vci_addr_t)(r_cleanup_nline.read() << (L2(m_words) +2))];
+#undef L2
+            HeapEntry heap_entry = m_heap_directory.read(r_cleanup_ptr.read());
+            bool last = (heap_entry.next == r_cleanup_ptr.read());
+            bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
+            bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
+            bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
+            bool match_dir          = match_dir_srcid && match_dir_inst;
+            bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+            bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
+            bool match_heap         = match_heap_srcid && match_heap_inst;
+
+            r_cleanup_prev_ptr = r_cleanup_ptr.read();
+            r_cleanup_prev_srcid = heap_entry.owner.srcid;
+            r_cleanup_prev_inst  = heap_entry.owner.inst;
+
+            if(match_dir){
+              DirectoryEntry dir_entry;
+              dir_entry.valid	    = true;
+              dir_entry.is_cnt      = r_cleanup_is_cnt.read();
+              dir_entry.dirty	    = r_cleanup_dirty.read();
+              dir_entry.tag	        = r_cleanup_tag.read();
+              dir_entry.lock	    = r_cleanup_lock.read();
+              dir_entry.ptr         = heap_entry.next;
+              dir_entry.count       = r_cleanup_count.read()-1;
+              dir_entry.owner.srcid = heap_entry.owner.srcid;
+              dir_entry.owner.inst  = heap_entry.owner.inst;
+              m_cache_directory.write(set,way,dir_entry);
+              r_cleanup_next_ptr    = r_cleanup_ptr.read();
+              r_cleanup_fsm         = CLEANUP_HEAP_FREE;
+            }
+            else if(match_heap){
+              DirectoryEntry dir_entry;
+              dir_entry.valid	    = true;
+              dir_entry.is_cnt      = r_cleanup_is_cnt.read();
+              dir_entry.dirty	    = r_cleanup_dirty.read();
+              dir_entry.tag	        = r_cleanup_tag.read();
+              dir_entry.lock	    = r_cleanup_lock.read();
+              dir_entry.ptr         = heap_entry.next;
+              dir_entry.count       = r_cleanup_count.read()-1;
+              dir_entry.owner.srcid = r_cleanup_copy.read();
+              dir_entry.owner.inst  = r_cleanup_copy_inst.read();
+              m_cache_directory.write(set,way,dir_entry);
+              r_cleanup_next_ptr    = r_cleanup_ptr.read();
+              r_cleanup_fsm         = CLEANUP_HEAP_FREE; 
+            }
+            else{
+              if(!last){
+                DirectoryEntry dir_entry;
+                dir_entry.valid	        = true;
+                dir_entry.is_cnt        = r_cleanup_is_cnt.read();
+                dir_entry.dirty	        = r_cleanup_dirty.read();
+                dir_entry.tag	        = r_cleanup_tag.read();
+                dir_entry.lock	        = r_cleanup_lock.read();
+                dir_entry.ptr           = r_cleanup_ptr.read();
+                dir_entry.count         = r_cleanup_count.read()-1;
+                dir_entry.owner.srcid   = r_cleanup_copy.read();
+                dir_entry.owner.inst    = r_cleanup_copy_inst.read();
+                m_cache_directory.write(set,way,dir_entry);
+
+                r_cleanup_next_ptr = heap_entry.next;
+                r_cleanup_fsm      = CLEANUP_HEAP_SEARCH;
+
+              } else{
+                assert(false && "MemCache ERROR : CLEANUP hit but line not shared");
+              }
+            }
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_HEAP_SEARCH:
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          HeapEntry heap_entry = m_heap_directory.read(r_cleanup_next_ptr.read());
+          bool last = (heap_entry.next == r_cleanup_next_ptr.read());
+          bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
+          bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
+          bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
+          bool match_heap         = match_heap_srcid && match_heap_inst;
+
+          if(match_heap){
+            r_cleanup_ptr           = heap_entry.next; // reuse ressources
+            r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
+          }
+          else{
+            if(last) {
+              assert(false && "MemCache ERROR : CLEANUP hit but line not shared");
+            } else {
+              r_cleanup_prev_ptr = r_cleanup_next_ptr.read();
+              r_cleanup_prev_srcid = heap_entry.owner.srcid;
+              r_cleanup_prev_inst  = heap_entry.owner.inst;
+              r_cleanup_next_ptr = heap_entry.next;
+              r_cleanup_fsm      = CLEANUP_HEAP_SEARCH;
+            }
+          }
+
+          break;
+        }
+        /////////////////
+      case CLEANUP_HEAP_CLEAN:
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
+          HeapEntry heap_entry; 
+          heap_entry.owner.srcid = r_cleanup_prev_srcid.read();
+          heap_entry.owner.inst  = r_cleanup_prev_inst.read();
+          if(last){ // this is the last entry of the list of copies
+            heap_entry.next     = r_cleanup_prev_ptr.read();
+          } else { // this is not the last entry
+            heap_entry.next     = r_cleanup_ptr.read();
+          }
+          m_heap_directory.write(r_cleanup_prev_ptr.read(),heap_entry);
+          r_cleanup_fsm = CLEANUP_HEAP_FREE;
+          break;
+        }
+        /////////////////
+      case CLEANUP_HEAP_FREE:
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          HeapEntry heap_entry;
+          heap_entry.owner.srcid = 0;
+          heap_entry.owner.inst  = false;
+          if(m_heap_directory.is_full()){
+            heap_entry.next     = r_cleanup_next_ptr.read();
+          } else {
+            heap_entry.next     = m_heap_directory.next_free_ptr();
+          }
+          m_heap_directory.write(r_cleanup_next_ptr.read(),heap_entry);
+          m_heap_directory.write_free_ptr(r_cleanup_next_ptr.read());
+          m_heap_directory.unset_full();
+          r_cleanup_fsm = CLEANUP_RSP;
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_LOCK:
+        {
+          if( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
+          {
+            size_t index;
+            bool hit_inval;
+            hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
+            if(!hit_inval) {
+#ifdef DEBUG_VCI_MEM_CACHE
+              std::cout << "MEM_CACHE WARNING: cleanup with no corresponding entry at address : " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::dec << std::endl;
+#endif
+              r_cleanup_fsm = CLEANUP_RSP;
+            } else {
+              r_cleanup_write_srcid = m_update_tab.srcid(index);
+              r_cleanup_write_trdid = m_update_tab.trdid(index);
+              r_cleanup_write_pktid = m_update_tab.pktid(index);
+              r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
+              r_cleanup_fsm = CLEANUP_UPT_WRITE;
+            }
+            r_cleanup_index.write(index) ; 
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_UPT_WRITE:
+        {
+          size_t count = 0;
+          m_update_tab.decrement(r_cleanup_index.read(), count); // &count
+          if(count == 0){
+            m_update_tab.clear(r_cleanup_index.read());
+#ifdef IDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " CLEANUP_UPT_WRITE update table : " << std::endl;
+	m_update_tab.print();
+#endif
+
+            if(r_cleanup_need_rsp.read()){
+              r_cleanup_fsm = CLEANUP_WRITE_RSP ;
+            } else {
+              r_cleanup_fsm = CLEANUP_RSP;
+            }
+          } else {
+            r_cleanup_fsm = CLEANUP_RSP ;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_WRITE_RSP:
+        {
+          if( !r_cleanup_to_tgt_rsp_req.read()) {
+            r_cleanup_to_tgt_rsp_req     = true;
+            r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
+            r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
+            r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
+            r_cleanup_fsm = CLEANUP_RSP;
+          }
+          break;
+        }
+        /////////////////
+      case CLEANUP_RSP:
+        {
+          if(p_vci_tgt_cleanup.rspack)
+            r_cleanup_fsm = CLEANUP_IDLE;
+          break;
+        }
+    } // end switch cleanup fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		LLSC FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The LLSC FSM handles the LL & SC atomic access.
+    //
+    // For a LL :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the LL request is registered in the Atomic Table and the
+    // response is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state.
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the LL request is not consumed in the FIFO.
+    //
+    // For a SC :
+    // It access the directory to check hit / miss.
+    // - In case of hit, the Atomic Table is checked and the proper response
+    // (true or false is sent to the requesting processor.
+    // - In case of miss, the LLSC FSM accesses the transaction table. 
+    // If a read transaction to the XRAM for this line already exists, 
+    // or if the transaction table is full, it returns to IDLE state. 
+    // Otherwise, a new transaction to the XRAM is initiated.
+    // In both cases, the SC request is not consumed in the FIFO.
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_llsc_fsm.read() ) {
+
+      ///////////////
+      case LLSC_IDLE:	 // fill the buffers
+        {
+          if( m_cmd_llsc_addr_fifo.rok() ) {
+#ifdef LOCK_DEBUG
+            std::cout << "SC data : " << m_cmd_llsc_wdata_fifo.read() << std::endl;
+            std::cout << "SC addr : " << std::hex << m_cmd_llsc_addr_fifo.read() << std::dec << std::endl;
+            std::cout << "SC cpt  : " << r_llsc_cpt.read() << std::endl;
+#endif
+            if(m_cmd_llsc_eop_fifo.read()){
+              m_cpt_sc++;
+              r_llsc_fsm = SC_DIR_LOCK;
+#ifdef LOCK_DEBUG
+              std::cout << "SC eop" << std::endl;
+#endif
+            } else { // we keep the last word
+                cmd_llsc_fifo_get = true;
+            }
+            // We fill the two buffers
+            if(r_llsc_cpt.read() < 2){
+                r_llsc_rdata[r_llsc_cpt.read()] = m_cmd_llsc_wdata_fifo.read();
+            }
+            if((r_llsc_cpt.read() == 1) && m_cmd_llsc_eop_fifo.read())
+                r_llsc_wdata = m_cmd_llsc_wdata_fifo.read();
+            if(r_llsc_cpt.read()>3)
+                assert(false && "MEMCACHE error : SC too long");
+            if(r_llsc_cpt.read()==2){
+                r_llsc_wdata = m_cmd_llsc_wdata_fifo.read();
+            }
+            r_llsc_cpt = r_llsc_cpt.read()+1;
+          }	
+          break;
+        }
+        /////////////////
+      case SC_DIR_LOCK:
+        {
+          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
+            size_t way = 0;
+            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
+            r_llsc_is_cnt   = entry.is_cnt;
+            r_llsc_dirty    = entry.dirty;
+            r_llsc_tag      = entry.tag;
+            r_llsc_way      = way;
+            r_llsc_copy     = entry.owner.srcid;
+            r_llsc_copy_inst= entry.owner.inst;
+            r_llsc_ptr      = entry.ptr;
+            r_llsc_count    = entry.count;
+            if ( entry.valid ){
+                r_llsc_fsm = SC_DIR_HIT_READ;
+            }
+            else r_llsc_fsm = LLSC_TRT_LOCK;
+          }
+          break;
+        }
+        ////////////////
+      case SC_DIR_HIT_READ:
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+
+          // update directory (lock & dirty bits
+          DirectoryEntry entry;
+          entry.valid	    = true;
+          entry.is_cnt      = r_llsc_is_cnt.read();
+          entry.dirty	    = true;
+          entry.lock	    = true;
+          entry.tag	        = r_llsc_tag.read();
+          entry.owner.srcid = r_llsc_copy.read();
+          entry.owner.inst  = r_llsc_copy_inst.read();
+          entry.count       = r_llsc_count.read();
+          entry.ptr         = r_llsc_ptr.read();
+          m_cache_directory.write(set, way, entry);
+
+          // read data in cache
+          bool ok;
+          ok = (r_llsc_rdata[0].read() == m_cache_data[way][set][word]);
+          if(r_llsc_cpt.read()==4) // 64 bits SC
+            ok &= (r_llsc_rdata[1] == m_cache_data[way][set][word+1]);
+
+#ifdef LOCK_DEBUG
+          std::cout << "SC_DIR_HIT_READ ok ? " << ok << std::endl;
+          if(!ok){
+              std::cout << "SC_DIR_HIT_READ cache data 0 : " << m_cache_data[way][set][word] << std::endl;
+              if(r_llsc_cpt.read()==4)
+                  std::cout << "SC_DIR_HIT_READ rdata 1      : " << m_cache_data[way][set][word+1] << std::endl;
+              std::cout << "SC_DIR_HIT_READ rdata 0      : " << r_llsc_rdata[0].read() << std::endl;
+              if(r_llsc_cpt.read()==4)
+                  std::cout << "SC_DIR_HIT_READ rdata 1      : " << r_llsc_rdata[1].read() << std::endl;
+              std::cout << "SC_DIR_HIT_READ wdata 0      : " << r_llsc_wdata.read() << std::endl;
+              if(r_llsc_cpt.read()==4)
+                  std::cout << "SC_DIR_HIT_READ wdata 1      : " << m_cmd_llsc_wdata_fifo.read() << std::endl;
+          }
+#endif
+          if(ok){
+            /* to avoid livelock, force the atomic access to fail (pseudo-)randomly */
+            bool fail = (r_llsc_lfsr % (64) == 0);
+            r_llsc_lfsr = (r_llsc_lfsr >> 1) ^ ((-(r_llsc_lfsr & 1)) & 0xd0000001);
+#ifdef RANDOMIZE_SC
+            if(fail){
+#else
+            if(0){
+#endif
+                r_llsc_fsm = SC_RSP_FALSE;
+            } else {
+                if(r_llsc_count.read()) {  // Shared line
+                    if(entry.is_cnt) {
+                        r_llsc_fsm = SC_TRT_LOCK;
+                    } else {
+                        r_llsc_fsm = SC_UPT_LOCK;
+                    }
+                } else {
+                    r_llsc_fsm = SC_DIR_HIT_WRITE;
+                }
+            }
+          } else {
+            r_llsc_fsm = SC_RSP_FALSE;
+          }
+          break;
+        }
+        ////////////////
+      case SC_DIR_HIT_WRITE:
+        {
+          size_t way	= r_llsc_way.read();
+          size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+          size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+
+          if(!r_llsc_count.read()){ // no update
+            // write data in cache
+            m_cache_data[way][set][word] = r_llsc_wdata.read();
+            if(r_llsc_cpt.read()==4)
+                m_cache_data[way][set][word+1] = m_cmd_llsc_wdata_fifo.read();
+          }
+          
+          if(r_llsc_count.read()) {  // Shared line
+#ifdef LOCK_DEBUG
+            std::cout << "SC, shared line" << std::endl;
+#endif
+            r_llsc_fsm = SC_UPT_LOCK;
+          } else {
+            r_llsc_fsm = SC_RSP_TRUE;
+          }
+          break;
+        }
+        /////////////////////
+      case SC_UPT_LOCK: 	// Try to register the request in Update Table
+        {
+
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
+            size_t way	= r_llsc_way.read();
+            size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+            size_t word	= m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
+            bool        wok        = false;
+            size_t      index      = 0;
+            size_t      srcid      = m_cmd_llsc_srcid_fifo.read();
+            size_t      trdid      = m_cmd_llsc_trdid_fifo.read();
+            size_t      pktid      = m_cmd_llsc_pktid_fifo.read();
+            addr_t	    nline      = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t      nb_copies  = r_llsc_count.read();
+
+            wok =m_update_tab.set(true,	// it's an update transaction
+                false,                  // it's not a broadcast
+                true,                   // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+            if(wok){
+              // write data in cache
+              m_cache_data[way][set][word] = r_llsc_wdata.read();
+              if(r_llsc_cpt.read()==4)
+                  m_cache_data[way][set][word+1] = m_cmd_llsc_wdata_fifo.read();
+            }
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " SC_UPT_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_llsc_upt_index = index;
+            //  releases the lock protecting the Update Table and the Directory if no entry...
+            if ( wok ) r_llsc_fsm = SC_HEAP_LOCK;
+            else       r_llsc_fsm = SC_WAIT;
+          }
+          break;
+        }
+        ////////////////////
+      case SC_WAIT: 	// release all locks
+        {
+          r_llsc_fsm = SC_DIR_LOCK;
+          break;
+        }
+        ////////////////////
+      case SC_HEAP_LOCK: 	// lock the heap
+        {
+          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC ){
+            r_llsc_fsm = SC_UPT_REQ;
+          }
+          break;
+        }
+        ////////////////////
+      case SC_UPT_REQ: 	// Request the update
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          if( !r_llsc_to_init_cmd_multi_req.read() && 
+              !r_llsc_to_init_cmd_brdcast_req.read()  ){
+            r_llsc_to_init_cmd_brdcast_req  = false;
+            r_llsc_to_init_cmd_trdid        = r_llsc_upt_index.read();
+            r_llsc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_index        = m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_wdata        = r_llsc_wdata.read();
+            if(r_llsc_cpt.read() == 4){
+                r_llsc_to_init_cmd_is_long    = true;
+                r_llsc_to_init_cmd_wdata_high = m_cmd_llsc_wdata_fifo.read();
+            } else {
+                r_llsc_to_init_cmd_is_long    = false;
+                r_llsc_to_init_cmd_wdata_high = 0;
+            }
+
+            // We put the first copy in the fifo
+            llsc_to_init_cmd_fifo_put     = true;
+            llsc_to_init_cmd_fifo_inst    = r_llsc_copy_inst.read();
+            llsc_to_init_cmd_fifo_srcid   = r_llsc_copy.read();
+            if(r_llsc_count.read() == 1){
+#ifdef LOCK_DEBUG
+              std::cout << "SC_UPT_REQ, only one owner : " << r_llsc_copy.read() << std::endl;
+#endif
+              r_llsc_fsm = LLSC_IDLE;
+              cmd_llsc_fifo_get            = true;
+              r_llsc_to_init_cmd_multi_req = true;
+              r_llsc_cpt = 0;
+            } else {
+              r_llsc_fsm = SC_UPDATE;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case SC_UPDATE:   	// send a multi-update request to INIT_CMD fsm
+        {
+          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
+                    "MemCache ERROR : bad HEAP allocation");
+          HeapEntry entry = m_heap_directory.read(r_llsc_ptr.read());
+          llsc_to_init_cmd_fifo_inst  = entry.owner.inst;
+          llsc_to_init_cmd_fifo_srcid = entry.owner.srcid;
+          llsc_to_init_cmd_fifo_put = true;
+
+          if( m_llsc_to_init_cmd_inst_fifo.wok() ){
+            r_llsc_ptr = entry.next;
+            if( entry.next == r_llsc_ptr.read() ) { // last copy
+              r_llsc_to_init_cmd_multi_req = true;
+              r_llsc_fsm = LLSC_IDLE; // Response will be sent after receiving
+                                      // all update responses
+              cmd_llsc_fifo_get         = true;
+              r_llsc_cpt = 0;
+            } else {
+              r_llsc_fsm = SC_UPDATE;
+            }
+          } else {
+            r_llsc_fsm = SC_UPDATE;
+          }
+          
+          break;
+        }
+        //////////////////
+      case SC_TRT_LOCK:
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            if( !r_llsc_to_ixr_cmd_req ) { // we can transfer the data to the buffer
+              size_t way	= r_llsc_way.read();
+              size_t set	= m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+              for(size_t i = 0; i<m_words; i++){
+                if(i==m_x[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]) {
+                  r_llsc_to_ixr_cmd_data[i] = r_llsc_wdata.read();
+                } else {
+                    if((i==(m_x[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]+1)) && // 64 bit SC
+                        (r_llsc_cpt.read()==4)) {
+                        r_llsc_to_ixr_cmd_data[i] = m_cmd_llsc_wdata_fifo.read();
+                    } else {
+                        r_llsc_to_ixr_cmd_data[i] = m_cache_data[way][set][i];
+                    }
+                }
+              }
+              size_t wok_index = 0;
+              bool wok = !m_transaction_tab.full(wok_index);
+              if ( wok ) { // set a new entry in TRT
+                r_llsc_trt_index = wok_index;
+                r_llsc_fsm       = SC_INVAL_LOCK; 
+              } else {
+                r_llsc_fsm       = SC_WAIT;
+              }
+            } else {
+              r_llsc_fsm = SC_WAIT;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case SC_INVAL_LOCK:
+        {
+          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
+            bool        wok       = false;
+            size_t      index     = 0;
+            size_t      srcid     = m_cmd_llsc_srcid_fifo.read();
+            size_t      trdid     = m_cmd_llsc_trdid_fifo.read();
+            size_t      pktid     = m_cmd_llsc_pktid_fifo.read();
+            addr_t	    nline     = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t      nb_copies = r_llsc_count.read();
+
+            wok =m_update_tab.set(false,	// it's an inval transaction
+                true,                       // it's a broadcast
+                true,                       // it needs a response
+                srcid,
+                trdid,
+                pktid,
+                nline,
+                nb_copies,
+                index);
+#ifdef IDEBUG
+            if(wok){
+	std::cout << sc_time_stamp() << " " << name() << " LLSC_INVAL_LOCK update table : " << std::endl;
+	m_update_tab.print();
+            }
+#endif
+            r_llsc_upt_index = index;
+            //  releases the lock protecting Update Table if no entry...
+            if ( wok ) r_llsc_fsm = SC_DIR_INVAL;
+            else       r_llsc_fsm = SC_WAIT;
+          }
+          break;
+        }
+        //////////////////
+      case SC_DIR_INVAL:
+        {
+          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) &&
+              (r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC )  &&
+              (r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ))
+          {
+            m_transaction_tab.set(r_llsc_trt_index.read(),
+                false,				// write request to XRAM
+                m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())],
+                0,
+                0,
+                0,
+                false,				// not a processor read
+                0,  				// not a single word 
+                0,		        	// word index
+                std::vector<be_t>(m_words,0),
+                std::vector<data_t>(m_words,0));
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " SC_DIR_INVAL transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+            // invalidate directory entry
+            DirectoryEntry entry;
+            entry.valid	        = false;
+            entry.dirty	        = false;
+            entry.tag	        = 0;
+            entry.is_cnt        = false;
+            entry.lock	        = false;
+            entry.count         = 0;
+            entry.owner.srcid   = 0;
+            entry.owner.inst    = false;
+            entry.ptr           = 0;
+            size_t set	   = m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            size_t way	   = r_llsc_way.read();
+            m_cache_directory.write(set, way, entry);
+
+            r_llsc_fsm = SC_INVAL;
+          } else {
+            assert(false && "LOCK ERROR in LLSC_FSM, STATE = LLSC_DIR_INVAL");
+          }
+
+          break;
+
+        }
+        //////////////////
+      case SC_INVAL:
+        {
+          if ( !r_llsc_to_init_cmd_multi_req.read() &&
+               !r_llsc_to_init_cmd_brdcast_req.read()) {
+            r_llsc_to_init_cmd_multi_req    = false;
+            r_llsc_to_init_cmd_brdcast_req  = true;
+            r_llsc_to_init_cmd_trdid        = r_llsc_upt_index.read();
+            r_llsc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_init_cmd_index        = 0;
+            r_llsc_to_init_cmd_wdata        = 0;
+
+            r_llsc_fsm = SC_XRAM_SEND;
+            // all update responses
+          }
+
+          break;
+        }
+        //////////////////
+      case SC_XRAM_SEND:
+        {
+          if ( !r_llsc_to_ixr_cmd_req ) {
+            r_llsc_to_ixr_cmd_req     = true;
+            r_llsc_to_ixr_cmd_write   = true;
+            r_llsc_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
+            r_llsc_to_ixr_cmd_trdid   = r_llsc_trt_index.read();
+            r_llsc_fsm        = LLSC_IDLE;
+            cmd_llsc_fifo_get = true;
+            r_llsc_cpt = 0;
+          } else {
+            assert( false && "MEM_CACHE, LLSC FSM : SC_XRAM_SEND state : the request should not have been previously set");
+          }
+          break;
+        }
+        //////////////////
+      case SC_RSP_FALSE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get		= true;
+            r_llsc_cpt = 0;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 1;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        /////////////////
+      case SC_RSP_TRUE:
+        {
+          if( !r_llsc_to_tgt_rsp_req ) {
+            cmd_llsc_fifo_get	    = true;
+            r_llsc_cpt = 0;
+            r_llsc_to_tgt_rsp_req	= true;
+            r_llsc_to_tgt_rsp_data	= 0;
+            r_llsc_to_tgt_rsp_srcid	= m_cmd_llsc_srcid_fifo.read();
+            r_llsc_to_tgt_rsp_trdid	= m_cmd_llsc_trdid_fifo.read();
+            r_llsc_to_tgt_rsp_pktid	= m_cmd_llsc_pktid_fifo.read();
+            r_llsc_fsm 			    = LLSC_IDLE;
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_TRT_LOCK:         // read or write miss : check the Transaction Table
+        {
+          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+            size_t   index = 0;
+            bool hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],index);
+            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]);
+            bool wok = !m_transaction_tab.full(index);
+
+            if ( hit_read || !wok || hit_write ) {  // missing line already requested or no space in TRT
+              r_llsc_fsm = SC_WAIT;
+            } else {
+              r_llsc_trt_index = index;
+              r_llsc_fsm       = LLSC_TRT_SET;
+            }
+          }
+          break;
+        }
+        //////////////////
+      case LLSC_TRT_SET:	// register the XRAM transaction in Transaction Table
+        {
+            if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
+                std::vector<be_t> be_vector;
+                std::vector<data_t> data_vector;
+                be_vector.clear();
+                data_vector.clear();
+                for ( size_t i=0; i<m_words; i++ ) 
+                {   
+                    be_vector.push_back(0);
+                    data_vector.push_back(0);
+                }
+
+                m_transaction_tab.set(r_llsc_trt_index.read(),
+                  true,
+                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
+                  m_cmd_llsc_srcid_fifo.read(),
+                  m_cmd_llsc_trdid_fifo.read(),
+                  m_cmd_llsc_pktid_fifo.read(),
+                  false,
+                  0,
+                  0,
+                  be_vector,
+                  data_vector);
+#ifdef TDEBUG
+	std::cout << sc_time_stamp() << " " << name() << " LLSC_TRT_SET transaction table : " << std::endl;
+	for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)
+	  m_transaction_tab.print(i);
+#endif
+
+                r_llsc_fsm = LLSC_XRAM_REQ;        
+          }
+          break;
+        }
+        ///////////////////
+      case LLSC_XRAM_REQ:	// request the IXR_CMD FSM to fetch the missing line
+        {
+          if ( !r_llsc_to_ixr_cmd_req ) {
+            r_llsc_to_ixr_cmd_req        = true;
+            r_llsc_to_ixr_cmd_write      = false;
+            r_llsc_to_ixr_cmd_trdid      = r_llsc_trt_index.read();
+            r_llsc_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()];
+            r_llsc_fsm                   = SC_WAIT;
+          }
+          break;
+        }
+    } // end switch r_llsc_fsm
+
+
+    //////////////////////////////////////////////////////////////////////////////
+    //		INIT_CMD FSM
+    //////////////////////////////////////////////////////////////////////////////
+    // The INIT_CMD fsm controls the VCI CMD initiator port, used to update
+    // or invalidate cache lines in L1 caches.
+    // It implements a round-robin priority between the two following requests:
+    // - r_write_to_init_cmd_req : update request from WRITE FSM 
+    // - r_xram_rsp_to_init_cmd_req : invalidate request from XRAM_RSP FSM 
+    // The inval request is a single cell VCI write command containing the 
+    // index of the line to be invalidated.
+    // The update request is a multi-cells VCI write command : The first cell 
+    // contains the index of the cache line to be updated. The second cell contains 
+    // the index of the first modified word in the line. The following cells
+    // contain the data.
+    ///////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      //////////////////////// 
+      case INIT_CMD_UPDT_IDLE:	// Invalidate requests have highest priority
+        {
+
+          if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
+               r_xram_rsp_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            m_cpt_inval++;
+          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_write_to_init_cmd_inst_fifo.rok() ||
+                      r_write_to_init_cmd_multi_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+            m_cpt_update++;
+          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
+                      r_llsc_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+            m_cpt_update++;
+          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_INVAL_IDLE:	// Update requests have highest priority
+        {
+          if ( m_write_to_init_cmd_inst_fifo.rok() ||
+               r_write_to_init_cmd_multi_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+            m_cpt_update++;
+          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
+                      r_llsc_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+            m_cpt_update++;
+          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
+                      r_xram_rsp_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            m_cpt_inval++;
+          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_IDLE:	// Update requests for SCs have highest priority
+        {
+          if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
+               r_llsc_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+            m_cpt_update++;
+          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
+                      r_xram_rsp_to_init_cmd_multi_req.read()  ) {
+            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+            m_cpt_inval++;
+          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
+            m_cpt_inval++;
+          } else if ( m_write_to_init_cmd_inst_fifo.rok() ||
+                      r_write_to_init_cmd_multi_req.read() ) {
+            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+            m_cpt_update++;
+          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
+            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
+            m_cpt_inval++;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_INVAL_NLINE:	// send the cache line index
+        {
+          if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ){
+            if ( p_vci_ini.cmdack ) {
+              m_cpt_inval_mult++;
+              r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
+              xram_rsp_to_init_cmd_fifo_get = true;
+            }
+          } else {
+            if( r_xram_rsp_to_init_cmd_multi_req.read() ){
+              r_xram_rsp_to_init_cmd_multi_req = false;
+            } 
+            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_XRAM_BRDCAST:	// send the cache line index
+        {
+          if ( p_vci_ini.cmdack ) {
+            m_cpt_inval_brdcast++;
+            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
+            r_xram_rsp_to_init_cmd_brdcast_req = false;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_WRITE_BRDCAST:
+        {
+          if( p_vci_ini.cmdack ) {
+            m_cpt_inval_brdcast++;
+            r_write_to_init_cmd_brdcast_req = false;
+            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_NLINE:	// send the cache line index
+        {
+          if ( m_write_to_init_cmd_inst_fifo.rok() ) {
+            if ( p_vci_ini.cmdack ){
+              m_cpt_update_mult++;
+              r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
+            }
+          } else {
+            if ( r_write_to_init_cmd_multi_req.read() ){
+              r_write_to_init_cmd_multi_req = false;
+            }
+            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_UPDT_INDEX:	// send the first word index
+        {
+          r_init_cmd_cpt    = 0;
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) ) {
+              r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
+              write_to_init_cmd_fifo_get = true;
+            } else {
+              r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_BRDCAST:
+        {
+          if( p_vci_ini.cmdack ) {
+            m_cpt_inval_brdcast++;
+            r_llsc_to_init_cmd_brdcast_req = false;
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_NLINE:	// send the cache line index
+        {
+          if ( m_llsc_to_init_cmd_inst_fifo.rok() ){
+            if ( p_vci_ini.cmdack ){
+              m_cpt_update_mult++;
+              r_init_cmd_fsm = INIT_CMD_SC_UPDT_INDEX;
+            }
+          } else {
+            if( r_llsc_to_init_cmd_multi_req.read() ){
+              r_llsc_to_init_cmd_multi_req = false;
+            }
+            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
+          }
+          break;
+        }
+        /////////////////////////
+      case INIT_CMD_SC_UPDT_INDEX:	// send the first word index
+        {
+          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA;
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_SC_UPDT_DATA:	// send the data
+        {
+          if ( p_vci_ini.cmdack ) {
+            if(r_llsc_to_init_cmd_is_long.read()){
+                r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA_HIGH;
+            } else {
+                llsc_to_init_cmd_fifo_get = true;
+                r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+            }
+          }
+          break;
+        }
+        ////////////////////////
+      case INIT_CMD_SC_UPDT_DATA_HIGH:	// send the data upper
+        {
+          if ( p_vci_ini.cmdack ) {
+              llsc_to_init_cmd_fifo_get = true;
+              r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
+          }
+          break;
+        }
+
+
+    } // end switch r_init_cmd_fsm
+
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_RSP FSM
+    /////////////////////////////////////////////////////////////////////
+    // The TGT_RSP fsm sends the responses on the VCI target port
+    // with a round robin priority between six requests :
+    // - r_read_to_tgt_rsp_req
+    // - r_write_to_tgt_rsp_req
+    // - r_llsc_to_tgt_rsp_req
+    // - r_cleanup_to_tgt_rsp_req
+    // - r_init_rsp_to_tgt_rsp_req
+    // - r_xram_rsp_to_tgt_rsp_req
+    // The  ordering is :  read > write > llsc > cleanup > xram > init
+    /////////////////////////////////////////////////////////////////////
+
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      ///////////////////////
+      case TGT_RSP_READ_IDLE:		// write requests have the highest priority
+        {
+          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          break;
+        }
+        ////////////////////////
+      case TGT_RSP_WRITE_IDLE:		// llsc requests have the highest priority
+        {
+          if      ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_LLSC_IDLE:		// cleanup requests have the highest priority
+        {
+          if ( r_xram_rsp_to_tgt_rsp_req )  {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          break;
+        }
+      case TGT_RSP_XRAM_IDLE:		// init requests have the highest priority
+        {
+
+          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req )  {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_INIT_IDLE:		// cleanup requests have the highest priority
+        {
+          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          else if ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_CLEANUP_IDLE:		// read requests have the highest priority
+        {
+          if      ( r_read_to_tgt_rsp_req     ) {
+            r_tgt_rsp_fsm = TGT_RSP_READ;
+            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
+          }
+          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
+          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
+          else if ( r_xram_rsp_to_tgt_rsp_req ) {
+            r_tgt_rsp_fsm = TGT_RSP_XRAM;
+            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
+          }
+          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
+          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
+          break;
+        }
+        ///////////////////////
+      case TGT_RSP_READ:		// send the response
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) ) {
+              r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
+              r_read_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_WRITE:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
+            r_write_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_CLEANUP:		// send the write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
+            r_cleanup_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+        //////////////////
+      case TGT_RSP_LLSC:		// send one atomic word response
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_LLSC_IDLE;
+            r_llsc_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+
+        ///////////////////////
+      case TGT_RSP_XRAM:		// send the response
+        {
+          if ( p_vci_tgt.rspack ) {
+            if ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1)) {
+              r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
+              r_xram_rsp_to_tgt_rsp_req = false;
+            } else {
+              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
+            }
+          }
+          break;
+        }
+        ///////////////////
+      case TGT_RSP_INIT:		// send the pending write acknowledge
+        {
+          if ( p_vci_tgt.rspack ) {
+            r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
+            r_init_rsp_to_tgt_rsp_req = false;
+          }
+          break;
+        }
+    } // end switch tgt_rsp_fsm
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		NEW ALLOC_UPT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
+    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP 
+    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
+    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
+    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
+    // - The CLEANUP  FSM decrement an entry in UPT.
+    // The resource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_upt_fsm.read() ) {
+
+      ////////////////////////
+      case ALLOC_UPT_INIT_RSP:
+        if ( (r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK) && 
+             (r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR) ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_UPT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_UPT_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+        }
+        break;
+
+        ////////////////////////
+      case ALLOC_UPT_XRAM_RSP:
+        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK) 
+        { 
+          if       (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)       r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+        }
+        break;
+
+        //////////////////////////
+      case ALLOC_UPT_CLEANUP:
+        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
+        {
+          if      ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
+          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+        }
+        break;
+        
+        //////////////////////////
+      case ALLOC_UPT_LLSC:
+        if( (r_llsc_fsm.read() != SC_UPT_LOCK) && 
+            (r_llsc_fsm.read() != SC_INVAL_LOCK))
+        {
+          if      (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
+          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
+                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
+          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
+        }
+        break;
+
+    } // end switch r_alloc_upt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_DIR FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_DIR FSM allocates the access to the directory and
+    // the data cache with a round robin priority between 5 user FSMs :
+    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
+    // The ressource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_dir_fsm.read() ) {
+
+      ////////////////////
+      case ALLOC_DIR_READ:
+        if ( ( (r_read_fsm.read() != READ_DIR_LOCK) &&
+              (r_read_fsm.read() != READ_TRT_LOCK)  &&
+              (r_read_fsm.read() != READ_HEAP_LOCK))
+            ||
+            ( (r_read_fsm.read()        == READ_HEAP_LOCK) &&
+              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_READ) )
+            ||
+            ( (r_read_fsm.read()      == READ_TRT_LOCK)  &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)    )  ) 
+        {
+          if        (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   (r_llsc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_DIR_WRITE:
+        if ( ( (r_write_fsm.read() != WRITE_DIR_LOCK)     &&
+              (r_write_fsm.read() != WRITE_TRT_LOCK)     &&
+              (r_write_fsm.read() != WRITE_DIR_HIT_READ) &&
+              (r_write_fsm.read() != WRITE_DIR_HIT) &&
+              (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+              (r_write_fsm.read() != WRITE_INVAL_LOCK) &&
+              (r_write_fsm.read() != WRITE_UPT_LOCK) &&
+              (r_write_fsm.read() != WRITE_HEAP_LOCK))
+            ||
+            ( (r_write_fsm.read()       == WRITE_HEAP_LOCK) &&
+              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_WRITE) )
+            ||
+            ( (r_write_fsm.read()     == WRITE_TRT_LOCK) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
+        {
+          if        (r_llsc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+        }
+        break;
+
+        ////////////////////
+      case ALLOC_DIR_LLSC:
+        if ( ((r_llsc_fsm.read() != SC_DIR_LOCK)       &&
+              (r_llsc_fsm.read() != SC_DIR_HIT_READ )  &&
+              (r_llsc_fsm.read() != SC_DIR_HIT_WRITE ) &&
+              (r_llsc_fsm.read() != LLSC_TRT_LOCK )    &&
+              (r_llsc_fsm.read() != SC_TRT_LOCK)       &&
+              (r_llsc_fsm.read() != SC_INVAL_LOCK)     &&
+              (r_llsc_fsm.read() != SC_UPT_LOCK)       &&
+              (r_llsc_fsm.read() != SC_HEAP_LOCK))
+            ||
+            ( (r_llsc_fsm.read()       == SC_HEAP_LOCK) &&
+              (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) )
+            ||
+            ( (r_llsc_fsm.read()      == LLSC_TRT_LOCK ) &&
+              (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC)    ) )
+        {
+          if      (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)  r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+        }
+        break;
+
+        ///////////////////////
+      case ALLOC_DIR_CLEANUP:
+        if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
+            (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) )
+        {
+          if        (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if   (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if   (r_llsc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_DIR_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)   && 
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
+        {
+          if      (r_read_fsm.read() == READ_DIR_LOCK) 	        r_alloc_dir_fsm = ALLOC_DIR_READ;
+          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
+          else if (r_llsc_fsm.read() == SC_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_LLSC;
+          else if (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
+        }
+        break;
+
+    } // end switch alloc_dir_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_TRT FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
+    // with a round robin priority between 4 user FSMs :
+    // The cyclic priority is READ > WRITE > LLSC > XRAM_RSP
+    // The ressource is always allocated.
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    switch (r_alloc_trt_fsm) {
+
+      ////////////////////
+      case ALLOC_TRT_READ:
+        if ( r_read_fsm.read() != READ_TRT_LOCK ) 
+        {
+          if      ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ) )    r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+        }
+        break;
+        /////////////////////
+      case ALLOC_TRT_WRITE:
+        if ( (r_write_fsm.read() != WRITE_TRT_LOCK) &&
+             (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
+             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
+        {
+          if      ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+        }
+        break;
+        ////////////////////
+      case ALLOC_TRT_LLSC:
+        if ( (r_llsc_fsm.read() != LLSC_TRT_LOCK) &&
+             (r_llsc_fsm.read() != SC_TRT_LOCK) &&
+             (r_llsc_fsm.read() != SC_INVAL_LOCK))
+        { 
+          if      (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)     ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_XRAM_RSP:
+        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)  &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT)   &&
+            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)) {
+          if      ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
+                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
+          else if (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)    ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_TRT_IXR_RSP:
+        if ( (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
+            (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ) ) {
+          if      (r_read_fsm.read() == READ_TRT_LOCK) 	            r_alloc_trt_fsm = ALLOC_TRT_READ;
+          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
+                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
+          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
+                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
+        }
+        break;
+
+    } // end switch alloc_trt_fsm
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		ALLOC_HEAP FSM
+    ////////////////////////////////////////////////////////////////////////////////////
+    // The ALLOC_HEAP FSM allocates the access to the heap
+    // with a round robin priority between 5 user FSMs :
+    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
+    // The ressource is always allocated.
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    switch ( r_alloc_heap_fsm.read() ) {
+
+      ////////////////////
+      case ALLOC_HEAP_READ:
+        if (  (r_read_fsm.read() != READ_HEAP_LOCK) &&
+              (r_read_fsm.read() != READ_HEAP_ERASE)     ) 
+        {
+          if        (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+          else if   (r_llsc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+        }
+        break;
+
+        /////////////////////
+      case ALLOC_HEAP_WRITE:
+        if (  (r_write_fsm.read() != WRITE_HEAP_LOCK)   &&
+              (r_write_fsm.read() != WRITE_UPT_REQ)     &&
+              (r_write_fsm.read() != WRITE_UPDATE)  )
+        {
+          if        (r_llsc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_HEAP_LOCK) 	        r_alloc_heap_fsm = ALLOC_HEAP_READ;
+        }
+        break;
+
+        ////////////////////
+      case ALLOC_HEAP_LLSC:
+        if (  (r_llsc_fsm.read() != SC_HEAP_LOCK)  &&
+              (r_llsc_fsm.read() != SC_UPT_REQ )    &&
+              (r_llsc_fsm.read() != SC_UPDATE)  )
+        {
+          if      (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+          else if (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+          else if (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
+          else if (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+        }
+        break;
+
+        ///////////////////////
+      case ALLOC_HEAP_CLEANUP:
+        if ( (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) &&
+            (r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH)&&
+            (r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN)    )
+        {
+          if        (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
+          else if   (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
+          else if   (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+          else if   (r_llsc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+        }
+        break;
+        ////////////////////////
+      case ALLOC_HEAP_XRAM_RSP:
+        if ( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE )
+        {
+          if        (r_read_fsm.read() == READ_HEAP_LOCK) 	        r_alloc_heap_fsm = ALLOC_HEAP_READ;
+          else if   (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
+          else if   (r_llsc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
+          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
+        }
+        break;
+
+    } // end switch alloc_heap_fsm
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to READ FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_read_fifo_put ) {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
+        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+      } else {
+        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
+        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+      }
+    } else {
+      if ( cmd_read_fifo_get ) {
+        m_cmd_read_addr_fifo.simple_get();
+        m_cmd_read_length_fifo.simple_get();
+        m_cmd_read_srcid_fifo.simple_get();
+        m_cmd_read_trdid_fifo.simple_get();
+        m_cmd_read_pktid_fifo.simple_get();
+      }
+    }
+    /////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to WRITE FIFO
+    /////////////////////////////////////////////////////////////////////
+
+    if ( cmd_write_fifo_put ) {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
+      } else {
+        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
+        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
+        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
+      }
+    } else {
+      if ( cmd_write_fifo_get ) {
+        m_cmd_write_addr_fifo.simple_get();
+        m_cmd_write_eop_fifo.simple_get();
+        m_cmd_write_srcid_fifo.simple_get();
+        m_cmd_write_trdid_fifo.simple_get();
+        m_cmd_write_pktid_fifo.simple_get();
+        m_cmd_write_data_fifo.simple_get();
+        m_cmd_write_be_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		TGT_CMD to LLSC FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( cmd_llsc_fifo_put ) {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_eop_fifo.put_and_get(p_vci_tgt.eop.read()); 
+        m_cmd_llsc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
+      } else {
+        m_cmd_llsc_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
+        m_cmd_llsc_eop_fifo.simple_put(p_vci_tgt.eop.read()); 
+        m_cmd_llsc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
+        m_cmd_llsc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
+        m_cmd_llsc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
+        m_cmd_llsc_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
+      }
+    } else {
+      if ( cmd_llsc_fifo_get ) {
+        m_cmd_llsc_addr_fifo.simple_get();
+        m_cmd_llsc_eop_fifo.simple_get();
+        m_cmd_llsc_srcid_fifo.simple_get();
+        m_cmd_llsc_trdid_fifo.simple_get();
+        m_cmd_llsc_pktid_fifo.simple_get();
+        m_cmd_llsc_wdata_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		WRITE to INIT_CMD FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( write_to_init_cmd_fifo_put ) {
+      if ( write_to_init_cmd_fifo_get ) {
+        m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
+        m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
+      } else {
+        m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
+        m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
+      }
+    } else {
+      if ( write_to_init_cmd_fifo_get ) {
+        m_write_to_init_cmd_inst_fifo.simple_get();
+        m_write_to_init_cmd_srcid_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		XRAM_RSP to INIT_CMD FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( xram_rsp_to_init_cmd_fifo_put ) {
+      if ( xram_rsp_to_init_cmd_fifo_get ) {
+        m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
+        m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
+      } else {
+        m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
+        m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
+      }
+    } else {
+      if ( xram_rsp_to_init_cmd_fifo_get ) {
+        m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
+        m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
+      }
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    //		LLSC to INIT_CMD FIFO
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    if ( llsc_to_init_cmd_fifo_put ) {
+      if ( llsc_to_init_cmd_fifo_get ) {
+        m_llsc_to_init_cmd_inst_fifo.put_and_get(llsc_to_init_cmd_fifo_inst);
+        m_llsc_to_init_cmd_srcid_fifo.put_and_get(llsc_to_init_cmd_fifo_srcid);
+      } else {
+        m_llsc_to_init_cmd_inst_fifo.simple_put(llsc_to_init_cmd_fifo_inst);
+        m_llsc_to_init_cmd_srcid_fifo.simple_put(llsc_to_init_cmd_fifo_srcid);
+      }
+    } else {
+      if ( llsc_to_init_cmd_fifo_get ) {
+        m_llsc_to_init_cmd_inst_fifo.simple_get();
+        m_llsc_to_init_cmd_srcid_fifo.simple_get();
+      }
+    }
+
+
+  //////////////////////////////////////////////////////////////
+    m_cpt_cycles++;
+
+  } // end transition()
+
+  /////////////////////////////
+  tmpl(void)::genMoore()
+    /////////////////////////////
+  {
+    ////////////////////////////////////////////////////////////
+    // Command signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////////////
+
+
+    p_vci_ixr.be      = 0xF;
+    p_vci_ixr.pktid   = 0;
+    p_vci_ixr.srcid   = m_srcid_ixr;
+    p_vci_ixr.cons    = false;
+    p_vci_ixr.wrap    = false;
+    p_vci_ixr.contig  = true;
+    p_vci_ixr.clen    = 0;
+    p_vci_ixr.cfixed  = false;
+
+    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
+      p_vci_ixr.cmd     = vci_param::CMD_READ;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = 0x00000000;
+      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = true;
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_LLSC_NLINE ) {
+      if(r_llsc_to_ixr_cmd_write.read()){
+        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)((r_llsc_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = r_llsc_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+      } else {
+        p_vci_ixr.cmd     = vci_param::CMD_READ;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)(r_llsc_to_ixr_cmd_nline.read()*m_words*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = 0x00000000;
+        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = true;
+      }
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
+      if(r_write_to_ixr_cmd_write.read()){
+        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+      } else {
+        p_vci_ixr.cmd     = vci_param::CMD_READ;
+        p_vci_ixr.cmdval  = true;
+        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
+        p_vci_ixr.plen    = m_words*4;
+        p_vci_ixr.wdata   = 0x00000000;
+        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
+        p_vci_ixr.eop     = true;
+      }
+    } 
+    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
+      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
+      p_vci_ixr.cmdval  = true;
+      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
+      p_vci_ixr.plen    = m_words*4;
+      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
+      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
+      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
+    } else {
+      p_vci_ixr.cmdval  = false;
+      p_vci_ixr.address = 0;
+      p_vci_ixr.plen    = 0;
+      p_vci_ixr.wdata   = 0;
+      p_vci_ixr.trdid   = 0;
+      p_vci_ixr.eop	= false;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_ixr port
+    ////////////////////////////////////////////////////
+
+    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
+          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) || 
+        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
+    else                                        p_vci_ixr.rspack = false;
+
+    ////////////////////////////////////////////////////
+    // Command signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+
+    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
+      case TGT_CMD_IDLE:
+        p_vci_tgt.cmdack  = false;
+        break;
+      case TGT_CMD_READ:
+        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
+        break;
+      case TGT_CMD_READ_EOP:
+        p_vci_tgt.cmdack  = true;
+        break;
+      case TGT_CMD_WRITE:
+        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
+        break;
+      case TGT_CMD_ATOMIC:
+        p_vci_tgt.cmdack  = m_cmd_llsc_addr_fifo.wok();
+        break;
+      default:
+        p_vci_tgt.cmdack = false;
+        break;
+    }
+
+    ////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt port
+    ////////////////////////////////////////////////////
+    switch ( r_tgt_rsp_fsm.read() ) {
+
+      case TGT_RSP_READ_IDLE:
+      case TGT_RSP_WRITE_IDLE:
+      case TGT_RSP_LLSC_IDLE:
+      case TGT_RSP_XRAM_IDLE:
+      case TGT_RSP_INIT_IDLE:
+      case TGT_RSP_CLEANUP_IDLE:
+        p_vci_tgt.rspval  = false;
+        p_vci_tgt.rsrcid  = 0;
+        p_vci_tgt.rdata   = 0;
+        p_vci_tgt.rpktid  = 0;
+        p_vci_tgt.rtrdid  = 0;
+        p_vci_tgt.rerror  = 0;
+        p_vci_tgt.reop    = false;	
+        break;
+      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();
+        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
+        break;
+      case TGT_RSP_WRITE:
+        p_vci_tgt.rspval   = true;
+        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   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_CLEANUP:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      case TGT_RSP_LLSC:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = r_llsc_to_tgt_rsp_data.read();
+        p_vci_tgt.rsrcid   = r_llsc_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_llsc_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_llsc_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = true;
+        break;
+      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();
+        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
+        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
+        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
+        p_vci_tgt.rerror   = 0;
+        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1));
+        break;
+      case TGT_RSP_INIT:
+        p_vci_tgt.rspval   = true;
+        p_vci_tgt.rdata    = 0;
+        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;
+        p_vci_tgt.reop     = true;	
+        break;
+    } // end switch r_tgt_rsp_fsm
+
+    ///////////////////////////////////////////////////
+    // Command signals on the p_vci_ini port
+    ///////////////////////////////////////////////////
+
+    p_vci_ini.cmd     = vci_param::CMD_WRITE;
+    p_vci_ini.srcid   = m_srcid_ini;
+    p_vci_ini.pktid   = 0;
+    p_vci_ini.cons    = true;
+    p_vci_ini.wrap    = false;
+    p_vci_ini.contig  = false;
+    p_vci_ini.clen    = 0;
+    p_vci_ini.cfixed  = false;
+
+    switch ( r_init_cmd_fsm.read() ) {
+
+      case INIT_CMD_UPDT_IDLE:
+      case INIT_CMD_INVAL_IDLE:
+      case INIT_CMD_SC_UPDT_IDLE:
+        p_vci_ini.cmdval  = false;
+        p_vci_ini.address = 0;
+        p_vci_ini.wdata   = 0;
+        p_vci_ini.be      = 0;
+        p_vci_ini.plen    = 0;
+        p_vci_ini.trdid   = 0;
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_INVAL_NLINE:
+        p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
+        if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
+          if(m_xram_rsp_to_init_cmd_inst_fifo.read()) {
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_xram_rsp_to_init_cmd_srcid_fifo.read()]+4);
+          } else {
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_xram_rsp_to_init_cmd_srcid_fifo.read()]);
+          }
+        } else p_vci_ini.address = 0; // prevent segmentation faults by reading an empty fifo
+        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4;
+        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+      case INIT_CMD_XRAM_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4;
+        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+
+      case INIT_CMD_WRITE_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4 ;
+        p_vci_ini.eop     = true;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_NLINE:
+        p_vci_ini.cmdval  = m_write_to_init_cmd_inst_fifo.rok();
+        if(m_write_to_init_cmd_inst_fifo.rok()){
+          if(m_write_to_init_cmd_inst_fifo.read()) {
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 12);
+          } else {
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 8);
+          }
+        } else {
+          p_vci_ini.address = 0;
+        }
+        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.eop     = false;
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        if(m_write_to_init_cmd_inst_fifo.read()) {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 12);
+        } else {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 8);
+        }
+        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        if(m_write_to_init_cmd_inst_fifo.read()) {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 12);
+        } else {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 8);
+        }
+        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
+          r_write_to_init_cmd_index.read()].read();
+        p_vci_ini.be      = r_write_to_init_cmd_be[r_init_cmd_cpt.read() +
+            r_write_to_init_cmd_index.read()].read()  ;
+        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
+        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
+        break;
+
+      case INIT_CMD_SC_BRDCAST:
+        p_vci_ini.cmdval  = true;
+        p_vci_ini.address = BROADCAST_ADDR;
+        p_vci_ini.wdata   = (addr_t)r_llsc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32) & 0x3);
+        p_vci_ini.plen    = 4 ;
+        p_vci_ini.eop     = true;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_SC_UPDT_NLINE:
+        p_vci_ini.cmdval  = m_llsc_to_init_cmd_inst_fifo.rok();
+        if(m_llsc_to_init_cmd_inst_fifo.rok()){
+          if( m_llsc_to_init_cmd_inst_fifo.read() ) {
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 12);
+          } else {
+            p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 8);
+          }
+        } else {
+          p_vci_ini.address = 0;
+        }
+        p_vci_ini.wdata   = (uint32_t)r_llsc_to_init_cmd_nline.read();
+        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32 ) & 0x3);
+        if(r_llsc_to_init_cmd_is_long.read()){
+            p_vci_ini.plen    = 4 * 4;
+        } else {
+            p_vci_ini.plen    = 4 * 3;
+        }
+        p_vci_ini.eop     = false;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        break;
+      case INIT_CMD_SC_UPDT_INDEX:
+        p_vci_ini.cmdval  = true;
+        if( m_llsc_to_init_cmd_inst_fifo.read() ) {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 12);
+        } else {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 8);
+        }
+        p_vci_ini.wdata   = r_llsc_to_init_cmd_index.read();
+        p_vci_ini.be      = 0xF;
+        if(r_llsc_to_init_cmd_is_long.read()){
+            p_vci_ini.plen    = 4 * 4;
+        } else {
+            p_vci_ini.plen    = 4 * 3;
+        }
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = false;
+        break;
+      case INIT_CMD_SC_UPDT_DATA:
+        p_vci_ini.cmdval  = true;
+        if( m_llsc_to_init_cmd_inst_fifo.read() ) {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 12);
+        } else {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 8);
+        }
+        p_vci_ini.wdata   = r_llsc_to_init_cmd_wdata.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        if(r_llsc_to_init_cmd_is_long.read()){
+            p_vci_ini.plen    = 4 * 4;
+            p_vci_ini.eop     = false;
+        } else {
+            p_vci_ini.plen    = 4 * 3;
+            p_vci_ini.eop     = true;
+        }
+        break;
+      case INIT_CMD_SC_UPDT_DATA_HIGH:
+        p_vci_ini.cmdval  = true;
+        if( m_llsc_to_init_cmd_inst_fifo.read() ) {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 12);
+        } else {
+          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 8);
+        }
+        p_vci_ini.wdata   = r_llsc_to_init_cmd_wdata_high.read();
+        p_vci_ini.be      = 0xF;
+        p_vci_ini.plen    = 4 * 4;
+        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
+        p_vci_ini.eop     = true;
+        break;
+
+    } // end switch r_init_cmd_fsm
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_ini port
+    //////////////////////////////////////////////////////
+
+    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
+    else                                          p_vci_ini.rspack  = false;
+
+    //////////////////////////////////////////////////////
+    // Response signals on the p_vci_tgt_cleanup port
+    //////////////////////////////////////////////////////
+    p_vci_tgt_cleanup.rspval = false;
+    p_vci_tgt_cleanup.rsrcid = 0;
+    p_vci_tgt_cleanup.rdata  = 0;
+    p_vci_tgt_cleanup.rpktid = 0;
+    p_vci_tgt_cleanup.rtrdid = 0;
+    p_vci_tgt_cleanup.rerror = 0;
+    p_vci_tgt_cleanup.reop   = false;
+    p_vci_tgt_cleanup.cmdack = false ;
+
+    switch(r_cleanup_fsm.read()){
+      case CLEANUP_IDLE:
+        {
+          p_vci_tgt_cleanup.cmdack = true ;
+          break;
+        }
+      case CLEANUP_RSP:
+        {
+          p_vci_tgt_cleanup.rspval = true;
+          p_vci_tgt_cleanup.rdata  = 0;
+          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
+          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
+          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
+          p_vci_tgt_cleanup.rerror = 0;
+          p_vci_tgt_cleanup.reop   = 1;
+          break;
+        }
+
+    }
+
+  } // end genMoore()
+
+}} // end name space
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
