/*
 * Copyright (c) 2019-2021 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * For use for simulation and test purposes only
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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 __GPU_COMPUTE_OPERAND_INFO_HH__
#define __GPU_COMPUTE_OPERAND_INFO_HH__

#include "arch/gpu_registers.hh"
#include "base/flags.hh"
#include "config/the_gpu_isa.hh"

namespace gem5
{

class OperandInfo
{
  public:
    OperandInfo() = delete;
    OperandInfo(int opSelectorVal, int size, bool src, bool scalar_reg,
                bool vector_reg, bool imm)
        : _opSelectorVal(opSelectorVal), _size(size),
          _numDWords(size <= 4 ? 1 : size / 4)
    {
        if (src)
            flags.set(SRC);
        if (scalar_reg)
            flags.set(SCALAR_REG);
        if (vector_reg)
            flags.set(VECTOR_REG);
        if (imm)
            flags.set(IMMEDIATE);
        if (TheGpuISA::isVccReg(opSelectorVal))
            flags.set(VCC);
        if (TheGpuISA::isExecMask(opSelectorVal))
            flags.set(EXEC);
        if (TheGpuISA::isFlatScratchReg(opSelectorVal))
            flags.set(FLAT);
        if (TheGpuISA::isLiteral(opSelectorVal))
            flags.set(LITERAL);
        if (TheGpuISA::isConstVal(opSelectorVal))
            flags.set(CONSTANT);
        if (TheGpuISA::isPosConstVal(opSelectorVal))
            flags.set(POS_CONST);
    }

    int numRegisters() const { return _numDWords / TheGpuISA::RegSizeDWords; }
    int sizeInDWords() const { return _numDWords; }

    int size() const { return _size; }
    // Certain opIdx's get changed in calls to opSelectorToRegIdx
    // This avoids that by returning the exact value
    int rawRegisterIndex() const { return _opSelectorVal; }

    int
    registerIndex(int numScalarRegs) const
    {
      // Some regs (i.e. VSRC, VDST) are explicitly declared as vectors
      // as opposed to checking if it's a vector through a function call, so
      // they don't have an offset applied and can be returned immediately
      if (isVectorReg() && _opSelectorVal < TheGpuISA::REG_VGPR_MIN)
        return _opSelectorVal;
      return TheGpuISA::opSelectorToRegIdx(_opSelectorVal, numScalarRegs);
    }
    bool isSrc() const { return flags.isSet(SRC); }
    bool isDst() const { return !flags.isSet(SRC); }
    bool isImm() const { return flags.isSet(IMMEDIATE); }
    bool isScalarReg() const { return flags.isSet(SCALAR_REG); }
    bool isVectorReg() const { return flags.isSet(VECTOR_REG); }
    bool isVcc() const { return flags.isSet(VCC); }
    bool isExec() const { return flags.isSet(EXEC); }
    bool isFlatScratch() const { return flags.isSet(FLAT); }

    void
    setVirtToPhysMapping(std::vector<int> v, std::vector<int> p)
    {
        _virtIndices = v;
        _physIndices = p;

        assert(_virtIndices.size() == _physIndices.size());
        assert(_numDWords == _physIndices.size());
    }

    /**
     * We typically only need the first virtual register for the operand
     * regardless of its size.
     */
    int virtIdx(int reg_num=0) const { return _virtIndices.at(reg_num); }
    int physIdx(int reg_num=0) const { return _physIndices.at(reg_num); }

    const std::vector<int>&
    virtIndices() const
    {
        return _virtIndices;
    }

    const std::vector<int>&
    physIndices() const
    {
        return _physIndices;
    }

    std::vector<int>&
    bankReadCounts() const
    {
        return _bankReadCounts;
    }

    typedef uint32_t FlagsType;
    typedef gem5::Flags<FlagsType> Flags;

  private:

    enum : FlagsType {
        // If the operand is a src or not
        SRC                 = 0x00000001,

        // If the operand is a scalar or not
        SCALAR_REG          = 0x00000002,

        // If the operand is a vector or not
        VECTOR_REG          = 0x00000004,

        // If the operand is an immediate or not
        IMMEDIATE           = 0x00000008,

        // If the operand is a VCC register
        VCC                 = 0x00000010,

        // If the operand is an EXEC register
        EXEC                = 0x00000020,

        // If the operand is a FLAT/SCRATCH register
        FLAT                = 0x00000040,

        // If the operand is a literal
        LITERAL             = 0x00000080,

        // If the operand is a constant value
        CONSTANT            = 0x00000100,

        // If the constant is positive or negative
        POS_CONST           = 0x00000200
    };

    Flags flags;

    /**
     * Value of the operand as used in registers.cc functions
     */
    const int _opSelectorVal;

    /**
     * Size of the operand in bytes
     */
    const int _size;

    /**
     * Size of operand in DWords
     */
    const int _numDWords;

    std::vector<int> _virtIndices;
    std::vector<int> _physIndices;

    /**
     * The number of reads this operand will make to each bank.
     */
    mutable std::vector<int> _bankReadCounts;
};

} // namespace gem5

#endif // __GPU_COMPUTE_OPERAND_INFO_H__
