/* -*- 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) Telecom ParisTech, Comelec 
 *         Jeremie Brunel <jeremie.brunel@telecom-paristech.fr>, 2013
 *
 */
#ifndef SOCLIB_CABA_TESTER_ARBITER
#define SOCLIB_CABA_TESTER_ARBITER

#include <systemc>
#include "caba_base_module.h"

namespace soclib {
    namespace caba {
        using namespace sc_core;
        
            class VciTesterArbiter
            : public BaseModule
            {

                protected:
                    SC_HAS_PROCESS(VciTesterArbiter);

                public:
                    VciTesterArbiter(sc_module_name insname, const size_t nb_tester)
                      : p_clk("p_clk"),
                      p_resetn("p_resetn"),
                      soclib::caba::BaseModule(insname)
                    {
                      p_synchros = new sc_out<bool>[nb_tester];
                      p_times = new sc_in<uint32_t>[nb_tester];

                      m_nb_tester = nb_tester;

                      SC_METHOD(transition);
                      dont_initialize();
                      //sensitive << p_clk.pos();
                      for (size_t i=0;i<nb_tester;i++)
                      {
                          sensitive << p_times[i];
                      }

                      SC_METHOD(genMoore);
                      dont_initialize();
                      sensitive << p_clk.neg();
                    }

                    sc_out<bool> *p_synchros;
                    sc_in<uint32_t> *p_times;
                    sc_in<bool> p_clk;
                    sc_in<bool> p_resetn;

                    void transition()
                    {
                      if (!p_resetn)
                      {
                        return;
                      }

                      m_time = p_times[0].read();
                      for (size_t i=1;i<m_nb_tester;i++)
                      {
                        if (p_times[i].read()<m_time)
                          m_time = p_times[i].read();
                      }
                    }

                    void genMoore()
                    {
                      bool end = true;
                      for (size_t i=0;i<m_nb_tester;i++)
                      {
                        if (p_times[i].read() != (uint32_t)-1)
                          end = false;

                        if (p_times[i].read() == m_time)
                        {
                          p_synchros[i] = true;
                          //std::cout << i << " ok (" << m_time << ")" << std::endl;
                        }
                        else
                        {
                          p_synchros[i] = false;
                        }
                      }
                      if (end)
                      {
                        std::cout << "end of simulation, everything is working\n";
                        sc_stop();
                      }
                    }

                    ~VciTesterArbiter()
                    {
                    }

                private:
                    uint32_t m_time;
                    size_t m_nb_tester;
            };

    }
}

#endif 
