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 374)
+++ /trunk/modules/vci_block_device_tsar/caba/metadata/vci_block_device_tsar.sd	(revision 374)
@@ -0,0 +1,35 @@
+
+# -*- python -*-
+
+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('common:mapping_table'),
+		],
+	instance_parameters = [
+        	parameter.Module('mt', typename = 'common:mapping_table', auto = 'env:mapping_table'),
+        	parameter.IntTab('srcid'),
+        	parameter.IntTab('tgtid'),
+        	parameter.String('filename'),
+		parameter.Int('block_size'),
+		parameter.Int('burst_size'),
+		parameter.Int('latency'),
+        	],
+	   extensions = [
+		'dsx:addressable=tgtid',
+		'dsx:max_segments=1',
+		'dsx:get_ident=tgtid:p_vci_target:mt,srcid:p_vci_initiator:mt',
+		],
+)
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 374)
+++ /trunk/modules/vci_block_device_tsar/caba/source/include/vci_block_device_tsar.h	(revision 374)
@@ -0,0 +1,239 @@
+
+/* -*- 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
+ *         alain.greiner@lip6.fr april 2011
+ *
+ * Maintainers: alain
+ */
+
+//////////////////////////////////////////////////////////////////////////////////////
+// This component is a simplified disk controller with a VCI interface.
+// This component can perform data transfers between one single file belonging 
+// to the host system and a buffer in the memory of the virtual prototype.
+// The file name is an argument of the constructor.
+// This component has a DMA capability, and is both a target and an initiator.
+// The block size (bytes), and the burst size (bytes) must be power of 2.
+// The burst size is typically a cache line. 
+// If the memory buffer is not constrained to be aligned on a burst boundary. 
+// Both read and write transfers are supported. An IRQ is optionally
+// asserted when the transfer is completed. 
+//
+// As a target this block device controler contains 8 memory mapped registers,
+// taking 32 bytes in the address space.
+// - BLOCK_DEVICE_BUFFER        0x00 (read/write)    Memory buffer base address.
+// - BLOCK_DEVICE_COUNT         0x04 (read/write)    Number of blocks to be transfered.
+// - BLOCK_DEVICE_LBA           0x08 (read/write)    Index of first block in the file.
+// - BLOCK_DEVICE_OP            0x0C (write-only)    Writing here starts the operation.
+// - BLOCK_DEVICE_STATUS        0x10 (read-only)     Block Device status.
+// - BLOCK_DEVICE_IRQ_ENABLE    0x14 (read/write)    IRQ enabled if non zero.
+// - BLOCK_DEVICE_SIZE          0x18 (read-only)     Number of addressable blocks.
+// - BLOCK_DEVICE_BLOCK_SIZE    0x1C (read_only)     Block size in bytes.
+//
+// The following operations codes are supported: 
+// - BLOCK_DEVICE_NOOP          No operation
+// - BLOCK_DEVICE_READ          From block device to memory
+// - BLOCK_DEVICE_WRITE         From memory to block device 
+//
+// The BLOCK_DEVICE_STATUS is actually defined by the initiator FSM state.
+// The following values are defined for device status:
+// -BLOCK_DEVICE_IDLE           0
+// -BLOCK_DEVICE_BUSY           1
+// -BLOCK_DEVICE_READ_SUCCESS   2
+// -BLOCK_DEVICE_WRITE_SUCCESS  3
+// -BLOCK_DEVICE_READ_ERROR     4
+// -BLOCK_DEVICE_WRITE_ERROR    5
+//
+// In the 4 states READ_ERROR, READ_SUCCESS, WRITE_ERROR, WRITE_SUCCESS,
+// the IRQ is asserted (if it is enabled).
+// A read access to the BLOCK_DEVICE_STATUS in these 4 states reset 
+// the initiator FSM state to IDLE, and acknowledge the IRQ.
+// Any write access to registers BUFFER, COUNT, LBA, OP is ignored
+// if the device is not IDLE.
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef SOCLIB_VCI_BLOCK_DEVICE_TSAR_H
+#define SOCLIB_VCI_BLOCK_DEVICE_TSAR_H
+
+#include <stdint.h>
+#include <systemc>
+#include "caba_base_module.h"
+#include "mapping_table.h"
+#include "vci_initiator.h"
+#include "vci_target.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+template<typename vci_param>
+class VciBlockDeviceTsar
+	: public caba::BaseModule
+{
+private:
+
+    // Registers
+    sc_signal<int>            	 r_target_fsm;   	 // target fsm state register
+    sc_signal<int>               r_initiator_fsm;    // initiator fsm state register
+    sc_signal<bool>              r_irq_enable;   	 // default value is true
+    sc_signal<uint32_t>          r_nblocks;      	 // number of blocks in transfer
+    sc_signal<uint32_t>          r_buf_address;  	 // memory buffer address
+    sc_signal<uint32_t>          r_lba;          	 // first block index
+    sc_signal<bool>              r_read;         	 // requested operation
+    sc_signal<uint32_t>          r_index;        	 // flit index in local buffer
+    sc_signal<uint32_t>          r_latency_count;    // latency counter 
+    sc_signal<uint32_t>          r_flit_count;   	 // flit counter (in a burst)
+    sc_signal<uint32_t>          r_burst_count;   	 // burst counter (in a block)
+    sc_signal<uint32_t>          r_block_count;  	 // block counter (in a transfer)
+    sc_signal<uint32_t>          r_burst_offset;     // number of non aligned flits
+    sc_signal<uint32_t>          r_burst_nflits;     // number of flits in a burst
+    sc_signal<bool>              r_go;           	 // command from T_FSM to M_FSM
+
+    sc_signal<sc_dt::sc_uint<vci_param::S> >	r_srcid;		// save srcid
+    sc_signal<sc_dt::sc_uint<vci_param::T> >	r_trdid;		// save trdid
+    sc_signal<sc_dt::sc_uint<vci_param::P> >	r_pktid;		// save pktid
+
+    uint32_t*                    r_local_buffer; 	 // capacity is one block 
+
+    // structural parameters
+    soclib::common::Segment      m_segment;      	 // segment associated to target
+    uint32_t                     m_srcid;        	 // initiator index
+    int                          m_fd;           	 // File descriptor
+    uint64_t                     m_device_size;  	 // Total number of blocks
+    const uint32_t               m_flits_per_block;	 // number of flits in a block
+    const uint32_t               m_flits_per_burst;	 // number of flits in a burst
+    const uint32_t               m_bursts_per_block; // number of bursts in a block
+    const uint32_t               m_latency;      	 // device latency
+
+    // methods
+    void transition();
+    void genMoore();
+
+    //  Master FSM states
+    enum {
+    M_IDLE              = 0,
+
+    M_READ_BLOCK        = 1,
+    M_READ_BURST        = 2,
+    M_READ_CMD          = 3,
+    M_READ_RSP          = 4,
+    M_READ_SUCCESS      = 5,
+    M_READ_ERROR        = 6,
+
+    M_WRITE_BURST       = 7,
+    M_WRITE_CMD         = 8,
+    M_WRITE_RSP         = 9,
+    M_WRITE_BLOCK       = 10,
+    M_WRITE_SUCCESS     = 11,
+    M_WRITE_ERROR       = 12,
+    };
+
+    // Target FSM states
+    enum {
+    T_IDLE              = 0,
+    T_WRITE_BUFFER      = 1,
+    T_READ_BUFFER       = 2,
+    T_WRITE_COUNT       = 3,
+    T_READ_COUNT        = 4,
+    T_WRITE_LBA         = 5,
+    T_READ_LBA          = 6,
+    T_WRITE_OP          = 7,
+    T_READ_STATUS       = 8,
+    T_WRITE_IRQEN       = 9,
+    T_READ_IRQEN        = 10,
+    T_READ_SIZE         = 11,
+    T_READ_BLOCK        = 12,
+    T_READ_ERROR        = 13,
+    T_WRITE_ERROR       = 14,
+    };
+
+    // Error codes values
+    enum {
+    VCI_READ_OK		= 0,
+    VCI_READ_ERROR	= 1,
+    VCI_WRITE_OK	= 2,
+    VCI_WRITE_ERROR	= 3,
+    };
+
+    /* transaction type, pktid field */
+    enum transaction_type_e
+    {
+      // b3 unused
+      // b2 READ / NOT READ
+      // Si READ
+      //  b1 DATA / INS
+      //  b0 UNC / MISS
+      // Si NOT READ
+      //  b1 accÃšs table llsc type SW / other
+      //  b2 WRITE/CAS/LL/SC
+      TYPE_READ_DATA_UNC          = 0x0,
+      TYPE_READ_DATA_MISS         = 0x1,
+      TYPE_READ_INS_UNC           = 0x2,
+      TYPE_READ_INS_MISS          = 0x3,
+      TYPE_WRITE                  = 0x4,
+      TYPE_CAS                    = 0x5,
+      TYPE_LL                     = 0x6,
+      TYPE_SC                     = 0x7
+    };
+
+protected:
+
+    SC_HAS_PROCESS(VciBlockDeviceTsar);
+
+public:
+
+    // ports
+    sc_in<bool> 					      p_clk;
+    sc_in<bool> 					      p_resetn;
+    soclib::caba::VciInitiator<vci_param> p_vci_initiator;
+    soclib::caba::VciTarget<vci_param>    p_vci_target;
+    sc_out<bool> 					      p_irq;
+
+    void print_trace();
+
+    // Constructor   
+    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,
+        const uint32_t	                    latency = 0);
+};
+
+}}
+
+#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 374)
+++ /trunk/modules/vci_block_device_tsar/caba/source/src/vci_block_device_tsar.cpp	(revision 374)
@@ -0,0 +1,684 @@
+/* -*- 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
+ *         alain.greiner@lip6.fr april 2011
+ *
+ * Maintainers: alain
+ */
+
+#include <stdint.h>
+#include <iostream>
+#include <fcntl.h>
+#include "vci_block_device_tsar.h"
+
+namespace soclib { namespace caba {
+
+#define tmpl(t) template<typename vci_param> t VciBlockDeviceTsar<vci_param>
+
+using namespace soclib::caba;
+using namespace soclib::common;
+
+////////////////////////
+tmpl(void)::transition()
+{
+    if(p_resetn.read() == false) 
+    {
+        r_initiator_fsm = M_IDLE;
+        r_target_fsm    = T_IDLE;
+        r_irq_enable    = true;
+        r_go            = false;
+        return;
+    } 
+
+    //////////////////////////////////////////////////////////////////////////////
+    // The Target FSM controls the following registers:
+    // r_target_fsm, r_irq_enable, r_nblocks, r_buf adress, r_lba, r_go, r_read
+    //////////////////////////////////////////////////////////////////////////////
+
+    switch(r_target_fsm) {
+    ////////////
+    case T_IDLE:
+    {
+        if ( p_vci_target.cmdval.read() ) 
+        { 
+            r_srcid = p_vci_target.srcid.read();
+            r_trdid = p_vci_target.trdid.read();
+            r_pktid = p_vci_target.pktid.read();
+            sc_dt::sc_uint<vci_param::N> address = p_vci_target.address.read();
+            bool                  read    = (p_vci_target.cmd.read() == vci_param::CMD_READ);
+            uint32_t              cell    = (uint32_t)((address & 0x1F)>>2);
+
+            if     ( !read && !m_segment.contains(address) )      r_target_fsm = T_WRITE_ERROR;
+            else if(  read && !m_segment.contains(address) )      r_target_fsm = T_READ_ERROR;
+            else if( !read && !p_vci_target.eop.read() )          r_target_fsm = T_WRITE_ERROR;
+            else if(  read && !p_vci_target.eop.read() )          r_target_fsm = T_READ_ERROR;
+            else if( !read && (cell == BLOCK_DEVICE_BUFFER) )     r_target_fsm = T_WRITE_BUFFER;
+            else if(  read && (cell == BLOCK_DEVICE_BUFFER) )     r_target_fsm = T_READ_BUFFER;
+            else if( !read && (cell == BLOCK_DEVICE_COUNT) )      r_target_fsm = T_WRITE_COUNT;
+            else if(  read && (cell == BLOCK_DEVICE_COUNT) )      r_target_fsm = T_READ_COUNT;
+            else if( !read && (cell == BLOCK_DEVICE_LBA) )        r_target_fsm = T_WRITE_LBA;
+            else if(  read && (cell == BLOCK_DEVICE_LBA) )        r_target_fsm = T_READ_LBA;
+            else if( !read && (cell == BLOCK_DEVICE_OP) )         r_target_fsm = T_WRITE_OP;
+            else if(  read && (cell == BLOCK_DEVICE_STATUS) )     r_target_fsm = T_READ_STATUS;
+            else if( !read && (cell == BLOCK_DEVICE_IRQ_ENABLE) ) r_target_fsm = T_WRITE_IRQEN;
+            else if(  read && (cell == BLOCK_DEVICE_IRQ_ENABLE) ) r_target_fsm = T_READ_IRQEN;
+            else if(  read && (cell == BLOCK_DEVICE_SIZE) )       r_target_fsm = T_READ_SIZE;
+            else if(  read && (cell == BLOCK_DEVICE_BLOCK_SIZE) ) r_target_fsm = T_READ_BLOCK;
+        }
+        break;
+    }
+    ////////////////////
+    case T_WRITE_BUFFER:
+    {
+        if ( r_initiator_fsm == M_IDLE )  r_buf_address = (uint32_t)p_vci_target.wdata.read();
+        if ( p_vci_target.rspack.read() ) r_target_fsm = T_IDLE;
+        break;
+    }
+    ///////////////////
+    case T_WRITE_COUNT:
+    {
+        if ( r_initiator_fsm == M_IDLE )  r_nblocks = (uint32_t)p_vci_target.wdata.read();
+        if ( p_vci_target.rspack.read() ) r_target_fsm = T_IDLE;
+        break;
+    }
+    /////////////////
+    case T_WRITE_LBA:
+    {
+        if ( r_initiator_fsm == M_IDLE )  r_lba = (uint32_t)p_vci_target.wdata.read();
+        if ( p_vci_target.rspack.read() ) r_target_fsm = T_IDLE;
+        break;
+    }
+    ////////////////
+    case T_WRITE_OP:
+    {
+        if ( r_initiator_fsm == M_IDLE ) 
+        {
+            if ( (uint32_t)p_vci_target.wdata.read() == BLOCK_DEVICE_READ )
+            {
+                r_read = true;
+                r_go = true;
+            }
+            else if ( (uint32_t)p_vci_target.wdata.read() == BLOCK_DEVICE_WRITE)
+            {
+                r_read = false;
+                r_go = true;
+            }
+        }
+        if ( p_vci_target.rspack.read() ) r_target_fsm = T_IDLE;
+        break;
+    }
+    ///////////////////
+    case T_WRITE_IRQEN:
+    {
+        r_irq_enable = (p_vci_target.wdata.read() != 0);
+        if ( p_vci_target.rspack.read() ) r_target_fsm = T_IDLE;
+        break;
+    }
+    ///////////////////
+    case T_READ_BUFFER:
+    case T_READ_COUNT:
+    case T_READ_LBA:
+    case T_READ_IRQEN:
+    case T_READ_SIZE:
+    case T_READ_BLOCK:
+    case T_READ_ERROR:
+    case T_WRITE_ERROR:
+    {
+        if ( p_vci_target.rspack.read() ) r_target_fsm = T_IDLE;
+        break;
+    }
+    ///////////////////
+    case T_READ_STATUS:
+    {
+        if ( p_vci_target.rspack.read() ) 
+        {
+            r_target_fsm = T_IDLE;
+            if( (r_initiator_fsm == M_READ_SUCCESS ) ||
+                (r_initiator_fsm == M_READ_ERROR   ) ||
+                (r_initiator_fsm == M_WRITE_SUCCESS) ||
+                (r_initiator_fsm == M_WRITE_ERROR  ) ) r_go = false;
+        }
+        break;
+    }
+    } // end switch target fsm
+	
+    //////////////////////////////////////////////////////////////////////////////
+    // The initiator FSM executes a loop, transfering one block per iteration.
+    // Each block is split in bursts, and the number of bursts depends
+    // on the memory buffer alignment on a burst boundary:
+    // - If buffer aligned, all burst have the same length (m_flits_per burst)
+    //   and the number of bursts is (m_bursts_per_block).
+    // - If buffer not aligned, the number of bursts is (m_bursts_per_block + 1)
+    //   and first and last burst are shorter, because all flits in a burst 
+    //   must be contained in a single cache line.
+    //   first burst => nflits = m_flits_per_burst - offset
+    //   last  burst => nflits = offset
+    //   other burst => nflits = m_flits_per_burst
+    //////////////////////////////////////////////////////////////////////////////
+
+    switch( r_initiator_fsm.read() ) {
+    ////////////
+    case M_IDLE: 	// check buffer alignment to compute the number of bursts
+    {
+        if ( r_go.read() ) 
+        {
+            r_index         = 0;
+            r_block_count   = 0;
+            r_burst_count   = 0;
+            r_flit_count    = 0;
+            r_latency_count = m_latency;
+
+            // compute r_burst_offset (zero when buffer aligned)
+            r_burst_offset = (r_buf_address.read()>>2) % m_flits_per_burst;
+
+            // start tranfer
+            if ( r_read.read() ) 	r_initiator_fsm = M_READ_BLOCK;
+            else                    r_initiator_fsm = M_WRITE_BURST;
+        }
+        break;
+    } 
+    //////////////////
+    case M_READ_BLOCK:  // read one block from disk after waiting m_latency cycles
+    {
+        if ( r_latency_count.read() == 0 )
+        {
+            r_latency_count = m_latency;
+            ::lseek(m_fd, (r_lba + r_block_count)*m_flits_per_block*4, SEEK_SET);
+            if( ::read(m_fd, r_local_buffer, m_flits_per_block*4) < 0 )  
+            {
+                r_initiator_fsm = M_READ_ERROR;
+            }
+            else   
+            {
+                r_burst_count   = 0;
+                r_flit_count    = 0;
+                r_initiator_fsm = M_READ_BURST;
+            }
+        }
+        else
+        {
+            r_latency_count = r_latency_count.read() - 1;
+        }
+        break;
+    }
+    //////////////////
+    case M_READ_BURST:  // Compute the number of flits in the burst
+    {
+        uint32_t offset = r_burst_offset.read();
+
+        if ( offset )                  // buffer not aligned
+        {
+            if ( r_burst_count.read() == 0 ) r_burst_nflits = m_flits_per_burst - offset;
+            else if ( r_burst_count.read() == m_bursts_per_block ) r_burst_nflits = offset;
+            else r_burst_nflits = m_flits_per_burst;
+        }
+        else                           // buffer aligned
+        {
+            r_burst_nflits = m_flits_per_burst;
+        }
+        r_initiator_fsm =  M_READ_CMD;
+        break;
+    }
+    ////////////////
+    case M_READ_CMD:	// Send a multi-flits VCI WRITE command
+    {
+        if ( p_vci_initiator.cmdack.read() )
+        {
+            if ( r_flit_count == (r_burst_nflits.read() - 1) ) // last flit in a burst
+            {
+                r_initiator_fsm = M_READ_RSP;
+                r_flit_count = 0;
+            }
+            else                                               // not the last flit
+            {
+                r_flit_count = r_flit_count.read() + 1;
+            }
+
+            // compute next flit address and next local buffer index
+            r_buf_address = r_buf_address.read() + 4;
+            r_index       = r_index.read() + 1;
+        }
+        break;
+    }
+    ////////////////
+    case M_READ_RSP: 	// Wait a single flit VCI WRITE response
+    {
+        if ( p_vci_initiator.rspval.read() )
+        {
+            bool aligned = (r_burst_offset.read() == 0);
+
+            if ( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
+            {
+                r_initiator_fsm = M_READ_ERROR;
+            }
+            else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or 
+                      (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) )
+            {
+                if ( r_block_count.read() == (r_nblocks.read()-1) ) // last burst of last block 
+                {
+                    r_initiator_fsm = M_READ_SUCCESS;
+                }
+                else                                              // last burst not last block
+                {
+                    r_index          = 0;
+                    r_burst_count    = 0;
+                    r_block_count    = r_block_count.read() + 1;
+                    r_initiator_fsm  = M_READ_BLOCK;
+                }
+            }
+            else                                                // not the last burst
+            {
+                r_burst_count = r_burst_count.read() + 1;
+                r_initiator_fsm = M_READ_BURST;
+            }
+        }
+        break;
+    }
+    ///////////////////
+    case M_READ_SUCCESS:
+    case M_READ_ERROR:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        break;
+    }
+    ///////////////////
+    case M_WRITE_BURST:  // Compute the number of flits in the burst
+    {
+        uint32_t offset = r_burst_offset.read();
+
+        if ( offset )                  // buffer not aligned
+        {
+            if ( r_burst_count.read() == 0 ) r_burst_nflits = m_flits_per_burst - offset;
+            else if ( r_burst_count.read() == m_bursts_per_block ) r_burst_nflits = offset;
+            else r_burst_nflits = m_flits_per_burst;
+        }
+        else                           // buffer aligned
+        {
+            r_burst_nflits = m_flits_per_burst;
+        }
+        r_initiator_fsm =  M_WRITE_CMD;
+        break;
+    }
+    /////////////////
+    case M_WRITE_CMD:	// This is actually a single flit VCI READ command
+    {
+	    if ( p_vci_initiator.cmdack.read() ) r_initiator_fsm = M_WRITE_RSP;
+        break;
+    }
+    /////////////////
+    case M_WRITE_RSP:	// This is actually a multi-flits VCI READ response
+    {
+        bool aligned = (r_burst_offset.read() == 0);
+
+        if ( p_vci_initiator.rspval.read() )
+        {
+            r_local_buffer[r_index.read()] = (uint32_t)p_vci_initiator.rdata.read();
+            r_index = r_index.read() + 1;
+
+            if ( p_vci_initiator.reop.read() )  // last flit of the burst
+            {
+	        r_flit_count  = 0;
+                r_buf_address = r_buf_address.read() + (r_burst_nflits.read()<<2); 
+
+	        if( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
+                {
+                    r_initiator_fsm = M_WRITE_ERROR;
+                }
+                else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or 
+                          (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) ) // last burst
+                {
+                    r_initiator_fsm  = M_WRITE_BLOCK;
+                }
+                else                                          // not the last burst
+                {
+                    r_burst_count = r_burst_count.read() + 1;
+                    r_initiator_fsm = M_WRITE_BURST;
+                }
+            }
+            else
+            {
+	            r_flit_count = r_flit_count.read() + 1;
+            }
+        }
+        break;
+    }
+    ///////////////////
+    case M_WRITE_BLOCK:		// write a block to disk after waiting m_latency cycles
+    {
+        if ( r_latency_count == 0 )
+        {
+            r_latency_count = m_latency;
+            ::lseek(m_fd, (r_lba + r_block_count)*m_flits_per_block*vci_param::B, SEEK_SET);
+            if( ::write(m_fd, r_local_buffer, m_flits_per_block*vci_param::B) < 0 )
+            {
+                r_initiator_fsm = M_WRITE_ERROR; 
+            }
+            else if ( r_block_count.read() == r_nblocks.read() - 1 ) 
+            {
+                r_initiator_fsm = M_WRITE_SUCCESS; 
+            }
+            else
+            {
+                r_burst_count    = 0;
+		r_index          = 0;
+                r_block_count    = r_block_count.read() + 1;
+                r_initiator_fsm = M_WRITE_BURST;
+            }
+        } 
+        else
+        {
+            r_latency_count = r_latency_count - 1;
+        }
+        break;
+    }
+    /////////////////////
+    case M_WRITE_SUCCESS:
+    case M_WRITE_ERROR:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        break;
+    }
+    } // end switch r_initiator_fsm
+}  // end transition
+
+//////////////////////
+tmpl(void)::genMoore()
+{
+    // p_vci_target port   
+    p_vci_target.rsrcid = (sc_dt::sc_uint<vci_param::S>)r_srcid.read();
+    p_vci_target.rtrdid = (sc_dt::sc_uint<vci_param::T>)r_trdid.read();
+    p_vci_target.rpktid = (sc_dt::sc_uint<vci_param::P>)r_pktid.read();
+    p_vci_target.reop   = true;
+
+    switch(r_target_fsm) {
+    case T_IDLE:
+        p_vci_target.cmdack = true;
+        p_vci_target.rspval = false;
+        break;
+    case T_READ_STATUS:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        if     (r_initiator_fsm == M_IDLE)          p_vci_target.rdata = BLOCK_DEVICE_IDLE;
+        else if(r_initiator_fsm == M_READ_SUCCESS)  p_vci_target.rdata = BLOCK_DEVICE_READ_SUCCESS;
+        else if(r_initiator_fsm == M_WRITE_SUCCESS) p_vci_target.rdata = BLOCK_DEVICE_WRITE_SUCCESS;
+        else if(r_initiator_fsm == M_READ_ERROR)   	p_vci_target.rdata = BLOCK_DEVICE_READ_ERROR;
+        else if(r_initiator_fsm == M_WRITE_ERROR)  	p_vci_target.rdata = BLOCK_DEVICE_WRITE_ERROR;
+        else                                    	p_vci_target.rdata = BLOCK_DEVICE_BUSY;
+        p_vci_target.rerror = VCI_READ_OK;
+        break;
+    case T_READ_BUFFER:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        p_vci_target.rdata  = (uint32_t)r_buf_address.read();
+        p_vci_target.rerror = VCI_READ_OK;
+        break;
+    case T_READ_COUNT:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        p_vci_target.rdata = (uint32_t)r_nblocks.read();
+        p_vci_target.rerror = VCI_READ_OK;
+        break;
+    case T_READ_LBA:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        p_vci_target.rdata = (uint32_t)r_lba.read();
+        p_vci_target.rerror = VCI_READ_OK;
+        break;
+    case T_READ_IRQEN:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        p_vci_target.rdata = (uint32_t)r_irq_enable.read();
+        p_vci_target.rerror = VCI_READ_OK;
+        break;
+    case T_READ_SIZE:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        p_vci_target.rdata = (uint32_t)m_device_size;
+        p_vci_target.rerror = VCI_READ_OK;
+        break;
+    case T_READ_BLOCK:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        p_vci_target.rdata = (uint32_t)m_flits_per_block*vci_param::B;
+        p_vci_target.rerror = VCI_READ_OK;
+        break;
+    case T_READ_ERROR:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        p_vci_target.rdata = 0;
+        p_vci_target.rerror = VCI_READ_ERROR;
+        break;
+    case T_WRITE_ERROR:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        p_vci_target.rdata = 0;
+        p_vci_target.rerror = VCI_WRITE_ERROR;
+        break;
+    default:
+        p_vci_target.cmdack = false;
+        p_vci_target.rspval = true;
+        p_vci_target.rdata = 0;
+        p_vci_target.rerror = VCI_WRITE_OK;
+        break;
+    } // end switch target fsm
+
+    // p_vci_initiator port
+    p_vci_initiator.srcid  = (sc_dt::sc_uint<vci_param::S>)m_srcid;
+    p_vci_initiator.trdid  = 0;
+    p_vci_initiator.contig = true;
+    p_vci_initiator.cons   = false;
+    p_vci_initiator.wrap   = false;
+    p_vci_initiator.cfixed = false;
+    p_vci_initiator.clen   = 0;
+
+    switch (r_initiator_fsm) {
+    case M_WRITE_CMD:		// It is actually a single flit VCI read command
+        p_vci_initiator.rspack  = false;
+        p_vci_initiator.cmdval  = true;
+        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
+        p_vci_initiator.cmd     = vci_param::CMD_READ;
+        p_vci_initiator.pktid   = TYPE_READ_DATA_UNC; // or _MISS ?
+        p_vci_initiator.wdata   = 0;
+        p_vci_initiator.be      = (uint32_t)0xF;
+        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nflits.read()<<2);
+        p_vci_initiator.eop     = true;
+        break;
+    case M_READ_CMD:		// It is actually a multi-flits VCI WRITE command 
+        p_vci_initiator.rspack  = false;
+        p_vci_initiator.cmdval  = true;
+        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read(); 
+        p_vci_initiator.cmd     = vci_param::CMD_WRITE;
+        p_vci_initiator.pktid   = TYPE_WRITE;
+        p_vci_initiator.wdata   = (uint32_t)r_local_buffer[r_index.read()];
+        p_vci_initiator.be      = 0xF;
+        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nflits.read()<<2);
+        p_vci_initiator.eop     = ( r_flit_count.read() == (r_burst_nflits.read() - 1) );
+        break;
+    case M_READ_RSP:
+    case M_WRITE_RSP:
+        p_vci_initiator.rspack  = true;
+        p_vci_initiator.cmdval  = false;
+        break;
+    default:
+        p_vci_initiator.rspack  = false;
+        p_vci_initiator.cmdval  = false;
+        break;
+    }
+
+    // IRQ signal
+    if(((r_initiator_fsm == M_READ_SUCCESS)    ||
+			    (r_initiator_fsm == M_WRITE_SUCCESS)   ||
+			    (r_initiator_fsm == M_READ_ERROR)      ||
+			    (r_initiator_fsm == M_WRITE_ERROR) ) &&  r_irq_enable) p_irq = true;
+    else			                               p_irq = false;
+} // end GenMoore()
+
+//////////////////////////////////////////////////////////////////////////////
+tmpl(/**/)::VciBlockDeviceTsar( sc_core::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,
+                                  const uint32_t                       burst_size,
+                                  const uint32_t                       latency)
+
+: caba::BaseModule(name),
+	m_segment(mt.getSegment(tgtid)),
+	m_srcid(mt.indexForId(srcid)),
+	m_flits_per_block(block_size/vci_param::B),
+	m_flits_per_burst(burst_size/vci_param::B),
+	m_bursts_per_block(block_size/burst_size),
+	m_latency(latency),
+	p_clk("p_clk"),
+	p_resetn("p_resetn"),
+	p_vci_initiator("p_vci_initiator"),
+	p_vci_target("p_vci_target"),
+	p_irq("p_irq") 
+{
+	SC_METHOD(transition);
+	sensitive_pos << p_clk;
+
+	SC_METHOD(genMoore);
+	sensitive_neg << p_clk;
+
+	if( (block_size != 64 )  && 
+        (block_size != 128)  && 
+        (block_size != 256)  && 
+        (block_size != 512)  && 
+        (block_size != 1024) &&
+        (block_size != 2048) && 
+        (block_size != 4096) )
+	{
+		std::cout << "Error in component VciBlockDeviceTsar : " << name << std::endl;
+		std::cout << "The block size must be 128, 256, 512, 1024, 2048 or 4096 bytes" << std::endl;
+		exit(1);
+	}
+	if( (burst_size != 1 ) && 
+		(burst_size != 2 ) && 
+		(burst_size != 4 ) && 
+		(burst_size != 8 ) && 
+		(burst_size != 16) && 
+		(burst_size != 32) && 
+		(burst_size != 64) )
+	{
+		std::cout << "Error in component VciBlockDeviceTsar : " << name << std::endl;
+		std::cout << "The burst size must be 1, 2, 4, 8, 16, 32 or 64 bytes" << std::endl;
+		exit(1);
+	}
+	if ( m_segment.size() < 32 ) 
+	{
+		std::cout << "Error in component VciBlockDeviceTsar : " << name << std::endl;
+		std::cout << "The size of the segment cannot be smaller than 32 bytes" << std::endl;
+		exit(1);
+	}
+	if ( (m_segment.baseAddress() & 0x0000001F) != 0 ) 
+	{
+		std::cout << "Error in component VciBlockDeviceTsar : " << name << std::endl;
+		std::cout << "The base address of the segment must be multiple of 32 bytes" << std::endl;
+		exit(1);
+	}
+	if ( vci_param::B != 4 )
+	{
+		std::cout << "Error in component VciBlockDeviceTsar : " << name << std::endl;
+		std::cout << "The VCI data fields must have 32 bits" << std::endl;
+		exit(1);
+	}
+	m_fd = ::open(filename.c_str(), O_RDWR);
+	if ( m_fd < 0 ) 
+	{
+		std::cout << "Error in component VciBlockDeviceTsar : " << name << std::endl;
+		std::cout << "Unable to open file " << filename << std::endl;
+		exit(1);
+	}
+	m_device_size = lseek(m_fd, 0, SEEK_END) / block_size;
+	if ( m_device_size > ((uint64_t)1<<32) ) 
+	{
+		std::cout << "Warning: block device " << name << std::endl;
+		std::cout << "The file " << filename << std::endl;
+		std::cout << "has more blocks than addressable with the 32 bits PIBUS address" << std::endl;
+		m_device_size = ((uint64_t)1<<32);
+	}
+
+	r_local_buffer = new uint32_t[m_flits_per_block];
+
+} // end constructor
+
+//////////////////////////
+tmpl(void)::print_trace()
+{
+	const char* initiator_str[] = {
+		"IDLE",
+
+		"READ_BLOCK",
+		"READ_BURST",
+		"READ_CMD",
+		"READ_RSP",
+		"READ_TEST",
+		"READ_SUCCESS",
+		"READ_ERROR",
+
+		"WRITE_BURST",
+		"WRITE_CMD",
+		"WRITE_RSP",
+		"WRITE_BLOCK",
+		"WRITE_SUCCESS",
+		"WRITE_ERROR",
+	};
+	const char* target_str[] = {
+		"IDLE        ",
+		"WRITE_BUFFER",
+		"READ_BUFFER ",
+		"WRITE_COUNT ",
+		"READ_COUNT  ",
+		"WRITE_LBA   ",
+		"READ_LBA    ",
+		"WRITE_OP    ",
+		"READ_STATUS ",
+		"WRITE_IRQEN ",
+		"READ_IRQEN  ",
+		"READ_SIZE   ",
+		"READ_BLOCK  ",
+		"READ_ERROR  ",
+		"WRITE_ERROR ",
+	};
+
+	std::cout << "BDEV_TGT : " << target_str[r_target_fsm.read()] 
+		  << "  BDEV_INI : " << initiator_str[r_initiator_fsm.read()] 
+		  << "  block = " << r_block_count.read() 
+		  << "  burst = " << r_burst_count.read() 
+		  << "  flit  = " << r_flit_count.read() <<std::endl; 
+}
+
+
+}} // 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_block_device_tsar/include/soclib/block_device_tsar.h
===================================================================
--- /trunk/modules/vci_block_device_tsar/include/soclib/block_device_tsar.h	(revision 374)
+++ /trunk/modules/vci_block_device_tsar/include/soclib/block_device_tsar.h	(revision 374)
@@ -0,0 +1,66 @@
+/*
+ * 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
+ *         alain greiner
+ *
+ * Maintainers: alain
+ */
+#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,
+};
+
+#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
+
