/*
 * 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.
 */

#ifndef __CPU_O3_REGFILE_HH__
#define __CPU_O3_REGFILE_HH__

#include <vector>

#include "arch/generic/isa.hh"
#include "arch/vecregs.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
#include "cpu/o3/comm.hh"
#include "debug/IEW.hh"

namespace gem5
{

namespace o3
{

class UnifiedFreeList;

/**
 * Simple physical register file class.
 */
class PhysRegFile
{
  private:

    using PhysIds = std::vector<PhysRegId>;
  public:
    using IdRange = std::pair<PhysIds::iterator,
                              PhysIds::iterator>;
  private:
    /** Integer register file. */
    std::vector<RegVal> intRegFile;
    std::vector<PhysRegId> intRegIds;
    RegId zeroReg;

    /** Floating point register file. */
    std::vector<RegVal> floatRegFile;
    std::vector<PhysRegId> floatRegIds;

    /** Vector register file. */
    std::vector<TheISA::VecRegContainer> vectorRegFile;
    std::vector<PhysRegId> vecRegIds;

    /** Vector element register file. */
    std::vector<RegVal> vectorElemRegFile;
    std::vector<PhysRegId> vecElemIds;

    /** Predicate register file. */
    std::vector<TheISA::VecPredRegContainer> vecPredRegFile;
    std::vector<PhysRegId> vecPredRegIds;

    /** Condition-code register file. */
    std::vector<RegVal> ccRegFile;
    std::vector<PhysRegId> ccRegIds;

    /** Misc Reg Ids */
    std::vector<PhysRegId> miscRegIds;

    /**
     * Number of physical general purpose registers
     */
    unsigned numPhysicalIntRegs;

    /**
     * Number of physical floating point registers
     */
    unsigned numPhysicalFloatRegs;

    /**
     * Number of physical vector registers
     */
    unsigned numPhysicalVecRegs;

    /**
     * Number of physical vector element registers
     */
    unsigned numPhysicalVecElemRegs;

    /**
     * Number of physical predicate registers
     */
    unsigned numPhysicalVecPredRegs;

    /**
     * Number of physical CC registers
     */
    unsigned numPhysicalCCRegs;

    /** Total number of physical registers. */
    unsigned totalNumRegs;

  public:
    /**
     * Constructs a physical register file with the specified amount of
     * integer and floating point registers.
     */
    PhysRegFile(unsigned _numPhysicalIntRegs,
                unsigned _numPhysicalFloatRegs,
                unsigned _numPhysicalVecRegs,
                unsigned _numPhysicalVecPredRegs,
                unsigned _numPhysicalCCRegs,
                const BaseISA::RegClasses &regClasses);

    /**
     * Destructor to free resources
     */
    ~PhysRegFile() {}

    /** Initialize the free list */
    void initFreeList(UnifiedFreeList *freeList);

    /** @return the number of integer physical registers. */
    unsigned numIntPhysRegs() const { return numPhysicalIntRegs; }

    /** @return the number of floating-point physical registers. */
    unsigned numFloatPhysRegs() const { return numPhysicalFloatRegs; }
    /** @return the number of vector physical registers. */
    unsigned numVecPhysRegs() const { return numPhysicalVecRegs; }
    /** @return the number of predicate physical registers. */
    unsigned numPredPhysRegs() const { return numPhysicalVecPredRegs; }

    /** @return the number of vector physical registers. */
    unsigned numVecElemPhysRegs() const { return numPhysicalVecElemRegs; }

    /** @return the number of condition-code physical registers. */
    unsigned numCCPhysRegs() const { return numPhysicalCCRegs; }

    /** @return the total number of physical registers. */
    unsigned totalNumPhysRegs() const { return totalNumRegs; }

    /** Gets a misc register PhysRegIdPtr. */
    PhysRegIdPtr getMiscRegId(RegIndex reg_idx) {
        return &miscRegIds[reg_idx];
    }

    /** Reads an integer register. */
    RegVal
    readIntReg(PhysRegIdPtr phys_reg) const
    {
        assert(phys_reg->is(IntRegClass));

        DPRINTF(IEW, "RegFile: Access to int register %i, has data "
                "%#x\n", phys_reg->index(), intRegFile[phys_reg->index()]);
        return intRegFile[phys_reg->index()];
    }

    RegVal
    readFloatReg(PhysRegIdPtr phys_reg) const
    {
        assert(phys_reg->is(FloatRegClass));

        RegVal floatRegBits = floatRegFile[phys_reg->index()];

        DPRINTF(IEW, "RegFile: Access to float register %i as int, "
                "has data %#x\n", phys_reg->index(), floatRegBits);

        return floatRegBits;
    }

    /** Reads a vector register. */
    const TheISA::VecRegContainer &
    readVecReg(PhysRegIdPtr phys_reg) const
    {
        assert(phys_reg->is(VecRegClass));

        DPRINTF(IEW, "RegFile: Access to vector register %i, has "
                "data %s\n", int(phys_reg->index()),
                vectorRegFile[phys_reg->index()]);

        return vectorRegFile[phys_reg->index()];
    }

    /** Reads a vector register for modification. */
    TheISA::VecRegContainer &
    getWritableVecReg(PhysRegIdPtr phys_reg)
    {
        /* const_cast for not duplicating code above. */
        return const_cast<TheISA::VecRegContainer&>(readVecReg(phys_reg));
    }

    /** Reads a vector element. */
    RegVal
    readVecElem(PhysRegIdPtr phys_reg) const
    {
        assert(phys_reg->is(VecElemClass));
        RegVal val = vectorElemRegFile[
                phys_reg->index() * TheISA::NumVecElemPerVecReg +
                phys_reg->elemIndex()];
        DPRINTF(IEW, "RegFile: Access to element %d of vector register %i,"
                " has data %#x\n", phys_reg->elemIndex(),
                phys_reg->index(), val);

        return val;
    }

    /** Reads a predicate register. */
    const TheISA::VecPredRegContainer&
    readVecPredReg(PhysRegIdPtr phys_reg) const
    {
        assert(phys_reg->is(VecPredRegClass));

        DPRINTF(IEW, "RegFile: Access to predicate register %i, has "
                "data %s\n", int(phys_reg->index()),
                vecPredRegFile[phys_reg->index()]);

        return vecPredRegFile[phys_reg->index()];
    }

    TheISA::VecPredRegContainer&
    getWritableVecPredReg(PhysRegIdPtr phys_reg)
    {
        /* const_cast for not duplicating code above. */
        return const_cast<TheISA::VecPredRegContainer&>(
                readVecPredReg(phys_reg));
    }

    /** Reads a condition-code register. */
    RegVal
    readCCReg(PhysRegIdPtr phys_reg)
    {
        assert(phys_reg->is(CCRegClass));

        DPRINTF(IEW, "RegFile: Access to cc register %i, has "
                "data %#x\n", phys_reg->index(),
                ccRegFile[phys_reg->index()]);

        return ccRegFile[phys_reg->index()];
    }

    /** Sets an integer register to the given value. */
    void
    setIntReg(PhysRegIdPtr phys_reg, RegVal val)
    {
        assert(phys_reg->is(IntRegClass));

        DPRINTF(IEW, "RegFile: Setting int register %i to %#x\n",
                phys_reg->index(), val);

        if (phys_reg->index() != zeroReg.index())
            intRegFile[phys_reg->index()] = val;
    }

    void
    setFloatReg(PhysRegIdPtr phys_reg, RegVal val)
    {
        assert(phys_reg->is(FloatRegClass));

        DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n",
                phys_reg->index(), (uint64_t)val);

        floatRegFile[phys_reg->index()] = val;
    }

    /** Sets a vector register to the given value. */
    void
    setVecReg(PhysRegIdPtr phys_reg, const TheISA::VecRegContainer& val)
    {
        assert(phys_reg->is(VecRegClass));

        DPRINTF(IEW, "RegFile: Setting vector register %i to %s\n",
                int(phys_reg->index()), val);

        vectorRegFile[phys_reg->index()] = val;
    }

    /** Sets a vector register to the given value. */
    void
    setVecElem(PhysRegIdPtr phys_reg, RegVal val)
    {
        assert(phys_reg->is(VecElemClass));

        DPRINTF(IEW, "RegFile: Setting element %d of vector register %i to"
                " %#x\n", phys_reg->elemIndex(), int(phys_reg->index()), val);

        vectorElemRegFile[phys_reg->index() * TheISA::NumVecElemPerVecReg +
                phys_reg->elemIndex()] = val;
    }

    /** Sets a predicate register to the given value. */
    void
    setVecPredReg(PhysRegIdPtr phys_reg,
            const TheISA::VecPredRegContainer& val)
    {
        assert(phys_reg->is(VecPredRegClass));

        DPRINTF(IEW, "RegFile: Setting predicate register %i to %s\n",
                int(phys_reg->index()), val);

        vecPredRegFile[phys_reg->index()] = val;
    }

    /** Sets a condition-code register to the given value. */
    void
    setCCReg(PhysRegIdPtr phys_reg, RegVal val)
    {
        assert(phys_reg->is(CCRegClass));

        DPRINTF(IEW, "RegFile: Setting cc register %i to %#x\n",
                phys_reg->index(), (uint64_t)val);

        ccRegFile[phys_reg->index()] = val;
    }

    /**
     * Get the PhysRegIds of the elems of all vector registers.
     * Auxiliary function to transition from Full vector mode to Elem mode
     * and to initialise the rename map.
     */
    IdRange getRegIds(RegClassType cls);

    /**
     * Get the true physical register id.
     * As many parts work with PhysRegIdPtr, we need to be able to produce
     * the pointer out of just class and register idx.
     */
    PhysRegIdPtr getTrueId(PhysRegIdPtr reg);
};

} // namespace o3
} // namespace gem5

#endif //__CPU_O3_REGFILE_HH__
