/* -*- c++ -*-
 * File         : vci_synthetic_initiator.h
 * Date         : 26/08/2010
 * Copyright    : UPMC / LIP6
 * Authors      : Christophe Choichillon
 * Version	: 2.1
 * 
 * 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
 *
 * Versions :
 *           - 1.0 Sending only one request at a time
 *	     - 2.0 Sending multiple transactions and broadcast responses 
 *		   identified with pktid (deprecated)
 *	     - 2.1 Broadcast responses identified with the value 0 of trdid
 *
 * Maintainers: christophe.choichillon@lip6.fr
 */

#ifndef SOCLIB_CABA_SYNTHETIC_INITIATOR_H
#define SOCLIB_CABA_SYNTHETIC_INITIATOR_H

#include <cassert>
#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"
#include "arithmetics.h"

namespace soclib {  namespace caba {
    using namespace sc_core;

    template<typename vci_param>
    class VciSyntheticInitiator
      : public soclib::caba::BaseModule
    {
      typedef uint32_t addr_t;
      typedef uint32_t data_t;
      typedef uint32_t tag_t;
      typedef uint32_t size_t;
      typedef uint32_t be_t;
      typedef uint32_t copy_t;


      /* States of the VCI CMD fsm */
      enum vci_fsm_state_e{
	VCI_IDLE,
	VCI_SINGLE_SEND,
	VCI_BC_SEND,
	VCI_SINGLE_REGISTER
      };

      enum bc_fsm_state_e{
      	BC_RSP_IDLE,
	BC_RSP_WAIT_RSP
      };


      

    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,
		const uint32_t length,    // Packet length (flit numbers)
		const uint32_t rho,       // Packets ratio on the network
		const uint32_t depth,     // Fifo depth
		const uint32_t xmesh,	
		const uint32_t ymesh,
		const uint32_t bc_period = 0, // Broadcast period, if no broadcast => 0
		const uint32_t xmin = 0, 
		const uint32_t xmax = 0,
		const uint32_t ymin = 0,
		const uint32_t ymax = 0
		);                                 

      ~VciSyntheticInitiator();

      void transition();

      void genMoore();

      uint32_t destAdress();

      uint32_t destAdress(uint32_t *rand_seed);

      void printStats();

      double getLatencySingle();

      double getLatencyBC();

      void print_trace();

    private:

      // Component attributes
      const size_t   		  m_length;		// Number of words to write
      const size_t		  m_rho;		// offered load * 1000
      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;
      static const size_t 	  m_tab_size = 1 << vci_param::T;


      // Fifo transmitting requests from the generator FSM to the VCI FSM
      GenericFifo<uint64_t>    	r_date_fifo;
      GenericFifo<bool>    	r_bc_fifo;

      // VCI CMD FSM
      sc_signal<int>           	r_cmd_fsm;
      sc_signal<addr_t>		r_cmd_address;  // Address for the single transaction
      sc_signal<int>		r_cmd_trdid;	// TRDID for the single transaction
      sc_signal<size_t>    	r_cmd_count;    // Numbers of words sent
      sc_signal<uint32_t>	r_cmd_seed;	// seed for reproducible address generation 

      // Broadcast FSM
      sc_signal<uint32_t>	r_bc_nrsp;	   // Expected number of responses for a broadcast command
      sc_signal<uint32_t>       r_time_to_next_bc; // Time to wait between 2 BC
	
      // Pending transaction FSMs
      sc_signal<bool>*		r_pending_fsm;  // FSM states
      sc_signal<uint64_t>*	r_pending_date; // single transaction requested date

      // Instrumentation registers
      sc_signal<uint64_t>	r_cpt_cycles;   // Local time 
      sc_signal<uint64_t>	r_cpt_period;   // Number of cycles between 2 broadcast transactions
      sc_signal<size_t>      	r_nb_single;	// Total number of single transactions
      sc_signal<uint64_t>  	r_latency_single;	// Total cumulated latency for single transactions
      sc_signal<size_t>		r_nb_bc;	// Total number of bc transactions
      sc_signal<uint64_t>	r_latency_bc;	// Total cumulated latency for broadcast transactions

    }; // end class VciSyntheticInitiator
 
  }}

#endif
