/* -*- c++ -*-
 * File : vci_cc_vcache_wrapper_v4.h
 * Copyright (c) UPMC, Lip6, SoC
 * Authors : Alain GREINER, Yang GAO
 * Date : 27/11/2011
 *
 * SOCLIB_LGPL_HEADER_BEGIN
 * 
 * This file is part of SoCLib, GNU LGPLv2.1.
 * 
 * SoCLib is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; version 2.1 of the License.
 * 
 * SoCLib is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with SoCLib; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * SOCLIB_LGPL_HEADER_END
 */
 
#ifndef SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER_V4_H
#define SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER_V4_H

#include <inttypes.h>
#include <systemc>
#include "caba_base_module.h"
#include "multi_write_buffer.h"
#include "generic_fifo.h"
#include "generic_tlb.h"
#include "generic_cam.h"
#include "generic_cache.h"
#include "vci_initiator.h"
#include "vci_target.h"
#include "mapping_table.h"
#include "static_assert.h"
#include "iss2.h"

namespace soclib {
namespace caba {

using namespace sc_core;

////////////////////////////////////////////
template<typename vci_param, typename iss_t>
class VciCcVCacheWrapperV4
////////////////////////////////////////////
    : public soclib::caba::BaseModule
{
    typedef uint32_t vaddr_t;
    typedef uint32_t tag_t;
    typedef uint32_t type_t;
    typedef typename iss_t::DataOperationType data_op_t;

    typedef typename vci_param::addr_t  paddr_t;
    typedef typename vci_param::be_t    vci_be_t;
    typedef typename vci_param::srcid_t vci_srcid_t;
    typedef typename vci_param::trdid_t vci_trdid_t;
    typedef typename vci_param::pktid_t vci_pktid_t;
    typedef typename vci_param::plen_t  vci_plen_t;

    enum icache_fsm_state_e {  
        ICACHE_IDLE,             
        // handling XTN processor requests
        ICACHE_XTN_TLB_FLUSH,
        ICACHE_XTN_CACHE_FLUSH, 
        ICACHE_XTN_TLB_INVAL,  
        ICACHE_XTN_CACHE_INVAL_VA,
        ICACHE_XTN_CACHE_INVAL_PA,  
        ICACHE_XTN_CACHE_INVAL_GO,
        // handling tlb miss
        ICACHE_TLB_WAIT,
        // handling cache miss
        ICACHE_MISS_VICTIM,   
        ICACHE_MISS_INVAL,   
        ICACHE_MISS_WAIT,   
        ICACHE_MISS_UPDT, 
        // handling unc read
        ICACHE_UNC_WAIT,  
        // handling coherence requests
        ICACHE_CC_CHECK, 
        ICACHE_CC_INVAL, 
        ICACHE_CC_UPDT, 
    };

    enum dcache_fsm_state_e {  
        DCACHE_IDLE,                
        // handling itlb & dtlb miss
        DCACHE_TLB_MISS,
        DCACHE_TLB_PTE1_GET,           
        DCACHE_TLB_PTE1_SELECT,      
        DCACHE_TLB_PTE1_UPDT,       
        DCACHE_TLB_PTE2_GET,    
        DCACHE_TLB_PTE2_SELECT,       
        DCACHE_TLB_PTE2_UPDT,           
        DCACHE_TLB_SC_UPDT,           
        DCACHE_TLB_SC_WAIT,           
        DCACHE_TLB_RETURN,         
	    // handling processor XTN requests
        DCACHE_XTN_SWITCH,
        DCACHE_XTN_SYNC,
        DCACHE_XTN_IC_INVAL_VA,        
        DCACHE_XTN_IC_FLUSH,        
        DCACHE_XTN_IC_INVAL_PA,     
        DCACHE_XTN_IT_INVAL,          
        DCACHE_XTN_DC_FLUSH,        
        DCACHE_XTN_DC_INVAL_VA,        
        DCACHE_XTN_DC_INVAL_PA,     
        DCACHE_XTN_DC_INVAL_WAIT,
        DCACHE_XTN_DC_INVAL_GO,          
        DCACHE_XTN_DT_INVAL,          
        //handling fourth stage write
        DCACHE_WRITE_TLB_DIRTY,
        DCACHE_WRITE_CACHE_DIRTY,
        DCACHE_WRITE_SC_WAIT,           
        DCACHE_WRITE_UNC_WAIT,
	// handling processor miss requests
        DCACHE_MISS_VICTIM,
        DCACHE_MISS_INVAL,
        DCACHE_MISS_INVAL_WAIT,
        DCACHE_MISS_WAIT,           
        DCACHE_MISS_UPDT,           
        // handling processor unc and sc requests
        DCACHE_UNC_WAIT,            
        // handling coherence requests
        DCACHE_CC_CHECK,            
        DCACHE_CC_INVAL,            
        DCACHE_CC_UPDT,             
        DCACHE_CC_WAIT,             
    };

    enum cmd_fsm_state_e {      
        CMD_IDLE,
        CMD_INS_MISS,
        CMD_INS_UNC,
        CMD_DATA_MISS,
        CMD_DATA_UNC,
        CMD_DATA_WRITE,
        CMD_DATA_SC, 
    };

    enum rsp_fsm_state_e {       
        RSP_IDLE,
        RSP_INS_MISS,
        RSP_INS_UNC,
        RSP_DATA_MISS,
        RSP_DATA_UNC,
        RSP_DATA_WRITE,
        RSP_DATA_SC,
    };

    enum cleanup_cmd_fsm_state_e {
        CLEANUP_DATA_IDLE,
        CLEANUP_DATA_GO,
        CLEANUP_INS_IDLE,
        CLEANUP_INS_GO,
    };

    enum tgt_fsm_state_e {  
        TGT_IDLE,
        TGT_UPDT_WORD,
        TGT_UPDT_DATA,
        TGT_REQ_BROADCAST,
        TGT_REQ_ICACHE,
        TGT_REQ_DCACHE,
        TGT_RSP_BROADCAST,
        TGT_RSP_ICACHE, 
        TGT_RSP_DCACHE,
    };

    enum inval_itlb_fsm_state_e {
        INVAL_ITLB_IDLE,
        INVAL_ITLB_SCAN,
    };

    enum inval_dtlb_fsm_state_e {
        INVAL_DTLB_IDLE,
        INVAL_DTLB_SCAN,
    };

    // TLB Mode : ITLB / DTLB / ICACHE / DCACHE
    enum {          
        INS_TLB_MASK    = 0x8,
        DATA_TLB_MASK   = 0x4,
        INS_CACHE_MASK  = 0x2,
        DATA_CACHE_MASK = 0x1,
    };

    // Error Type
    enum mmu_error_type_e 
    {
        MMU_NONE                      = 0x0000, // None
        MMU_WRITE_PT1_UNMAPPED 	      = 0x0001, // Write access of Page fault on Page Table 1          
        MMU_WRITE_PT2_UNMAPPED 	      = 0x0002, // Write access of Page fault on Page Table 2          
        MMU_WRITE_PRIVILEGE_VIOLATION = 0x0004, // Write access of Protected access in user mode      
        MMU_WRITE_ACCES_VIOLATION     = 0x0008, // Write access of write access to a non writable page
        MMU_WRITE_UNDEFINED_XTN       = 0x0020, // Write access of undefined external access address  
        MMU_WRITE_PT1_ILLEGAL_ACCESS  = 0x0040, // Write access of Bus Error accessing Table 1       
        MMU_WRITE_PT2_ILLEGAL_ACCESS  = 0x0080, // Write access of Bus Error accessing Table 2      
        MMU_WRITE_DATA_ILLEGAL_ACCESS = 0x0100, // Write access of Bus Error in cache access     
        MMU_READ_PT1_UNMAPPED 	      = 0x1001, // Read access of Page fault on Page Table 1  	
        MMU_READ_PT2_UNMAPPED 	      = 0x1002, // Read access of Page fault on Page Table 2  
        MMU_READ_PRIVILEGE_VIOLATION  = 0x1004, // Read access of Protected access in user mode 
        MMU_READ_EXEC_VIOLATION       = 0x1010, // Exec access to a non exec page              
        MMU_READ_UNDEFINED_XTN 	      = 0x1020, // Read access of Undefined external access address 
        MMU_READ_PT1_ILLEGAL_ACCESS   = 0x1040, // Read access of Bus Error in Table1 access      
        MMU_READ_PT2_ILLEGAL_ACCESS   = 0x1080, // Read access of Bus Error in Table2 access 	
        MMU_READ_DATA_ILLEGAL_ACCESS  = 0x1100, // Read access of Bus Error in cache access 
    };

    // miss types for data cache
    enum dcache_miss_type_e
    {
        PTE1_MISS, 
        PTE2_MISS,
        PROC_MISS,  
    };

    enum transaction_type_d_e
    {
        // b0 : 1 if cached
        // b1 : 1 if instruction
        TYPE_DATA_UNC     = 0x0,
        TYPE_DATA_MISS    = 0x1,
        TYPE_INS_UNC      = 0x2,
        TYPE_INS_MISS     = 0x3,
    };

public:
    sc_in<bool>                             p_clk;
    sc_in<bool>                             p_resetn;
    sc_in<bool>                             p_irq[iss_t::n_irq];
    soclib::caba::VciInitiator<vci_param>   p_vci_ini_d;
    soclib::caba::VciInitiator<vci_param>   p_vci_ini_c;
    soclib::caba::VciTarget<vci_param>      p_vci_tgt_c;

private:

    // STRUCTURAL PARAMETERS
    soclib::common::AddressDecodingTable<uint32_t, bool>    	m_cacheability_table;
    const soclib::common::Segment                           	m_segment;
    const vci_srcid_t                                       	m_srcid_d;
    const vci_srcid_t                                       	m_srcid_c;

    const size_t  						m_itlb_ways;
    const size_t  						m_itlb_sets;

    const size_t  						m_dtlb_ways;
    const size_t  						m_dtlb_sets;

    const size_t  						m_icache_ways;
    const size_t  						m_icache_sets;
    const paddr_t 						m_icache_yzmask;
    const size_t  						m_icache_words;

    const size_t  						m_dcache_ways;
    const size_t  						m_dcache_sets;
    const paddr_t 						m_dcache_yzmask;
    const size_t  						m_dcache_words;

    const uint32_t						m_max_frozen_cycles;

    const size_t  						m_paddr_nbits;  

    ////////////////////////////////////////
    // Variables used by print_trace()
    ////////////////////////////////////////

    bool							            m_ireq_valid;
    uint32_t						            m_ireq_addr;
    soclib::common::Iss2::ExecMode	            m_ireq_mode;

    bool					            		m_irsp_valid;
    uint32_t				            		m_irsp_instruction;
    bool						            	m_irsp_error;

    bool							            m_dreq_valid;
    uint32_t						            m_dreq_addr;
    soclib::common::Iss2::ExecMode	            m_dreq_mode;
    soclib::common::Iss2::DataOperationType		m_dreq_type;
    uint32_t							        m_dreq_wdata;
    uint8_t				    		        	m_dreq_be;

    bool					            		m_drsp_valid;
    uint32_t							        m_drsp_rdata;
    bool				            			m_drsp_error;

    /////////////////////////////////////////////
    // debug variables (for each FSM)
    /////////////////////////////////////////////
    uint32_t                                    m_debug_start_cycle;
    bool                                        m_debug_ok;
    bool                                        m_debug_previous_hit;
    bool                                        m_debug_dcache_fsm;
    bool                                        m_debug_icache_fsm;
    bool                                        m_debug_cleanup_fsm;
    bool                                        m_debug_inval_itlb_fsm;
    bool                                        m_debug_inval_dtlb_fsm;

    ///////////////////////////////
    // Software visible REGISTERS
    ///////////////////////////////
    sc_signal<uint32_t>     r_mmu_ptpr;             	// page table pointer register
    sc_signal<uint32_t>     r_mmu_mode;             	// mmu mode register
    sc_signal<uint32_t>     r_mmu_word_lo;          	// mmu misc data low
    sc_signal<uint32_t>     r_mmu_word_hi;          	// mmu misc data hight
    sc_signal<uint32_t>     r_mmu_ibvar;      	    	// mmu bad instruction address
    sc_signal<uint32_t>     r_mmu_dbvar;              	// mmu bad data address
    sc_signal<uint32_t>     r_mmu_ietr;                 // mmu instruction error type
    sc_signal<uint32_t>     r_mmu_detr;                 // mmu data error type
    sc_signal<uint32_t>	    r_mmu_params;		        // read-only
    sc_signal<uint32_t>	    r_mmu_release;		        // read_only


    //////////////////////////////
    // ICACHE FSM REGISTERS
    //////////////////////////////
    sc_signal<int>          r_icache_fsm;               // state register
    sc_signal<int>          r_icache_fsm_save;          // return state for coherence operation
    sc_signal<paddr_t>      r_icache_vci_paddr;      	// physical address 
    sc_signal<uint32_t>     r_icache_vaddr_save;        // virtual address requested by the processor

    // icache miss handling
    sc_signal<size_t>       r_icache_miss_way;		    // selected way for cache update
    sc_signal<size_t>       r_icache_miss_set;		    // selected set for cache update         
    sc_signal<size_t>       r_icache_miss_word;		    // word index for sequencial cache update
    sc_signal<bool>         r_icache_miss_inval;        // coherence request matching a pending miss

    // coherence request handling
    sc_signal<size_t>       r_icache_cc_way;		    // selected way for cc update/inval
    sc_signal<size_t>       r_icache_cc_set;		    // selected set for cc update/inval
    sc_signal<size_t>       r_icache_cc_word;		    // word counter for cc update

    // icache flush handling
    sc_signal<size_t>       r_icache_flush_count;	    // slot counter used for cache flush

    // communication between ICACHE FSM and VCI_CMD FSM
    sc_signal<bool>         r_icache_miss_req;           // cached read miss
    sc_signal<bool>         r_icache_unc_req;            // uncached read miss

    // communication between ICACHE FSM and DCACHE FSM
    sc_signal<bool>	        r_icache_tlb_miss_req;       // itlb miss request (set icache/reset dcache)
    sc_signal<bool>         r_icache_tlb_rsp_error;      // itlb miss response error (written by dcache)

    // communication between ICACHE FSM and CLEANUP FSMs
    sc_signal<bool>         r_icache_cleanup_req;        // ins cleanup request
    sc_signal<paddr_t>      r_icache_cleanup_line;       // ins cleanup NLINE

    ///////////////////////////////
    // DCACHE FSM REGISTERS
    ///////////////////////////////
    sc_signal<int>          r_dcache_fsm;               // state register
    sc_signal<int>          r_dcache_fsm_save;          // return state for coherence operation
    // registers written in P0 stage (used in P1 stage)
    sc_signal<bool>         r_dcache_p0_valid;		    // P1 pipeline stage must be executed
    sc_signal<uint32_t>     r_dcache_p0_vaddr;          // virtual address (from proc)
    sc_signal<uint32_t>     r_dcache_p0_wdata;          // write data (from proc)
    sc_signal<vci_be_t>     r_dcache_p0_be;             // byte enable (from proc)
    sc_signal<paddr_t>      r_dcache_p0_paddr;          // physical address 
    sc_signal<bool>         r_dcache_p0_cacheable;	    // address cacheable 
    sc_signal<size_t>       r_dcache_p0_tlb_way;	    // selected way (from dtlb) 
    sc_signal<size_t>       r_dcache_p0_tlb_set;	    // selected set (from dtlb)
    sc_signal<paddr_t>      r_dcache_p0_tlb_nline;	    // nline value (from dtlb) 
    sc_signal<bool>         r_dcache_p0_tlb_dirty;    	// dirty bit (from dtlb)
    sc_signal<bool>         r_dcache_p0_tlb_big;      	// big page bit (from dtlb)
    // registers written in P1 stage (used in P2 stage)
    sc_signal<bool>         r_dcache_p1_valid;		    // P2 pipeline stage must be executed
    sc_signal<bool>         r_dcache_p1_updt_cache;     // dcache must be updated 
    sc_signal<bool>         r_dcache_p1_set_dirty;      // PTE dirty bit must be set
    sc_signal<uint32_t>     r_dcache_p1_vaddr;          // virtual address (from proc)
    sc_signal<uint32_t>     r_dcache_p1_wdata;          // write data (from proc)
    sc_signal<vci_be_t>     r_dcache_p1_be;             // byte enable (from proc)
    sc_signal<paddr_t>      r_dcache_p1_paddr;          // physical address 
    sc_signal<size_t>       r_dcache_p1_cache_way;	    // selected way (from dcache) 
    sc_signal<size_t>       r_dcache_p1_cache_set;	    // selected set (from dcache)    
    sc_signal<size_t>       r_dcache_p1_cache_word;	    // selected word (from dcache)    
    sc_signal<size_t>       r_dcache_p1_tlb_way;	    // selected way (from dtlb) 
    sc_signal<size_t>       r_dcache_p1_tlb_set;	    // selected set (from dtlb)
    sc_signal<paddr_t>      r_dcache_p1_tlb_nline;	    // nline value (from dtlb) 
    // registers written in P2 stage (used in P3 stage)
    sc_signal<uint32_t>     r_dcache_p2_vaddr;          // virtual address (from proc)
    sc_signal<size_t>       r_dcache_p2_tlb_way;	    // selected way in dtlb 
    sc_signal<size_t>       r_dcache_p2_tlb_set;	    // selected set in dtlb
    sc_signal<bool>         r_dcache_p2_set_dirty;	    // PTE dirty bit must be set
    sc_signal<paddr_t>      r_dcache_p2_pte_paddr;      // PTE physical address 
    sc_signal<size_t>       r_dcache_p2_pte_way;	    // selected way in dcache
    sc_signal<size_t>       r_dcache_p2_pte_set;	    // selected set in dcache
    sc_signal<size_t>       r_dcache_p2_pte_word;	    // selected word in dcache
    sc_signal<size_t>       r_dcache_p2_pte_flags;	    // pte value read in dcache
    
    // communication between DCACHE FSM and VCI_CMD FSM
    sc_signal<paddr_t>      r_dcache_vci_paddr;		    // physical address for VCI command
    sc_signal<bool>         r_dcache_vci_miss_req;      // read miss request
    sc_signal<bool>         r_dcache_vci_unc_req;       // uncacheable read request
    sc_signal<bool>         r_dcache_vci_unc_be;        // uncacheable read byte enable
    sc_signal<bool>         r_dcache_vci_sc_req;        // atomic write request (Compare & swap)
    sc_signal<uint32_t>     r_dcache_vci_sc_old;        // previous data value for an atomic write
    sc_signal<uint32_t>     r_dcache_vci_sc_new;        // new data value for an atomic write

    // register used for XTN inval
    sc_signal<size_t>       r_dcache_xtn_way;		    // selected way (from dcache) 
    sc_signal<size_t>       r_dcache_xtn_set;		    // selected set (from dcache)    

    // write buffer state extension
    sc_signal<bool>         r_dcache_pending_unc_write; // pending uncacheable write in WBUF

    // handling dcache miss
    sc_signal<int>	    r_dcache_miss_type;		        // type of miss depending on the requester
    sc_signal<size_t>       r_dcache_miss_word;		    // word index for sequencial cache update
    sc_signal<size_t>       r_dcache_miss_way;		    // selected way for cache update
    sc_signal<size_t>       r_dcache_miss_set;		    // selected set for cache update
    sc_signal<bool>         r_dcache_miss_inval;        // coherence request matching a pending miss

    // handling coherence requests
    sc_signal<size_t>       r_dcache_cc_way;		    // selected way for cc update/inval
    sc_signal<size_t>       r_dcache_cc_set;		    // selected set for cc update/inval
    sc_signal<size_t>       r_dcache_cc_word;		    // word counter for cc update

    // dcache flush handling
    sc_signal<size_t>       r_dcache_flush_count;	    // slot counter used for cache flush

    // used by the TLB miss sub-fsm
    sc_signal<uint32_t>     r_dcache_tlb_vaddr;		    // virtual address for a tlb miss
    sc_signal<bool>         r_dcache_tlb_ins;		    // target tlb (itlb if true)
    sc_signal<paddr_t>      r_dcache_tlb_paddr;		    // physical address of pte
    sc_signal<uint32_t>     r_dcache_tlb_pte_flags;	    // pte1 or first word of pte2
    sc_signal<uint32_t>     r_dcache_tlb_pte_ppn;	    // second word of pte2
    sc_signal<size_t>       r_dcache_tlb_cache_way;	    // selected way in dcache 
    sc_signal<size_t>       r_dcache_tlb_cache_set;	    // selected set in dcache 
    sc_signal<size_t>       r_dcache_tlb_cache_word;	// selected word in dcache
    sc_signal<size_t>       r_dcache_tlb_way;		    // selected way in tlb    
    sc_signal<size_t>       r_dcache_tlb_set;		    // selected set in tlb    

    // LL reservation handling
    sc_signal<bool>         r_dcache_ll_valid;		    // valid LL reservation
    sc_signal<uint32_t>     r_dcache_ll_data;		    // LL reserved data
    sc_signal<paddr_t>      r_dcache_ll_vaddr;		    // LL reserved address 
                            
    // communication between DCACHE FSM and INVAL_ITLB/INVAL_DTLB FSMs
    sc_signal<bool>         r_dcache_itlb_inval_req;	// inval request of one or several TLB entries
    sc_signal<bool>         r_dcache_dtlb_inval_req;	// inval request of one or several TLB entries;
    sc_signal<paddr_t>      r_dcache_tlb_inval_line;	// line index 

    // communication between DCACHE FSM and ICACHE FSM
    sc_signal<bool>         r_dcache_xtn_req;           // xtn request (caused by processor)
    sc_signal<int>          r_dcache_xtn_opcode;        // xtn request type

    // communication between DCACHE FSM and CLEANUP FSMs
    sc_signal<bool>         r_dcache_cleanup_req;       // data cleanup request
    sc_signal<paddr_t>      r_dcache_cleanup_line;      // data cleanup NLINE

    // dcache directory extension
    bool                    *r_dcache_in_itlb;          // copy of dcache line in itlb
    bool                    *r_dcache_in_dtlb;          // copy of dcache line in dtlb

    ///////////////////////////////////
    // VCI_CMD FSM REGISTERS
    ///////////////////////////////////
    sc_signal<int>          r_vci_cmd_fsm;
    sc_signal<size_t>       r_vci_cmd_min;      	    // used for write bursts 
    sc_signal<size_t>       r_vci_cmd_max;      	    // used for write bursts 
    sc_signal<size_t>       r_vci_cmd_cpt;    		    // used for write bursts 
    sc_signal<bool>         r_vci_cmd_imiss_prio;	    // round-robin between imiss & dmiss

    ///////////////////////////////////
    // VCI_RSP FSM REGISTERS
    ///////////////////////////////////
    sc_signal<int>          r_vci_rsp_fsm;
    sc_signal<size_t>       r_vci_rsp_cpt;
    sc_signal<bool>         r_vci_rsp_ins_error;
    sc_signal<bool>         r_vci_rsp_data_error;
    GenericFifo<uint32_t>   r_vci_rsp_fifo_icache;	    // response FIFO to ICACHE FSM
    GenericFifo<uint32_t>   r_vci_rsp_fifo_dcache;	    // response FIFO to DCACHE FSM

    ///////////////////////////////////
    //  CLEANUP FSM REGISTER
    ///////////////////////////////////
    sc_signal<int>          r_cleanup_fsm;              // state register
    sc_signal<size_t>       r_cleanup_trdid;            // to clear the registration buffer
    GenericCam<paddr_t>     r_cleanup_buffer;           // Registration buffer for cleanups

    ///////////////////////////////////
    //  TGT FSM REGISTERS
    ///////////////////////////////////
    sc_signal<int>          r_tgt_fsm;			        // state register
    sc_signal<paddr_t>      r_tgt_paddr;		        // cache line physical address
    sc_signal<size_t>       r_tgt_word_count;		    // word index
    sc_signal<size_t>       r_tgt_word_min;		        // index of the first word to be updated
    sc_signal<size_t>       r_tgt_word_max;		        // index of the last word to be updated
    sc_signal<bool>         r_tgt_update;		        // update request
    sc_signal<bool>         r_tgt_update_data;		    // update data request
    sc_signal<vci_srcid_t>  r_tgt_srcid;
    sc_signal<vci_pktid_t>  r_tgt_pktid;
    sc_signal<vci_trdid_t>  r_tgt_trdid;

    // communications between TGT FSM and DCACHE/ICACHE FSMs
    sc_signal<bool>         r_tgt_icache_req;		    // coherence request (set by tgt)
    sc_signal<bool>         r_tgt_dcache_req;		    // coherence request (set by tgt)
    sc_signal<bool>         r_tgt_icache_rsp;		    // coherence response (set by icache)
    sc_signal<bool>         r_tgt_dcache_rsp;		    // coherence response (set by dcache)

    uint32_t                *r_tgt_buf;			        // cache line word buffer 
    vci_be_t                *r_tgt_be;			        // cache line be buffer 

    ///////////////////////////////////
    // INVAL_ITLB FSM REGISTERS
    ///////////////////////////////////
    sc_signal<int>          r_inval_itlb_fsm; 		    // state register
    sc_signal<size_t>       r_inval_itlb_count;		    // counter to scan all itlb entries

    ///////////////////////////////////
    // INVAL_DTLB FSM REGISTERS
    ///////////////////////////////////
    sc_signal<int>          r_inval_dtlb_fsm;		    //state register
    sc_signal<size_t>       r_inval_dtlb_count;		    // counter to scan all dtlb entries

    //////////////////////////////////////////////////////////////////
    // processor, write buffer, caches , TLBs and CAM for cleanups 
    //////////////////////////////////////////////////////////////////
    iss_t                       r_iss;   
    MultiWriteBuffer<paddr_t>	r_wbuf;
    GenericCache<paddr_t>   	r_icache;
    GenericCache<paddr_t>    	r_dcache;
    GenericTlb<paddr_t>       	r_itlb;
    GenericTlb<paddr_t>     	r_dtlb;

    ////////////////////////////////
    // Activity counters
    ////////////////////////////////
    uint32_t m_cpt_dcache_data_read;        // DCACHE DATA READ
    uint32_t m_cpt_dcache_data_write;       // DCACHE DATA WRITE
    uint32_t m_cpt_dcache_dir_read;         // DCACHE DIR READ
    uint32_t m_cpt_dcache_dir_write;        // DCACHE DIR WRITE

    uint32_t m_cpt_icache_data_read;        // ICACHE DATA READ
    uint32_t m_cpt_icache_data_write;       // ICACHE DATA WRITE
    uint32_t m_cpt_icache_dir_read;         // ICACHE DIR READ
    uint32_t m_cpt_icache_dir_write;        // ICACHE DIR WRITE

    uint32_t m_cpt_frz_cycles;	            // number of cycles where the cpu is frozen
    uint32_t m_cpt_total_cycles;	        // total number of cycles

    // Cache activity counters
    uint32_t m_cpt_data_read;               // total number of read data
    uint32_t m_cpt_data_write;              // total number of write data
    uint32_t m_cpt_data_miss;               // number of read miss
    uint32_t m_cpt_ins_miss;                // number of instruction miss
    uint32_t m_cpt_unc_read;                // number of read uncached
    uint32_t m_cpt_write_cached;            // number of cached write
    uint32_t m_cpt_ins_read;                // number of instruction read
    uint32_t m_cpt_ins_spc_miss;            // number of speculative instruction miss

    uint32_t m_cost_write_frz;              // number of frozen cycles related to write buffer         
    uint32_t m_cost_data_miss_frz;          // number of frozen cycles related to data miss
    uint32_t m_cost_unc_read_frz;           // number of frozen cycles related to uncached read
    uint32_t m_cost_ins_miss_frz;           // number of frozen cycles related to ins miss

    uint32_t m_cpt_imiss_transaction;       // number of VCI instruction miss transactions
    uint32_t m_cpt_dmiss_transaction;       // number of VCI data miss transactions
    uint32_t m_cpt_unc_transaction;         // number of VCI uncached read transactions
    uint32_t m_cpt_write_transaction;       // number of VCI write transactions
    uint32_t m_cpt_icache_unc_transaction;

    uint32_t m_cost_imiss_transaction;      // cumulated duration for VCI IMISS transactions
    uint32_t m_cost_dmiss_transaction;      // cumulated duration for VCI DMISS transactions
    uint32_t m_cost_unc_transaction;        // cumulated duration for VCI UNC transactions
    uint32_t m_cost_write_transaction;      // cumulated duration for VCI WRITE transactions
    uint32_t m_cost_icache_unc_transaction; // cumulated duration for VCI IUNC transactions    
    uint32_t m_length_write_transaction;    // cumulated length for VCI WRITE transactions

    // TLB activity counters
    uint32_t m_cpt_ins_tlb_read;            // number of instruction tlb read
    uint32_t m_cpt_ins_tlb_miss;            // number of instruction tlb miss
    uint32_t m_cpt_ins_tlb_update_acc;      // number of instruction tlb update 
    uint32_t m_cpt_ins_tlb_occup_cache;     // number of instruction tlb occupy data cache line 
    uint32_t m_cpt_ins_tlb_hit_dcache;      // number of instruction tlb hit in data cache

    uint32_t m_cpt_data_tlb_read;           // number of data tlb read
    uint32_t m_cpt_data_tlb_miss;           // number of data tlb miss
    uint32_t m_cpt_data_tlb_update_acc;     // number of data tlb update 
    uint32_t m_cpt_data_tlb_update_dirty;   // number of data tlb update dirty
    uint32_t m_cpt_data_tlb_hit_dcache;     // number of data tlb hit in data cache
    uint32_t m_cpt_data_tlb_occup_cache;    // number of data tlb occupy data cache line
    uint32_t m_cpt_tlb_occup_dcache;
    
    uint32_t m_cost_ins_tlb_miss_frz;       // number of frozen cycles related to instruction tlb miss
    uint32_t m_cost_data_tlb_miss_frz;      // number of frozen cycles related to data tlb miss
    uint32_t m_cost_ins_tlb_update_acc_frz;    // number of frozen cycles related to instruction tlb update acc
    uint32_t m_cost_data_tlb_update_acc_frz;   // number of frozen cycles related to data tlb update acc
    uint32_t m_cost_data_tlb_update_dirty_frz; // number of frozen cycles related to data tlb update dirty
    uint32_t m_cost_ins_tlb_occup_cache_frz;   // number of frozen cycles related to instruction tlb miss operate in dcache
    uint32_t m_cost_data_tlb_occup_cache_frz;  // number of frozen cycles related to data tlb miss operate in dcache

    uint32_t m_cpt_itlbmiss_transaction;       // number of itlb miss transactions
    uint32_t m_cpt_itlb_ll_transaction;        // number of itlb ll acc transactions
    uint32_t m_cpt_itlb_sc_transaction;        // number of itlb sc acc transactions
    uint32_t m_cpt_dtlbmiss_transaction;       // number of dtlb miss transactions
    uint32_t m_cpt_dtlb_ll_transaction;        // number of dtlb ll acc transactions
    uint32_t m_cpt_dtlb_sc_transaction;        // number of dtlb sc acc transactions
    uint32_t m_cpt_dtlb_ll_dirty_transaction;  // number of dtlb ll dirty transactions
    uint32_t m_cpt_dtlb_sc_dirty_transaction;  // number of dtlb sc dirty transactions

    uint32_t m_cost_itlbmiss_transaction;       // cumulated duration for VCI instruction TLB miss transactions
    uint32_t m_cost_itlb_ll_transaction;        // cumulated duration for VCI instruction TLB ll acc transactions
    uint32_t m_cost_itlb_sc_transaction;        // cumulated duration for VCI instruction TLB sc acc transactions
    uint32_t m_cost_dtlbmiss_transaction;       // cumulated duration for VCI data TLB miss transactions
    uint32_t m_cost_dtlb_ll_transaction;        // cumulated duration for VCI data TLB ll acc transactions
    uint32_t m_cost_dtlb_sc_transaction;        // cumulated duration for VCI data TLB sc acc transactions
    uint32_t m_cost_dtlb_ll_dirty_transaction;  // cumulated duration for VCI data TLB ll dirty transactions
    uint32_t m_cost_dtlb_sc_dirty_transaction;  // cumulated duration for VCI data TLB sc dirty transactions

    // coherence activity counters
    uint32_t m_cpt_cc_update_icache;            // number of coherence update instruction commands
    uint32_t m_cpt_cc_update_dcache;            // number of coherence update data commands
    uint32_t m_cpt_cc_inval_icache;             // number of coherence inval instruction commands
    uint32_t m_cpt_cc_inval_dcache;             // number of coherence inval data commands
    uint32_t m_cpt_cc_broadcast;                // number of coherence broadcast commands
    
    uint32_t m_cost_updt_data_frz;              // number of frozen cycles related to coherence update data packets
    uint32_t m_cost_inval_ins_frz;              // number of frozen cycles related to coherence inval instruction packets
    uint32_t m_cost_inval_data_frz;             // number of frozen cycles related to coherence inval data packets
    uint32_t m_cost_broadcast_frz;              // number of frozen cycles related to coherence broadcast packets

    uint32_t m_cpt_cc_cleanup_ins;              // number of coherence cleanup packets
    uint32_t m_cpt_cc_cleanup_data;             // number of coherence cleanup packets

    uint32_t m_cpt_icleanup_transaction;        // number of instruction cleanup transactions
    uint32_t m_cpt_dcleanup_transaction;        // number of instructinumber of data cleanup transactions
    uint32_t m_cost_icleanup_transaction;       // cumulated duration for VCI instruction cleanup transactions
    uint32_t m_cost_dcleanup_transaction;       // cumulated duration for VCI data cleanup transactions

    uint32_t m_cost_ins_tlb_inval_frz;      // number of frozen cycles related to checking ins tlb invalidate
    uint32_t m_cpt_ins_tlb_inval;           // number of ins tlb invalidate

    uint32_t m_cost_data_tlb_inval_frz;     // number of frozen cycles related to checking data tlb invalidate    
    uint32_t m_cpt_data_tlb_inval;          // number of data tlb invalidate

    // FSM activity counters
    uint32_t m_cpt_fsm_icache     [64];
    uint32_t m_cpt_fsm_dcache     [64];
    uint32_t m_cpt_fsm_cmd        [64];
    uint32_t m_cpt_fsm_rsp        [64];
    uint32_t m_cpt_fsm_tgt        [64];
    uint32_t m_cpt_fsm_cmd_cleanup[64];
    uint32_t m_cpt_fsm_rsp_cleanup[64];

    uint32_t m_cpt_stop_simulation;		// used to stop simulation if frozen

protected:
    SC_HAS_PROCESS(VciCcVCacheWrapperV4);

public:
    VciCcVCacheWrapperV4(
        sc_module_name insname,
        int proc_id,
        const soclib::common::MappingTable &mtp,
        const soclib::common::MappingTable &mtc,
        const soclib::common::IntTab &initiator_index_d,
        const soclib::common::IntTab &initiator_index_c,
        const soclib::common::IntTab &target_index_d,
        size_t   itlb_ways,
        size_t   itlb_sets,
        size_t   dtlb_ways,
        size_t   dtlb_sets,
        size_t   icache_ways,
        size_t   icache_sets,
        size_t   icache_words,
        size_t   dcache_ways,
        size_t   dcache_sets,
        size_t   dcache_words,
        size_t   wbuf_nlines, 
        size_t   wbuf_nwords, 
        uint32_t max_frozen_cycles,
        uint32_t debug_start_cycle,
        bool     debug_ok);

    ~VciCcVCacheWrapperV4();

    void print_cpi();
    void print_stats();
    void clear_stats();
    void print_trace(size_t mode = 0);
    void cache_monitor(paddr_t addr);

private:
    void transition();
    void genMoore();

    soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC);
    soclib_static_assert((int)iss_t::SC_NOT_ATOMIC == (int)vci_param::STORE_COND_NOT_ATOMIC);
};

}}

#endif /* SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER_V4_H */

// Local Variables:
// tab-width: 4
// c-basic-offset: 4
// c-file-offsets:((innamespace . 0)(inline-open . 0))
// indent-tabs-mode: nil
// End:

// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4




