/*
 * Copyright (c) 2013-2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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.
 */

/**
 * @file
 *
 * Classes for buffer, queue and FIFO behaviour.
 */

#ifndef __CPU_MINOR_BUFFERS_HH__
#define __CPU_MINOR_BUFFERS_HH__

#include <iostream>
#include <queue>
#include <sstream>

#include "base/logging.hh"
#include "cpu/activity.hh"
#include "cpu/minor/trace.hh"
#include "cpu/timebuf.hh"

namespace Minor
{

/** Interface class for data with reporting/tracing facilities.  This
 *  interface doesn't actually have to be used as other classes which need
 *  this interface uses templating rather than inheritance but it's provided
 *  here to document the interface needed by those classes. */
class ReportIF
{
  public:
    /** Print the data in a format suitable to be the value in "name=value"
     *  trace lines */
    virtual void reportData(std::ostream &os) const = 0;

    virtual ~ReportIF() { }
};

/** Interface class for data with 'bubble' values.  This interface doesn't
 *  actually have to be used as other classes which need this interface uses
 *  templating rather than inheritance but it's provided here to document
 *  the interface needed by those classes. */
class BubbleIF
{
  public:
    virtual bool isBubble() const = 0;
};

/** ...ReportTraits are trait classes with the same functionality as
 *  ReportIF, but with elements explicitly passed into the report...
 *  functions. */

/** Allow a template using ReportTraits to call report... functions of
 *  ReportIF-bearing elements themselves */
template <typename ElemType> /* ElemType should implement ReportIF */
class ReportTraitsAdaptor
{
  public:
    static void
    reportData(std::ostream &os, const ElemType &elem)
    { elem.reportData(os); }
};

/** A similar adaptor but for elements held by pointer
 *  ElemType should implement ReportIF */
template <typename PtrType>
class ReportTraitsPtrAdaptor
{
  public:
    static void
    reportData(std::ostream &os, const PtrType &elem)
    { elem->reportData(os); }
};

/** ... BubbleTraits are trait classes to add BubbleIF interface
 *  functionality to templates which process elements which don't necessarily
 *  implement BubbleIF themselves */

/** Default behaviour, no bubbles */
template <typename ElemType>
class NoBubbleTraits
{
  public:
    static bool isBubble(const ElemType &) { return false; }
    static ElemType
    bubble()
    {
        panic("bubble called but no bubble interface");
    }
};

/** Pass on call to the element */
template <typename ElemType>
class BubbleTraitsAdaptor
{
  public:
    static bool isBubble(const ElemType &elem)
    { return elem.isBubble(); }

    static ElemType bubble() { return ElemType::bubble(); }
};

/** Pass on call to the element where the element is a pointer */
template <typename PtrType, typename ElemType>
class BubbleTraitsPtrAdaptor
{
  public:
    static bool isBubble(const PtrType &elem)
    { return elem->isBubble(); }

    static PtrType bubble() { return ElemType::bubble(); }
};

/** TimeBuffer with MinorTrace and Named interfaces */
template <typename ElemType,
    typename ReportTraits = ReportTraitsAdaptor<ElemType>,
    typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
class MinorBuffer : public Named, public TimeBuffer<ElemType>
{
  protected:
    /** The range of elements that should appear in trace lines */
    int reportLeft, reportRight;

    /** Name to use for the data in a MinorTrace line */
    std::string dataName;

  public:
    MinorBuffer(const std::string &name,
        const std::string &data_name,
        int num_past, int num_future,
        int report_left = -1, int report_right = -1) :
        Named(name), TimeBuffer<ElemType>(num_past, num_future),
        reportLeft(report_left), reportRight(report_right),
            dataName(data_name)
    { }

  public:
    /* Is this buffer full of only bubbles */
    bool
    empty() const
    {
        bool ret = true;

        for (int i = -this->past; i <= this->future; i++) {
            if (!BubbleTraits::isBubble((*this)[i]))
                ret = false;
        }

        return ret;
    }

    /** Report buffer states from 'slot' 'from' to 'to'.  For example 0,-1
      * will produce two slices with current (just assigned) and last (one
      * advance() old) slices with the current (0) one on the left.
      * Reverse the numbers to change the order of slices */
    void
    minorTrace() const
    {
        std::ostringstream data;

        int step = (reportLeft > reportRight ? -1 : 1);
        int end = reportRight + step;
        int i = reportLeft;

        while (i != end) {
            const ElemType &datum = (*this)[i];

            ReportTraits::reportData(data, datum);
            i += step;
            if (i != end)
                data << ',';
        }

        MINORTRACE("%s=%s\n", dataName, data.str());
    }
};

/** Wraps a MinorBuffer with Input/Output interfaces to ensure that units
 *  within the model can only see the right end of buffers between them. */
template <typename Data>
class Latch
{
  public:
    typedef MinorBuffer<Data> Buffer;

  protected:
    /** Delays, in cycles, writing data into the latch and seeing it on the
     *  latched wires */
    Cycles delay;

    Buffer buffer;

  public:
    /** forward/backwardDelay specify the delay from input to output in each
     *  direction.  These arguments *must* be >= 1 */
    Latch(const std::string &name,
        const std::string &data_name,
        Cycles delay_ = Cycles(1),
        bool report_backwards = false) :
        delay(delay_),
        buffer(name, data_name, delay_, 0, (report_backwards ? -delay_ : 0),
            (report_backwards ? 0 : -delay_))
    { }

  public:
    /** Encapsulate wires on either input or output of the latch.
     *  forward/backward correspond to data direction relative to the
     *  pipeline.  Latched and Immediate specify delay for backward data.
     *  Immediate data is available to earlier stages *during* the cycle it
     *  is written */
    class Input
    {
      public:
        typename Buffer::wire inputWire;

      public:
        Input(typename Buffer::wire input_wire) :
            inputWire(input_wire)
        { }
    };

    class Output
    {
      public:
        typename Buffer::wire outputWire;

      public:
        Output(typename Buffer::wire output_wire) :
            outputWire(output_wire)
        { }
    };

    bool empty() const { return buffer.empty(); }

    /** An interface to just the input of the buffer */
    Input input() { return Input(buffer.getWire(0)); }

    /** An interface to just the output of the buffer */
    Output output() { return Output(buffer.getWire(-delay)); }

    void minorTrace() const { buffer.minorTrace(); }

    void evaluate() { buffer.advance(); }
};

/** A pipeline simulating class that will stall (not advance when advance()
 *  is called) if a non-bubble value lies at the far end of the pipeline.
 *  The user can clear the stall before calling advance to unstall the
 *  pipeline. */
template <typename ElemType,
    typename ReportTraits,
    typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
class SelfStallingPipeline : public MinorBuffer<ElemType, ReportTraits>
{
  protected:
    /** Wire at the input end of the pipeline (for convenience) */
    typename TimeBuffer<ElemType>::wire pushWire;
    /** Wire at the output end of the pipeline (for convenience) */
    typename TimeBuffer<ElemType>::wire popWire;

  public:
    /** If true, advance will not advance the pipeline */
    bool stalled;

    /** The number of slots with non-bubbles in them */
    unsigned int occupancy;

  public:
    SelfStallingPipeline(const std::string &name,
        const std::string &data_name,
        unsigned depth) :
        MinorBuffer<ElemType, ReportTraits>
            (name, data_name, depth, 0, -1, -depth),
        pushWire(this->getWire(0)),
        popWire(this->getWire(-depth)),
        stalled(false),
        occupancy(0)
    {
        assert(depth > 0);

        /* Write explicit bubbles to get around the case where the default
         *  constructor for the element type isn't good enough */
        for (unsigned i = 0; i <= depth; i++)
            (*this)[-i] = BubbleTraits::bubble();
    }

  public:
    /** Write an element to the back of the pipeline.  This doesn't cause
     *  the pipeline to advance until advance is called.  Pushing twice
     *  without advance-ing will just cause an overwrite of the last push's
     *  data. */
    void push(ElemType &elem)
    {
        assert(!alreadyPushed());
        *pushWire = elem;
        if (!BubbleTraits::isBubble(elem))
            occupancy++;
    }

    /** Peek at the end element of the pipe */
    ElemType &front() { return *popWire; }

    const ElemType &front() const { return *popWire; }

    /** Have we already pushed onto this pipe without advancing */
    bool alreadyPushed() { return !BubbleTraits::isBubble(*pushWire); }

    /** There's data (not a bubble) at the end of the pipe */
    bool isPopable() { return !BubbleTraits::isBubble(front()); }

    /** Try to advance the pipeline.  If we're stalled, don't advance.  If
     *  we're not stalled, advance then check to see if we become stalled
     *  (a non-bubble at the end of the pipe) */
    void
    advance()
    {
        bool data_at_end = isPopable();

        if (!stalled) {
            TimeBuffer<ElemType>::advance();
            /* If there was data at the end of the pipe that has now been
             *  advanced out of the pipe, we've lost data */
            if (data_at_end)
                occupancy--;
            /* Is there data at the end of the pipe now? */
            stalled = isPopable();
            /* Insert a bubble into the empty input slot to make sure that
             *  element is correct in the case where the default constructor
             *  for ElemType doesn't produce a bubble */
            ElemType bubble = BubbleTraits::bubble();
            *pushWire = bubble;
        }
    }
};

/** Base class for space reservation requestable objects */
class Reservable
{
  public:
    /** Can a slot be reserved? */
    virtual bool canReserve() const = 0;

    /** Reserve a slot in whatever structure this is attached to */
    virtual void reserve() = 0;

    /** Free a reserved slot */
    virtual void freeReservation() = 0;

    virtual ~Reservable() {};
};

/** Wrapper for a queue type to act as a pipeline stage input queue.
 *  Handles capacity management, bubble value suppression and provides
 *  reporting.
 *
 *  In an ideal world, ElemType would be derived from ReportIF and BubbleIF,
 *  but here we use traits and allow the Adaptors ReportTraitsAdaptor and
 *  BubbleTraitsAdaptor to work on data which *does* directly implement
 *  those interfaces. */
template <typename ElemType,
    typename ReportTraits = ReportTraitsAdaptor<ElemType>,
    typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
class Queue : public Named, public Reservable
{
  private:
      std::deque<ElemType> queue;

    /** Number of slots currently reserved for future (reservation
     *  respecting) pushes */
    unsigned int numReservedSlots;

    /** Need this here as queues usually don't have a limited capacity */
    unsigned int capacity;

    /** Name to use for the data in MinorTrace */
    std::string dataName;

  public:
    Queue(const std::string &name, const std::string &data_name,
        unsigned int capacity_) :
        Named(name),
        numReservedSlots(0),
        capacity(capacity_),
        dataName(data_name)
    { }

  public:
    /** Push an element into the buffer if it isn't a bubble.  Bubbles are
     *  just discarded.  It is assummed that any push into a queue with
     *  reserved space intends to take that space */
    void
    push(ElemType &data)
    {
        if (!BubbleTraits::isBubble(data)) {
            freeReservation();
            queue.push_back(data);

            if (queue.size() > capacity) {
                warn("%s: No space to push data into queue of capacity"
                    " %u, pushing anyway\n", name(), capacity);
            }

        }
    }

    /** Clear all allocated space.  Be careful how this is used */
    void clearReservedSpace() { numReservedSlots = 0; }

    /** Clear a single reserved slot */
    void freeReservation()
    {
        if (numReservedSlots != 0)
            numReservedSlots--;
    }

    /** Reserve space in the queue for future pushes.  Enquiries about space
     *  in the queue using unreservedRemainingSpace will only tell about
     *  space which is not full and not reserved. */
    void
    reserve()
    {
        /* Check reservable space */
        if (unreservedRemainingSpace() == 0)
            warn("%s: No space is reservable in queue", name());

        numReservedSlots++;
    }

    bool canReserve() const { return unreservedRemainingSpace() != 0; }

    /** Number of slots available in an empty buffer */
    unsigned int totalSpace() const { return capacity; }

    /** Number of slots already occupied in this buffer */
    unsigned int occupiedSpace() const { return queue.size(); }

    /** Number of slots which are reserved. */
    unsigned int reservedSpace() const { return numReservedSlots; }

    /** Number of slots yet to fill in this buffer.  This doesn't include
     *  reservation. */
    unsigned int
    remainingSpace() const
    {
        int ret = capacity - queue.size();

        return (ret < 0 ? 0 : ret);
    }

    /** Like remainingSpace but does not count reserved spaces */
    unsigned int
    unreservedRemainingSpace() const
    {
        int ret = capacity - (queue.size() + numReservedSlots);

        return (ret < 0 ? 0 : ret);
    }

    /** Head value.  Like std::queue::front */
    ElemType &front() { return queue.front(); }

    const ElemType &front() const { return queue.front(); }

    /** Pop the head item.  Like std::queue::pop */
    void pop() { queue.pop_front(); }

    /** Is the queue empty? */
    bool empty() const { return queue.empty(); }

    void
    minorTrace() const
    {
        std::ostringstream data;
        /* If we become over-full, totalSpace() can actually be smaller than
         * occupiedSpace().  Handle this */
        unsigned int num_total = (occupiedSpace() > totalSpace() ?
            occupiedSpace() : totalSpace());

        unsigned int num_reserved = reservedSpace();
        unsigned int num_occupied = occupiedSpace();

        int num_printed = 1;
        /* Bodge to rotate queue to report elements */
        while (num_printed <= num_occupied) {
            ReportTraits::reportData(data, queue[num_printed - 1]);
            num_printed++;

            if (num_printed <= num_total)
                data << ',';
        }

        int num_printed_reserved = 1;
        /* Show reserved slots */
        while (num_printed_reserved <= num_reserved &&
            num_printed <= num_total)
        {
            data << 'R';
            num_printed_reserved++;
            num_printed++;

            if (num_printed <= num_total)
                data << ',';
        }

        /* And finally pad with empty slots (if there are any) */
        while (num_printed <= num_total) {
            num_printed++;

            if (num_printed <= num_total)
                data << ',';
        }

        MINORTRACE("%s=%s\n", dataName, data.str());
    }
};

/** Like a Queue but with a restricted interface and a setTail function
 *  which, when the queue is empty, just takes a reference to the pushed
 *  item as the single element.  Calling pushTail will push that element
 *  onto the queue.
 *
 *  The purpose of this class is to allow the faster operation of queues of
 *  items which usually don't get deeper than one item and for which the copy
 *  associated with a push is expensive enough to want to avoid
 *
 *  The intended use case is the input buffer for pipeline stages, hence the
 *  class name */
template <typename ElemType,
    typename ReportTraits = ReportTraitsAdaptor<ElemType>,
    typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
class InputBuffer : public Reservable
{
  protected:
    /** Underlying queue */
    mutable Queue<ElemType, ReportTraits, BubbleTraits> queue;

    /** Pointer to the single element (if not NULL) */
    mutable ElemType *elementPtr;

  public:
    InputBuffer(const std::string &name, const std::string &data_name,
        unsigned int capacity_) :
        queue(name, data_name, capacity_),
        elementPtr(NULL)
    { }

  public:
    /** Set the tail of the queue, this is like push but needs
     *  to be followed by pushTail for the new tail to make its
     *  way into the queue proper */
    void
    setTail(ElemType &new_element)
    {
        assert(!elementPtr);
        if (!BubbleTraits::isBubble(new_element)) {
            if (queue.empty())
                elementPtr = &new_element;
            else
                queue.push(new_element);
        }
    }

    /** No single element or queue entries */
    bool empty() const { return !elementPtr && queue.empty(); }

    /** Return the element, or the front of the queue */
    const ElemType &front() const
    { return (elementPtr ? *elementPtr : queue.front()); }

    ElemType &front()
    { return (elementPtr ? *elementPtr : queue.front()); }

    /** Pop either the head, or if none, the head of the queue */
    void
    pop()
    {
        if (elementPtr) {
            /* A popped element was expected to be pushed into queue
             *  and so take a reserved space */
            elementPtr = NULL;
            queue.freeReservation();
        } else {
            queue.pop();
        }
    }

    /** Push the single element (if any) into the queue proper.  If the
     *  element's reference points to a transient object, remember to
     *  always do this before the end of that object's life */
    void
    pushTail() const
    {
        if (elementPtr)
            queue.push(*elementPtr);
        elementPtr = NULL;
    }

    /** Report elements */
    void
    minorTrace() const
    {
        pushTail();
        queue.minorTrace();
    }

    /** Reservable interface, passed on to queue */
    bool canReserve() const { return queue.canReserve(); }
    void reserve() { queue.reserve(); }
    void freeReservation() { queue.freeReservation(); }

    /** Like remainingSpace but does not count reserved spaces */
    unsigned int
    unreservedRemainingSpace()
    {
        pushTail();
        return queue.unreservedRemainingSpace();
    }
};

}

#endif /* __CPU_MINOR_BUFFERS_HH__ */
