/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__
#define __SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__

#include <list>
#include <string>

#include "../core/sc_module.hh" // for sc_gen_unique_name
#include "../core/sc_prim.hh"
#include "../utils/sc_report_handler.hh"
#include "sc_fifo_in_if.hh"
#include "sc_fifo_out_if.hh"

namespace sc_core
{

class sc_port_base;
class sc_event;

template <class T>
class sc_fifo : public sc_fifo_in_if<T>,
                public sc_fifo_out_if<T>,
                public sc_prim_channel
{
  public:
    explicit sc_fifo(int size=16) :
            sc_fifo_in_if<T>(), sc_fifo_out_if<T>(),
            sc_prim_channel(sc_gen_unique_name("fifo")),
            _size(size), _readsHappened(false), _reader(NULL), _writer(NULL)
    {}
    explicit sc_fifo(const char *name, int size=16) :
            sc_fifo_in_if<T>(), sc_fifo_out_if<T>(),
            sc_prim_channel(name), _size(size), _readsHappened(false),
            _reader(NULL), _writer(NULL)
    {}
    virtual ~sc_fifo() {}

    virtual void
    register_port(sc_port_base &port, const char *iface_type_name)
    {
        std::string tn(iface_type_name);
        if (tn == typeid(sc_fifo_in_if<T>).name() ||
                tn == typeid(sc_fifo_blocking_in_if<T>).name()) {
            if (_reader) {
                SC_REPORT_ERROR(
                        "(E104) sc_fifo<T> cannot have more than one reader",
                        "");
            }
            _reader = &port;
        } else if (tn == typeid(sc_fifo_out_if<T>).name() ||
                tn == typeid(sc_fifo_blocking_out_if<T>).name()) {
            if (_writer) {
                SC_REPORT_ERROR(
                        "(E105) sc_fifo<T> cannot have more than one writer",
                        "");
            }
            _writer = &port;
        } else {
            SC_REPORT_ERROR("(E107) bind interface to port failed",
                    "sc_fifo<T> port not recognized");
        }
    }

    virtual void
    read(T &t)
    {
        while (num_available() == 0)
            sc_core::wait(_dataWriteEvent);
        _readsHappened = true;
        t = _entries.front();
        _entries.pop_front();
        request_update();
    }
    virtual T
    read()
    {
        T t;
        read(t);
        return t;
    }
    virtual bool
    nb_read(T &t)
    {
        if (num_available()) {
            read(t);
            return true;
        } else {
            return false;
        }
    }
    operator T() { return read(); }

    virtual void
    write(const T &t)
    {
        while (num_free() == 0)
            sc_core::wait(_dataReadEvent);
        _pending.emplace_back(t);
        request_update();
    }
    virtual bool
    nb_write(const T &t)
    {
        if (num_free()) {
            write(t);
            return true;
        } else {
            return false;
        }
    }
    sc_fifo<T> &
    operator = (const T &t)
    {
        write(t);
        return *this;
    }

    virtual const sc_event &
    data_written_event() const
    {
        return _dataWriteEvent;
    }
    virtual const sc_event &
    data_read_event() const
    {
        return _dataReadEvent;
    }

    virtual int num_available() const { return _entries.size(); }
    virtual int
    num_free() const
    {
        return _size - _entries.size() - _pending.size();
    }

    virtual void
    print(std::ostream &os=std::cout) const
    {
        for (typename ::std::list<T>::iterator pos = _pending.begin();
                pos != _pending.end(); pos++) {
            os << *pos << ::std::endl;
        }
        for (typename ::std::list<T>::iterator pos = _entries.begin();
                pos != _entries.end(); pos++) {
            os << *pos << ::std::endl;
        }
    }
    virtual void
    dump(std::ostream &os=std::cout) const
    {
        os << "name = " << name() << std::endl;
        int idx = 0;
        for (typename ::std::list<T>::iterator pos = _pending.begin();
                pos != _pending.end(); pos++) {
            os << "value[" << idx++ << "] = " << *pos << ::std::endl;
        }
        for (typename ::std::list<T>::iterator pos = _entries.begin();
                pos != _entries.end(); pos++) {
            os << "value[" << idx++ << "] = " << *pos << ::std::endl;
        }
    }
    virtual const char *kind() const { return "sc_fifo"; }

  protected:
    virtual void
    update()
    {
        if (!_pending.empty()) {
            _dataWriteEvent.notify(SC_ZERO_TIME);
            _entries.insert(_entries.end(), _pending.begin(), _pending.end());
            _pending.clear();
        }
        if (_readsHappened) {
            _readsHappened = false;
            _dataReadEvent.notify(SC_ZERO_TIME);
        }
    }

  private:
    // Disabled
    sc_fifo(const sc_fifo<T> &) :
            sc_fifo_in_if<T>(), sc_fifo_in_if<T>(), sc_prim_channel()
    {}
    sc_fifo &operator = (const sc_fifo<T> &) { return *this; }

    sc_gem5::InternalScEvent _dataReadEvent;
    sc_gem5::InternalScEvent _dataWriteEvent;

    sc_port_base *_reader;
    sc_port_base *_writer;

    int _size;
    mutable std::list<T> _entries;
    mutable std::list<T> _pending;
    bool _readsHappened;
};

template <class T>
inline std::ostream &
operator << (std::ostream &os, const sc_fifo<T> &f)
{
    f.print(os);
    return os;
}

} // namespace sc_core

#endif  //__SYSTEMC_EXT_CHANNEL_SC_FIFO_HH__
