/* -*- c++ -*-
 * File         : vci_synthetic_initiator.h
 * Date         : 26/08/2010
 * Copyright    : UPMC / LIP6
 * Authors      : Christophe Choichillon
 *
 * SOCLIB_LGPL_HEADER_BEGIN
 *
 * This file is part of SoCLib, GNU LGPLv2.1.
 *
 * SoCLib is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; version 2.1 of the License.
 *
 * SoCLib is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with SoCLib; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 * SOCLIB_LGPL_HEADER_END
 *
 * Maintainers: christophe.choichillon@lip6.fr
 */

#ifndef SOCLIB_CABA_SYNTHETIC_INITIATOR_H
#define SOCLIB_CABA_SYNTHETIC_INITIATOR_H

#include <systemc>
#include <inttypes.h>
#include "generic_fifo.h"
#include "vci_initiator.h"
#include "soclib_endian.h"
#include "caba_base_module.h"
#include "int_tab.h"
#include "mapping_table.h"

namespace soclib {  namespace caba {
    using namespace sc_core;

    template<typename vci_param>
    class VciSyntheticInitiator
      : public soclib::caba::BaseModule
    {
      //typedef sc_dt::sc_uint<40> addr_t;
      typedef typename vci_param::fast_addr_t vci_addr_t;
      typedef uint32_t data_t;
      typedef uint32_t tag_t;
      typedef uint32_t size_t;
      typedef uint32_t be_t;
      typedef uint32_t copy_t;

      // Type of the addr_t and access of the fields
      typedef union{
        PACKED_BITFIELD(
	  vci_addr_t srcid:vci_param::S,
	  vci_addr_t null:(8*sizeof(vci_addr_t)-(2*vci_param::S)),
	) normal_address;
	PACKED_BITFIELD(
	  vci_addr_t xmin:vci_param::S,
	  vci_addr_t xmax:vci_param::S,
	  vci_addr_t ymin:vci_param::S,
	  vci_addr_t ymax:vci_param::S,
	  vci_addr_t null_:(8*sizeof(vci_addr_t)-(4*vci_param::S)),
	  vci_addr_t bc:2,
	) broadcast_address;
      } addr_t;


      /* States of the GENERATOR fsm */
      enum vci_fsm_state_e{
	VCI_IDLE,
	VCI_SINGLE_SEND,
	VCI_SINGLE_RECEIVE,
	VCI_BC_SEND,
	VCI_BC_RECEIVE
      };
      enum gen_fsm_state_e{
	A_IDLE,
	A_DATA
      };

      uint64_t	   m_cpt_cycles;            // Counter of cycles 
      

    protected:

      SC_HAS_PROCESS(VciSyntheticInitiator);
    
    public:
      sc_in<bool> 			  	p_clk;
      sc_in<bool> 			  	p_resetn;
      soclib::caba::VciInitiator<vci_param> 	p_vci;	

      VciSyntheticInitiator(
		sc_module_name name,
		const  soclib::common::MappingTable &mt,
		const  soclib::common::IntTab       &vci_index,
		size_t length,    // Packet length (flit numbers)
		float  rho,       // Packets ratio on the network
		size_t depth,     // Fifo depth
		size_t xmesh,	
		size_t ymesh,
		size_t bc_period = 0, // Broadcast period, if no broadcast => 0
		size_t xmin = 0, 
		size_t xmax = 0,
		size_t ymin = 0,
		size_t ymax = 0,
		);                                 

      ~VciSyntheticInitiator();

      void transition();

      void genMoore();

      void destAdress(size_t X_local, size_t Y_local, size_t &X_dest, size_t &Y_dest);

    private:

      // Component attributes
      const size_t   			  m_length;		// Number of words to write
      const size_t			  m_rho;		// Rate of packets in the network wanted
      const size_t			  m_depth;     		// Fifo depth
      const size_t			  m_xmesh;	
      const size_t			  m_ymesh;
      const size_t			  m_bc_period; 		// Broadcast period, if no broadcast => 0
      const size_t			  m_xmin; 
      const size_t			  m_xmax;
      const size_t			  m_ymin;
      const size_t			  m_ymax;
      const size_t			  m_srcid;
      const size_t			  m_coord;

      size_t      			  m_count;                  // Numbers of words sent
      size_t      			  m_npackets;		    // Total number of packets already sent
      uint64_t	  			  m_start_latency1;         // Start time of sending packet wanted
      uint64_t	  			  m_start_latency2;         // Start time of sending packet
      addr_t				  m_address_to_send;        // Address to send the write command
      float				  m_rhos;		    // Effective Rho during the simulation
      size_t				  m_bc_nrsp;		    // Expected number of responses for a broadcast command

      // Fifo transmitting date to the VCI FSM
      GenericFifo<uint64_t>    m_date_fifo;

      sc_signal<int>           r_vci_fsm;
	
      sc_signal<size_t>	       r_index;

      sc_signal<bool>	       r_broadcast_req;

    }; // end class VciSyntheticInitiator
 
  }}

#endif
