//////////////////////////////////////////////////////////////////////////////
// File: tsar_super_cluster.h
// Author: Manuel Bouyer
// Copyright: UPMC/LIP6
// Date : march 2016
// This program is released under the GNU public license
//////////////////////////////////////////////////////////////////////////////

#ifndef SOCLIB_CABA_TSAR_SUPER_CLUSTER_H
#define SOCLIB_CABA_TSAR_SUPER_CLUSTER_H

#include <systemc>
#include <sys/time.h>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <cstdarg>
#include <stdint.h>
#include "dspin_router_3d.h"
#include "tsar_xbar_cluster.h"

namespace soclib { namespace caba {

///////////////////////////////////////////////////////////////////////////
template<size_t dspin_cmd_width,
         size_t dspin_rsp_width,
         typename vci_param_int,
         typename vci_param_ext>  class TsarSuperCluster
///////////////////////////////////////////////////////////////////////////
    : public soclib::caba::BaseModule
{
    private:
    // Horizontal inter-clusters DSPIN signals
    DspinSignals<dspin_cmd_width>** signal_dspin_h_cmd_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_h_cmd_dec;
    DspinSignals<dspin_rsp_width>** signal_dspin_h_rsp_inc;
    DspinSignals<dspin_rsp_width>** signal_dspin_h_rsp_dec;
    DspinSignals<dspin_cmd_width>** signal_dspin_h_m2p_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_h_m2p_dec;
    DspinSignals<dspin_rsp_width>** signal_dspin_h_p2m_inc;
    DspinSignals<dspin_rsp_width>** signal_dspin_h_p2m_dec;
    DspinSignals<dspin_cmd_width>** signal_dspin_h_cla_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_h_cla_dec;

    // Vertical inter-clusters DSPIN signals
    DspinSignals<dspin_cmd_width>** signal_dspin_v_cmd_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_v_cmd_dec;
    DspinSignals<dspin_rsp_width>** signal_dspin_v_rsp_inc;
    DspinSignals<dspin_rsp_width>** signal_dspin_v_rsp_dec;
    DspinSignals<dspin_cmd_width>** signal_dspin_v_m2p_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_v_m2p_dec;
    DspinSignals<dspin_rsp_width>** signal_dspin_v_p2m_inc;
    DspinSignals<dspin_rsp_width>** signal_dspin_v_p2m_dec;
    DspinSignals<dspin_cmd_width>** signal_dspin_v_cla_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_v_cla_dec;

    // Z signals
    DspinSignals<dspin_cmd_width>** signal_dspin_zu_cmd_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_zu_cmd_dec;
    DspinSignals<dspin_rsp_width>** signal_dspin_zu_rsp_inc;
    DspinSignals<dspin_rsp_width>** signal_dspin_zu_rsp_dec;
    DspinSignals<dspin_cmd_width>** signal_dspin_zu_m2p_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_zu_m2p_dec;
    DspinSignals<dspin_rsp_width>** signal_dspin_zu_p2m_inc;
    DspinSignals<dspin_rsp_width>** signal_dspin_zu_p2m_dec;
    DspinSignals<dspin_cmd_width>** signal_dspin_zu_cla_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_zu_cla_dec;
    DspinSignals<dspin_cmd_width>** signal_dspin_zd_cmd_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_zd_cmd_dec;
    DspinSignals<dspin_rsp_width>** signal_dspin_zd_rsp_inc;
    DspinSignals<dspin_rsp_width>** signal_dspin_zd_rsp_dec;
    DspinSignals<dspin_cmd_width>** signal_dspin_zd_m2p_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_zd_m2p_dec;
    DspinSignals<dspin_rsp_width>** signal_dspin_zd_p2m_inc;
    DspinSignals<dspin_rsp_width>** signal_dspin_zd_p2m_dec;
    DspinSignals<dspin_cmd_width>** signal_dspin_zd_cla_inc;
    DspinSignals<dspin_cmd_width>** signal_dspin_zd_cla_dec;

    const size_t m_x_size;
    const size_t m_y_size;
    const size_t m_z_id;

    const size_t m_x_width;
    const size_t m_y_width;
    const size_t m_z_width;

    public:

    // Ports
    sc_in<bool>                                     p_clk;
    sc_in<bool>                                     p_resetn;

    soclib::caba::DspinOutput<dspin_cmd_width>      *p_cmd_out;
    soclib::caba::DspinInput<dspin_cmd_width>       *p_cmd_in;

    soclib::caba::DspinOutput<dspin_rsp_width>      *p_rsp_out;
    soclib::caba::DspinInput<dspin_rsp_width>       *p_rsp_in;

    soclib::caba::DspinOutput<dspin_cmd_width>      *p_m2p_out;
    soclib::caba::DspinInput<dspin_cmd_width>       *p_m2p_in;

    soclib::caba::DspinOutput<dspin_rsp_width>      *p_p2m_out;
    soclib::caba::DspinInput<dspin_rsp_width>       *p_p2m_in;

    soclib::caba::DspinOutput<dspin_cmd_width>      *p_cla_out;
    soclib::caba::DspinInput<dspin_cmd_width>       *p_cla_in;

    TsarXbarCluster<dspin_cmd_width,
                    dspin_rsp_width,
                    vci_param_int,
		    vci_param_ext> *clusters[32][32];


    TsarSuperCluster( sc_module_name                    insname,
                     size_t                             nb_procs,      // processors
                     size_t                             nb_ttys,       // TTY terminals
                     size_t                             nb_dmas,       //  DMA channels
                     size_t                             x_size,
                     size_t                             y_size,
                     size_t                             z,             // z coordinate
		     size_t				elevator_x,
		     size_t				elevator_y,
                     const soclib::common::MappingTable &mtd,          // internal
                     const soclib::common::MappingTable &mtx,          // external
                     size_t                             x_width,       // x field bits
                     size_t                             y_width,       // y field bits
                     size_t                             z_width,       // z field bits
                     size_t                             p_width,
                     size_t                             vci_srcid_width,
                     size_t                             tgtid_memc,
                     size_t                             tgtid_xicu,
                     size_t                             tgtid_mdma,
                     size_t                             tgtid_fbuf,
                     size_t                             tgtid_mtty,
                     size_t                             tgtid_brom,
                     size_t                             tgtid_mnic,
                     size_t                             tgtid_chbuf,
                     size_t                             tgtid_bdev,
                     size_t                             tgtid_simh,
                     size_t                             memc_ways,
                     size_t                             memc_sets,
                     size_t                             l1_i_ways,
                     size_t                             l1_i_sets,
                     size_t                             l1_d_ways,
                     size_t                             l1_d_sets,
                     size_t                             irq_per_processor,
                     size_t                             xram_latency,  // external ram
                     size_t				x_io,
		     size_t				y_io,
		     size_t				z_io,
                     size_t                             xfb,           // fbf pixels
                     size_t                             yfb,           // fbf lines
                     char*                              disk_name,     // virtual disk
                     size_t                             block_size,    // block size
                     size_t                             nic_channels,  // number channels
                     char*                              nic_rx_name,   // filename rx
                     char*                              nic_tx_name,   // filename tx
                     uint32_t                           nic_timeout,   // cycles
                     size_t                             chbufdma_channels,  // number channels
                     const Loader                       &loader,
                     uint32_t                           frozen_cycles,
                     uint32_t                           start_debug_cycle,
                     bool                               memc_debug_ok,
                     bool                               proc_debug_ok);

    ~TsarSuperCluster();
    void trace(sc_trace_file * tf);
    void reset();

};
}}

#endif
