Index: trunk/modules/vci_block_device_tsar_v4/caba/metadata/vci_block_device_tsar_v4.sd
===================================================================
--- trunk/modules/vci_block_device_tsar_v4/caba/metadata/vci_block_device_tsar_v4.sd	(revision 151)
+++ trunk/modules/vci_block_device_tsar_v4/caba/metadata/vci_block_device_tsar_v4.sd	(revision 151)
@@ -0,0 +1,35 @@
+
+# -*- python -*-
+
+Module('caba:vci_block_device_tsar_v4',
+	   classname = 'soclib::caba::VciBlockDeviceTsarV4',
+	   tmpl_parameters = [ parameter.Module('vci_param',  default = 'caba:vci_param'), ],
+	   header_files = ['../source/include/vci_block_device_tsar_v4.h', ],
+           interface_files = ['../../include/soclib/block_device_tsar_v4.h', ],
+	   implementation_files = ['../source/src/vci_block_device_tsar_v4.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_v4/caba/source/include/vci_block_device_tsar_v4.h
===================================================================
--- trunk/modules/vci_block_device_tsar_v4/caba/source/include/vci_block_device_tsar_v4.h	(revision 151)
+++ trunk/modules/vci_block_device_tsar_v4/caba/source/include/vci_block_device_tsar_v4.h	(revision 151)
@@ -0,0 +1,208 @@
+
+/* -*- 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, 
+// as well as the block size (bytes), and the burst size (bytes). 
+// This component has a DMA capability, and is both a target and an initiator.
+// 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_V4_H
+#define SOCLIB_VCI_BLOCK_DEVICE_TSAR_V4_H
+
+#include <stdint.h>
+#include <systemc>
+#include "caba_base_module.h"
+#include "mapping_table.h"
+
+namespace soclib {
+namespace caba {
+
+using namespace sc_core;
+
+template<typename vci_param>
+class VciBlockDeviceTsarV4
+	: 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 to be transfered
+    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_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_latency_count;	// latency access (for each block)
+    sc_signal<bool>           		r_go;           	// transmit command from T_FSM to M_FSM
+    sc_signal<sc_uint<vci_param::S> >	r_srcid;		// save srcid
+    sc_signal<sc_uint<vci_param::T> >	r_trdid;		// save trdid
+    sc_signal<sc_uint<vci_param::P> >	r_pktid;		// save pktid
+
+    uint32_t*   			m_local_buffer; 	// capacity is one block (block_size bytes)
+
+    // 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_CMD          = 2,
+    M_READ_RSP          = 3,
+    M_READ_TEST         = 4,
+    M_READ_SUCCESS      = 5,
+    M_READ_ERROR        = 6,
+    M_WRITE_BLOCK       = 7,
+    M_WRITE_CMD         = 8,
+    M_WRITE_RSP         = 9,
+    M_WRITE_TEST        = 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,
+    };
+
+protected:
+
+    SC_HAS_PROCESS(VciBlockDeviceTsarV4);
+
+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   
+    VciBlockDeviceTsarV4(
+		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_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_block_device_tsar_v4/caba/source/src/save
===================================================================
--- trunk/modules/vci_block_device_tsar_v4/caba/source/src/save	(revision 151)
+++ trunk/modules/vci_block_device_tsar_v4/caba/source/src/save	(revision 151)
@@ -0,0 +1,626 @@
+/* -*- 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 "vci_block_device_tsar_v4.h"
+#include <stdint.h>
+#include <iostream>
+#include <fcntl.h>
+
+namespace soclib { namespace caba {
+
+#define tmpl(t) template<typename vci_param> t VciBlockDeviceTsarV4<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_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 controls the following registers :
+    // r_initiator_fsm, r_flit_count, r_block_count, m_local_buffer 
+    /////////////////////////////////////////////////////////////////////////
+    switch(r_initiator_fsm) {
+    case M_IDLE : 	// waiting for activation
+    {
+	if ( r_go ) 
+        {
+            r_block_count   = 0;
+            r_burst_count   = 0;
+            r_flit_count    = 0;
+            r_latency_count = m_latency;
+
+            if ( r_read ) 	r_initiator_fsm = M_READ_BLOCK;
+            else 		r_initiator_fsm = M_WRITE_CMD;
+        }
+        break;
+    }
+    case M_READ_BLOCK:  // read one block from block 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( ::read(m_fd, m_local_buffer, m_flits_per_block*vci_param::B) < 0 )  
+            {
+                 r_initiator_fsm = M_READ_ERROR;
+            }
+            else   
+            {
+                 r_initiator_fsm = M_READ_CMD;
+            }
+        }
+        else
+        {
+            r_latency_count = r_latency_count - 1;
+        }
+        break;
+    }
+    case M_READ_CMD:	// This is actually a multi-flits VCI WRITE command
+    {
+        if ( p_vci_initiator.cmdack.read() )
+        {
+            if ( r_flit_count == (m_flits_per_burst - 1) )
+            {
+                r_initiator_fsm = M_READ_RSP;
+                r_flit_count = 0;
+            }
+            else
+            {
+                r_flit_count = r_flit_count + 1;
+            }
+        }
+        break;
+    }
+    case M_READ_RSP: 	// This is actually a single flit VCI WRITE response
+    {
+        if ( p_vci_initiator.rspval.read() )
+        {
+            if ( (p_vci_initiator.rerror.read()&0x1) == 0 ) r_initiator_fsm = M_READ_TEST;
+            else                                            r_initiator_fsm = M_READ_ERROR;
+        }
+        break;
+    }
+    case M_READ_TEST:
+    {
+        if ( r_burst_count.read() == (m_bursts_per_block - 1) )
+        {
+            if ( r_block_count.read() == (r_nblocks.read() - 1) ) // last burst of the last block 
+            {
+                r_burst_count = 0;
+                r_block_count = 0;
+                r_initiator_fsm = M_READ_SUCCESS;
+            }
+            else	// last burst but not last block
+            {
+                r_burst_count = 0;
+                r_block_count = r_block_count.read() + 1;
+                r_initiator_fsm  = M_READ_BLOCK;
+            }
+        }
+        else  // not the last burst of the block
+        {
+            r_burst_count = r_burst_count.read() + 1;
+            r_initiator_fsm = M_READ_CMD;
+        }
+        break;
+    }
+    case M_READ_SUCCESS:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        break;
+    }
+    case M_READ_ERROR:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        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
+    {
+        if ( p_vci_initiator.rspval.read() )
+        {
+            uint32_t index = (r_burst_count.read()*m_flits_per_burst) + r_flit_count.read();
+            m_local_buffer[index] = p_vci_initiator.rdata.read();
+            if ( p_vci_initiator.reop.read() )
+            {
+	        r_flit_count = 0;
+		if( (p_vci_initiator.rerror.read()&0x1) == 0 ) r_initiator_fsm = M_WRITE_BLOCK;
+                else                                           r_initiator_fsm = M_WRITE_ERROR;
+            }
+            else
+            {
+	        r_flit_count = r_flit_count.read() + 1;
+            }
+        }
+        break;
+    }
+    case M_WRITE_TEST:
+    {
+        if ( r_burst_count.read() == (m_bursts_per_block - 1) ) // last burst of the block
+        {
+            r_burst_count = 0;
+            r_block_count = r_block_count.read() + 1;
+            r_initiator_fsm = M_WRITE_BLOCK;
+        }							// not the last burst
+        else
+        {
+            r_burst_count = r_burst_count.read() + 1;
+            r_initiator_fsm = M_WRITE_CMD;
+        }
+        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, m_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() ) 
+            {
+                r_initiator_fsm = M_WRITE_SUCCESS; 
+            }
+            else
+            {
+                r_initiator_fsm = M_WRITE_CMD;
+            }
+        } 
+        else
+        {
+            r_latency_count = r_latency_count - 1;
+        }
+        break;
+    }
+    case M_WRITE_SUCCESS:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        break;
+    }
+    case M_WRITE_ERROR:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        break;
+    }
+    } // end switch r_initiator_fsm
+
+}  // end transition
+
+//////////////////////
+tmpl(void)::genMoore()
+{
+    sc_uint<vci_param::N> 	offset;
+    uint32_t			index;
+
+    // p_vci_target port   
+    p_vci_target.rsrcid = (sc_uint<vci_param::S>)r_srcid.read();
+    p_vci_target.rtrdid = (sc_uint<vci_param::T>)r_trdid.read();
+    p_vci_target.rpktid = (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  = (sc_uint<8*vci_param::B>)r_buf_address;
+        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 = (sc_uint<8*vci_param::B>)r_nblocks;
+        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 = (sc_uint<8*vci_param::B>)r_lba;
+        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 = (sc_uint<8*vci_param::B>)r_irq_enable;
+        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 = (sc_uint<8*vci_param::B>)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 = (sc_uint<8*vci_param::B>)m_flits_per_block;
+        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_uint<vci_param::S>)m_srcid;
+    p_vci_initiator.trdid  = 0;
+    p_vci_initiator.pktid  = 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
+        offset = (r_block_count.read()*m_flits_per_block +
+                  r_burst_count.read()*m_flits_per_burst) * vci_param::B;
+        p_vci_initiator.rspack  = false;
+        p_vci_initiator.cmdval  = true;
+        p_vci_initiator.address = (sc_uint<vci_param::N>)r_buf_address.read() + offset;
+        p_vci_initiator.cmd     = vci_param::CMD_READ;
+        p_vci_initiator.wdata   = 0;
+        p_vci_initiator.be      = (sc_uint<vci_param::B>)0xF;
+        p_vci_initiator.plen    = (sc_uint<vci_param::K>)m_flits_per_burst*vci_param::B;
+        p_vci_initiator.eop     = true;
+        break;
+    case M_READ_CMD:		// It is actually a multi-flits VCI WRITE command 
+        offset = ( r_block_count.read()*m_flits_per_block +
+                   r_burst_count.read()*m_flits_per_burst +
+                   r_flit_count.read() ) * vci_param::B;
+        index  = (r_burst_count.read()*m_flits_per_burst) + r_flit_count.read();
+
+std::cout << "   *** index  = " << index << std::endl;
+std::cout << "   *** offset = " << std::hex << offset << std::endl;
+std::cout << "   *** val    = " << std::hex << m_local_buffer[index] << std::endl;
+
+        p_vci_initiator.rspack  = false;
+        p_vci_initiator.cmdval  = true;
+        p_vci_initiator.address = (sc_uint<vci_param::N>)r_buf_address.read() + offset; 
+        p_vci_initiator.cmd     = vci_param::CMD_WRITE;
+        p_vci_initiator.wdata   = (sc_uint<8*vci_param::B>)m_local_buffer[index];
+        p_vci_initiator.be      = (sc_uint<vci_param::B>)0xF;
+        p_vci_initiator.plen    = (sc_uint<vci_param::K>)m_flits_per_burst*vci_param::B;
+        p_vci_initiator.eop     = ( r_flit_count.read() == (m_flits_per_burst - 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(/**/)::VciBlockDeviceTsarV4(   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) )
+	{
+		std::cout << "Error in component VciBlockDeviceTsarV4 : " << name << std::endl;
+		std::cout << "The block size must be 128, 256, 512 or 1024 bytes" << std::endl;
+		exit(1);
+	}
+	if ( m_segment.size() < 32 ) 
+	{
+		std::cout << "Error in component VciBlockDeviceTsarV4 : " << 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 VciBlockDeviceTsarV4 : " << name << std::endl;
+		std::cout << "The base address of the segment must be multiple of 32 bytes" << std::endl;
+		exit(1);
+	}
+	if ( block_size%burst_size != 0 )
+	{
+		std::cout << "Error in component VciBlockDeviceTsarV4 : " << name << std::endl;
+		std::cout << "The block_size parameter must be a multiple of the burst_size" << std::endl;
+		exit(1);
+	}
+	if ( burst_size%vci_param::B != 0 )
+	{
+		std::cout << "Error in component VciBlockDeviceTsarV4 : " << name << std::endl;
+		std::cout << "The burst_size parameter must be a multiple of vci_param::B" << std::endl;
+		exit(1);
+	}
+	m_fd = ::open(filename.c_str(), O_RDWR);
+	if ( m_fd < 0 ) 
+	{
+		std::cout << "Error in component VciBlockDeviceTsarV4 : " << 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);
+	}
+
+	m_local_buffer = new sc_uint<8*vci_param::B>[m_flits_per_block];
+
+	std::cout << std::endl << "Instanciation of VciBlockDeviceTsarV4 : " << name << std::endl;
+	std::cout << "    file_name  = " << filename << std::endl;
+	std::cout << "    burst_size = " << std::dec << m_flits_per_burst*vci_param::B << std::endl;
+	std::cout << "    block_size = " << std::dec << m_flits_per_block*vci_param::B << std::endl;
+	std::cout << "    latency    = " << std::dec << m_latency << std::endl;
+	std::cout << "    segment " << m_segment.name()
+		<< " | base = 0x" << std::hex << m_segment.baseAddress()
+		<< " | size = "   << std::dec << m_segment.size() << std::endl;
+
+} // end constructor
+
+//////////////////////////
+tmpl(void)::print_trace()
+{
+	const char* initiator_str[] = {
+		"IDLE         ",
+		"READ_BLOCK   ",
+		"READ_CMD     ",
+		"READ_RSP     ",
+		"READ_TEST    ",
+		"READ_SUCCESS ",
+		"READ_ERROR   ",
+		"WRITE_BLOCK  ",
+		"WRITE_CMD    ",
+		"WRITE_RSP    ",
+		"WRITE_TEST   ",
+		"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 << name() << "_tgt : " << target_str[r_target_fsm.read()] << "   "
+		<< name() << "_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_v4/caba/source/src/vci_block_device_tsar_v4.cpp
===================================================================
--- trunk/modules/vci_block_device_tsar_v4/caba/source/src/vci_block_device_tsar_v4.cpp	(revision 151)
+++ trunk/modules/vci_block_device_tsar_v4/caba/source/src/vci_block_device_tsar_v4.cpp	(revision 151)
@@ -0,0 +1,620 @@
+/* -*- 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 "vci_block_device_tsar_v4.h"
+#include <stdint.h>
+#include <iostream>
+#include <fcntl.h>
+
+namespace soclib { namespace caba {
+
+#define tmpl(t) template<typename vci_param> t VciBlockDeviceTsarV4<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_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 controls the following registers :
+    // r_initiator_fsm, r_flit_count, r_block_count, m_local_buffer 
+    /////////////////////////////////////////////////////////////////////////
+    switch(r_initiator_fsm) {
+    case M_IDLE : 	// waiting for activation
+    {
+	if ( r_go ) 
+        {
+            r_block_count   = 0;
+            r_burst_count   = 0;
+            r_flit_count    = 0;
+            r_latency_count = m_latency;
+
+            if ( r_read ) 	r_initiator_fsm = M_READ_BLOCK;
+            else 		r_initiator_fsm = M_WRITE_CMD;
+        }
+        break;
+    }
+    case M_READ_BLOCK:  // read one block from block 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*4, SEEK_SET);
+            if( ::read(m_fd, m_local_buffer, m_flits_per_block*4) < 0 )  
+            {
+                 r_initiator_fsm = M_READ_ERROR;
+            }
+            else   
+            {
+                 r_initiator_fsm = M_READ_CMD;
+            }
+        }
+        else
+        {
+            r_latency_count = r_latency_count - 1;
+        }
+        break;
+    }
+    case M_READ_CMD:	// This is actually a multi-flits VCI WRITE command
+    {
+        if ( p_vci_initiator.cmdack.read() )
+        {
+            if ( r_flit_count == (m_flits_per_burst - 1) )
+            {
+                r_initiator_fsm = M_READ_RSP;
+                r_flit_count = 0;
+            }
+            else
+            {
+                r_flit_count = r_flit_count + 1;
+            }
+        }
+        break;
+    }
+    case M_READ_RSP: 	// This is actually a single flit VCI WRITE response
+    {
+        if ( p_vci_initiator.rspval.read() )
+        {
+            if ( (p_vci_initiator.rerror.read()&0x1) == 0 ) r_initiator_fsm = M_READ_TEST;
+            else                                            r_initiator_fsm = M_READ_ERROR;
+        }
+        break;
+    }
+    case M_READ_TEST:
+    {
+        if ( r_burst_count.read() == (m_bursts_per_block - 1) )
+        {
+            if ( r_block_count.read() == (r_nblocks.read() - 1) ) // last burst of the last block 
+            {
+                r_burst_count = 0;
+                r_block_count = 0;
+                r_initiator_fsm = M_READ_SUCCESS;
+            }
+            else	// last burst but not last block
+            {
+                r_burst_count = 0;
+                r_block_count = r_block_count.read() + 1;
+                r_initiator_fsm  = M_READ_BLOCK;
+            }
+        }
+        else  // not the last burst of the block
+        {
+            r_burst_count = r_burst_count.read() + 1;
+            r_initiator_fsm = M_READ_CMD;
+        }
+        break;
+    }
+    case M_READ_SUCCESS:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        break;
+    }
+    case M_READ_ERROR:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        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
+    {
+        if ( p_vci_initiator.rspval.read() )
+        {
+            uint32_t index = (r_burst_count.read()*m_flits_per_burst) + r_flit_count.read();
+            m_local_buffer[index] = (uint32_t)p_vci_initiator.rdata.read();
+            if ( p_vci_initiator.reop.read() )
+            {
+	        r_flit_count = 0;
+		if( (p_vci_initiator.rerror.read()&0x1) == 0 ) r_initiator_fsm = M_WRITE_BLOCK;
+                else                                           r_initiator_fsm = M_WRITE_ERROR;
+            }
+            else
+            {
+	        r_flit_count = r_flit_count.read() + 1;
+            }
+        }
+        break;
+    }
+    case M_WRITE_TEST:
+    {
+        if ( r_burst_count.read() == (m_bursts_per_block - 1) ) // last burst of the block
+        {
+            r_burst_count = 0;
+            r_block_count = r_block_count.read() + 1;
+            r_initiator_fsm = M_WRITE_BLOCK;
+        }							// not the last burst
+        else
+        {
+            r_burst_count = r_burst_count.read() + 1;
+            r_initiator_fsm = M_WRITE_CMD;
+        }
+        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*4, SEEK_SET);
+            if( ::write(m_fd, m_local_buffer, m_flits_per_block*4) < 0 )
+            {
+                r_initiator_fsm = M_WRITE_ERROR; 
+            }
+            else if ( r_block_count.read() == r_nblocks.read() ) 
+            {
+                r_initiator_fsm = M_WRITE_SUCCESS; 
+            }
+            else
+            {
+                r_initiator_fsm = M_WRITE_CMD;
+            }
+        } 
+        else
+        {
+            r_latency_count = r_latency_count - 1;
+        }
+        break;
+    }
+    case M_WRITE_SUCCESS:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        break;
+    }
+    case M_WRITE_ERROR:
+    {
+        if( !r_go ) r_initiator_fsm = M_IDLE;
+        break;
+    }
+    } // end switch r_initiator_fsm
+
+}  // end transition
+
+//////////////////////
+tmpl(void)::genMoore()
+{
+    sc_uint<vci_param::N> 	offset;
+    uint32_t			index;
+
+    // p_vci_target port   
+    p_vci_target.rsrcid = (sc_uint<vci_param::S>)r_srcid.read();
+    p_vci_target.rtrdid = (sc_uint<vci_param::T>)r_trdid.read();
+    p_vci_target.rpktid = (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;
+        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;
+        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;
+        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;
+        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;
+        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_uint<vci_param::S>)m_srcid;
+    p_vci_initiator.trdid  = 0;
+    p_vci_initiator.pktid  = 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
+        offset = (r_block_count.read()*m_flits_per_block +
+                  r_burst_count.read()*m_flits_per_burst) * vci_param::B;
+        p_vci_initiator.rspack  = false;
+        p_vci_initiator.cmdval  = true;
+        p_vci_initiator.address = (sc_uint<vci_param::N>)r_buf_address.read() + offset;
+        p_vci_initiator.cmd     = vci_param::CMD_READ;
+        p_vci_initiator.wdata   = 0;
+        p_vci_initiator.be      = (uint32_t)0xF;
+        p_vci_initiator.plen    = (sc_uint<vci_param::K>)m_flits_per_burst*vci_param::B;
+        p_vci_initiator.eop     = true;
+        break;
+    case M_READ_CMD:		// It is actually a multi-flits VCI WRITE command 
+        offset = ( r_block_count.read()*m_flits_per_block +
+                   r_burst_count.read()*m_flits_per_burst +
+                   r_flit_count.read() ) * vci_param::B;
+        index  = (r_burst_count.read()*m_flits_per_burst) + r_flit_count.read();
+        p_vci_initiator.rspack  = false;
+        p_vci_initiator.cmdval  = true;
+        p_vci_initiator.address = (sc_uint<vci_param::N>)r_buf_address.read() + offset; 
+        p_vci_initiator.cmd     = vci_param::CMD_WRITE;
+        p_vci_initiator.wdata   = (uint32_t)m_local_buffer[index];
+        p_vci_initiator.be      = 0xF;
+        p_vci_initiator.plen    = (sc_uint<vci_param::K>)m_flits_per_burst*vci_param::B;
+        p_vci_initiator.eop     = ( r_flit_count.read() == (m_flits_per_burst - 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(/**/)::VciBlockDeviceTsarV4(   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) )
+	{
+		std::cout << "Error in component VciBlockDeviceTsarV4 : " << name << std::endl;
+		std::cout << "The block size must be 128, 256, 512 or 1024 bytes" << std::endl;
+		exit(1);
+	}
+	if ( m_segment.size() < 32 ) 
+	{
+		std::cout << "Error in component VciBlockDeviceTsarV4 : " << 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 VciBlockDeviceTsarV4 : " << name << std::endl;
+		std::cout << "The base address of the segment must be multiple of 32 bytes" << std::endl;
+		exit(1);
+	}
+	if ( block_size%burst_size != 0 )
+	{
+		std::cout << "Error in component VciBlockDeviceTsarV4 : " << name << std::endl;
+		std::cout << "The block_size parameter must be a multiple of the burst_size" << std::endl;
+		exit(1);
+	}
+	if ( vci_param::B != 4 )
+	{
+		std::cout << "Error in component VciBlockDeviceTsarV4 : " << 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 VciBlockDeviceTsarV4 : " << 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);
+	}
+
+	m_local_buffer = new uint32_t[m_flits_per_block];
+
+	std::cout << std::endl << "Instanciation of VciBlockDeviceTsarV4 : " << name << std::endl;
+	std::cout << "    file_name  = " << filename << std::endl;
+	std::cout << "    burst_size = " << std::dec << m_flits_per_burst*vci_param::B << std::endl;
+	std::cout << "    block_size = " << std::dec << m_flits_per_block*vci_param::B << std::endl;
+	std::cout << "    latency    = " << std::dec << m_latency << std::endl;
+	std::cout << "    segment " << m_segment.name()
+		<< " | base = 0x" << std::hex << m_segment.baseAddress()
+		<< " | size = "   << std::dec << m_segment.size() << std::endl;
+
+} // end constructor
+
+//////////////////////////
+tmpl(void)::print_trace()
+{
+	const char* initiator_str[] = {
+		"IDLE         ",
+		"READ_BLOCK   ",
+		"READ_CMD     ",
+		"READ_RSP     ",
+		"READ_TEST    ",
+		"READ_SUCCESS ",
+		"READ_ERROR   ",
+		"WRITE_BLOCK  ",
+		"WRITE_CMD    ",
+		"WRITE_RSP    ",
+		"WRITE_TEST   ",
+		"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_v4/include/soclib/block_device_tsar_v4.h
===================================================================
--- trunk/modules/vci_block_device_tsar_v4/include/soclib/block_device_tsar_v4.h	(revision 151)
+++ trunk/modules/vci_block_device_tsar_v4/include/soclib/block_device_tsar_v4.h	(revision 151)
@@ -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_V4_REGS_H
+#define BLOCK_DEVICE_TSAR_V4_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_V4_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
+
