/*
 * Copyright (c) 2016-2018 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.
 *
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * Copyright (c) 2013 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * 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: Kevin Lim
 */

#ifndef __CPU_O3_FREE_LIST_HH__
#define __CPU_O3_FREE_LIST_HH__

#include <iostream>
#include <queue>
#include <vector>

#include "base/logging.hh"
#include "base/trace.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/regfile.hh"
#include "debug/FreeList.hh"

/**
 * Free list for a single class of registers (e.g., integer
 * or floating point).  Because the register class is implicitly
 * determined by the rename map instance being accessed, all
 * architectural register index parameters and values in this class
 * are relative (e.g., %fp2 is just index 2).
 */
class SimpleFreeList
{
  private:

    /** The actual free list */
    std::queue<PhysRegIdPtr> freeRegs;

  public:

    SimpleFreeList() {};

    /** Add a physical register to the free list */
    void addReg(PhysRegIdPtr reg) { freeRegs.push(reg); }

    /** Add physical registers to the free list */
    template<class InputIt>
    void
    addRegs(InputIt first, InputIt last) {
        std::for_each(first, last, [this](typename InputIt::value_type& reg) {
            this->freeRegs.push(&reg);
        });
    }

    /** Get the next available register from the free list */
    PhysRegIdPtr getReg()
    {
        assert(!freeRegs.empty());
        PhysRegIdPtr free_reg = freeRegs.front();
        freeRegs.pop();
        return free_reg;
    }

    /** Return the number of free registers on the list. */
    unsigned numFreeRegs() const { return freeRegs.size(); }

    /** True iff there are free registers on the list. */
    bool hasFreeRegs() const { return !freeRegs.empty(); }
};


/**
 * FreeList class that simply holds the list of free integer and floating
 * point registers.  Can request for a free register of either type, and
 * also send back free registers of either type.  This is a very simple
 * class, but it should be sufficient for most implementations.  Like all
 * other classes, it assumes that the indices for the floating point
 * registers starts after the integer registers end.  Hence the variable
 * numPhysicalIntRegs is logically equivalent to the baseFP dependency.
 * Note that while this most likely should be called FreeList, the name
 * "FreeList" is used in a typedef within the CPU Policy, and therefore no
 * class can be named simply "FreeList".
 * @todo: Give a better name to the base FP dependency.
 */
class UnifiedFreeList
{
  private:

    /** The object name, for DPRINTF.  We have to declare this
     *  explicitly because Scoreboard is not a SimObject. */
    const std::string _name;

    /** The list of free integer registers. */
    SimpleFreeList intList;

    /** The list of free floating point registers. */
    SimpleFreeList floatList;

    /** The following two are exclusive interfaces. */
    /** @{ */
    /** The list of free vector registers. */
    SimpleFreeList vecList;

    /** The list of free vector element registers. */
    SimpleFreeList vecElemList;
    /** @} */

    /** The list of free predicate registers. */
    SimpleFreeList predList;

    /** The list of free condition-code registers. */
    SimpleFreeList ccList;

    /**
     * The register file object is used only to distinguish integer
     * from floating-point physical register indices.
     */
    PhysRegFile *regFile;

    /*
     * We give UnifiedRenameMap internal access so it can get at the
     * internal per-class free lists and associate those with its
     * per-class rename maps. See UnifiedRenameMap::init().
     */
    friend class UnifiedRenameMap;

  public:
    /** Constructs a free list.
     *  @param _numPhysicalIntRegs Number of physical integer registers.
     *  @param reservedIntRegs Number of integer registers already
     *                         used by initial mappings.
     *  @param _numPhysicalFloatRegs Number of physical fp registers.
     *  @param reservedFloatRegs Number of fp registers already
     *                           used by initial mappings.
     */
    UnifiedFreeList(const std::string &_my_name, PhysRegFile *_regFile);

    /** Gives the name of the freelist. */
    std::string name() const { return _name; };

    /** Returns a pointer to the condition-code free list */
    SimpleFreeList *getCCList() { return &ccList; }

    /** Gets a free integer register. */
    PhysRegIdPtr getIntReg() { return intList.getReg(); }

    /** Gets a free fp register. */
    PhysRegIdPtr getFloatReg() { return floatList.getReg(); }

    /** Gets a free vector register. */
    PhysRegIdPtr getVecReg() { return vecList.getReg(); }

    /** Gets a free vector elemenet register. */
    PhysRegIdPtr getVecElem() { return vecElemList.getReg(); }

    /** Gets a free predicate register. */
    PhysRegIdPtr getVecPredReg() { return predList.getReg(); }

    /** Gets a free cc register. */
    PhysRegIdPtr getCCReg() { return ccList.getReg(); }

    /** Adds a register back to the free list. */
    void addReg(PhysRegIdPtr freed_reg);

    /** Adds a register back to the free list. */
    template<class InputIt>
    void addRegs(InputIt first, InputIt last);

    /** Adds an integer register back to the free list. */
    void addIntReg(PhysRegIdPtr freed_reg) { intList.addReg(freed_reg); }

    /** Adds a fp register back to the free list. */
    void addFloatReg(PhysRegIdPtr freed_reg) { floatList.addReg(freed_reg); }

    /** Adds a vector register back to the free list. */
    void addVecReg(PhysRegIdPtr freed_reg) { vecList.addReg(freed_reg); }

    /** Adds a vector element register back to the free list. */
    void addVecElem(PhysRegIdPtr freed_reg) {
        vecElemList.addReg(freed_reg);
    }

    /** Adds a predicate register back to the free list. */
    void addVecPredReg(PhysRegIdPtr freed_reg) { predList.addReg(freed_reg); }

    /** Adds a cc register back to the free list. */
    void addCCReg(PhysRegIdPtr freed_reg) { ccList.addReg(freed_reg); }

    /** Checks if there are any free integer registers. */
    bool hasFreeIntRegs() const { return intList.hasFreeRegs(); }

    /** Checks if there are any free fp registers. */
    bool hasFreeFloatRegs() const { return floatList.hasFreeRegs(); }

    /** Checks if there are any free vector registers. */
    bool hasFreeVecRegs() const { return vecList.hasFreeRegs(); }

    /** Checks if there are any free vector registers. */
    bool hasFreeVecElems() const { return vecElemList.hasFreeRegs(); }

    /** Checks if there are any free predicate registers. */
    bool hasFreeVecPredRegs() const { return predList.hasFreeRegs(); }

    /** Checks if there are any free cc registers. */
    bool hasFreeCCRegs() const { return ccList.hasFreeRegs(); }

    /** Returns the number of free integer registers. */
    unsigned numFreeIntRegs() const { return intList.numFreeRegs(); }

    /** Returns the number of free fp registers. */
    unsigned numFreeFloatRegs() const { return floatList.numFreeRegs(); }

    /** Returns the number of free vector registers. */
    unsigned numFreeVecRegs() const { return vecList.numFreeRegs(); }

    /** Returns the number of free vector registers. */
    unsigned numFreeVecElems() const { return vecElemList.numFreeRegs(); }

    /** Returns the number of free predicate registers. */
    unsigned numFreeVecPredRegs() const { return predList.numFreeRegs(); }

    /** Returns the number of free cc registers. */
    unsigned numFreeCCRegs() const { return ccList.numFreeRegs(); }
};

template<class InputIt>
inline void
UnifiedFreeList::addRegs(InputIt first, InputIt last)
{
    // Are there any registers to add?
    if (first == last)
        return;

    panic_if((first != last) &&
            first->classValue() != (last-1)->classValue(),
            "Attempt to add mixed type regs: %s and %s",
            first->className(),
            (last-1)->className());
    switch (first->classValue()) {
        case IntRegClass:
            intList.addRegs(first, last);
            break;
        case FloatRegClass:
            floatList.addRegs(first, last);
            break;
        case VecRegClass:
            vecList.addRegs(first, last);
            break;
        case VecElemClass:
            vecElemList.addRegs(first, last);
            break;
        case VecPredRegClass:
            predList.addRegs(first, last);
            break;
        case CCRegClass:
            ccList.addRegs(first, last);
            break;
        default:
            panic("Unexpected RegClass (%s)",
                                   first->className());
    }

}

inline void
UnifiedFreeList::addReg(PhysRegIdPtr freed_reg)
{
    DPRINTF(FreeList,"Freeing register %i (%s).\n", freed_reg->index(),
            freed_reg->className());
    //Might want to add in a check for whether or not this register is
    //already in there.  A bit vector or something similar would be useful.
    switch (freed_reg->classValue()) {
        case IntRegClass:
            intList.addReg(freed_reg);
            break;
        case FloatRegClass:
            floatList.addReg(freed_reg);
            break;
        case VecRegClass:
            vecList.addReg(freed_reg);
            break;
        case VecElemClass:
            vecElemList.addReg(freed_reg);
            break;
        case VecPredRegClass:
            predList.addReg(freed_reg);
            break;
        case CCRegClass:
            ccList.addReg(freed_reg);
            break;
        default:
            panic("Unexpected RegClass (%s)",
                                   freed_reg->className());
    }

    // These assert conditions ensure that the number of free
    // registers are not more than the # of total Physical  Registers.
    // If this were false, it would mean that registers
    // have been freed twice, overflowing the free register
    // pool and potentially crashing SMT workloads.
    // ----
    // Comment out for now so as to not potentially break
    // CMP and single-threaded workloads
    // ----
    // assert(freeIntRegs.size() <= numPhysicalIntRegs);
    // assert(freeFloatRegs.size() <= numPhysicalFloatRegs);
}


#endif // __CPU_O3_FREE_LIST_HH__
