/*
 * Copyright (c) 2015 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.
 */

#include "gpu-compute/gpu_static_inst.hh"

#include "debug/GPUInst.hh"

namespace gem5
{

GPUStaticInst::GPUStaticInst(const std::string &opcode)
    : executed_as(enums::SC_NONE), _opcode(opcode),
      _instNum(0), _instAddr(0), srcVecDWords(-1), dstVecDWords(-1),
      srcScalarDWords(-1), dstScalarDWords(-1), maxOpSize(-1)
{
}

const std::string&
GPUStaticInst::disassemble()
{
    if (disassembly.empty()) {
        generateDisassembly();
        assert(!disassembly.empty());
    }

    return disassembly;
}

void
GPUStaticInst::initDynOperandInfo(Wavefront *wf, ComputeUnit *cu)
{
    // Lambda function, as this is only ever used here
    auto generateVirtToPhysMap = [&](OperandInfo& op,
                                     std::vector<OperandInfo>& opVec,
                                     MapRegFn mapFn, OpType opType)
    {
        std::vector<int> virt_idxs;
        std::vector<int> phys_idxs;

        int num_dwords = op.sizeInDWords();
        int virt_idx = op.registerIndex(wf->reservedScalarRegs);

        int phys_idx = -1;
        for (int i = 0; i < num_dwords; i++){
            phys_idx = (cu->registerManager->*mapFn)(wf, virt_idx + i);
            virt_idxs.push_back(virt_idx + i);
            phys_idxs.push_back(phys_idx);
        }
        DPRINTF(GPUInst, "%s adding %s %s (%d->%d) operand that uses "
                "%d registers.\n", disassemble(),
                (opType == OpType::SRC_VEC || opType == OpType::DST_VEC) ?
                "vector" : "scalar",
                (opType == OpType::SRC_VEC || opType == OpType::SRC_SCALAR) ?
                "src" : "dst", virt_idxs[0], phys_idxs[0], num_dwords);

        op.setVirtToPhysMapping(virt_idxs, phys_idxs);

        opVec.emplace_back(op);
    };

    for (auto& srcOp : srcOps) {
        if (srcOp.isVectorReg()) {
            generateVirtToPhysMap(srcOp, srcVecRegOps,
                            &RegisterManager::mapVgpr, OpType::SRC_VEC);
        } else if (srcOp.isScalarReg()) {
            generateVirtToPhysMap(srcOp, srcScalarRegOps,
                            &RegisterManager::mapSgpr, OpType::SRC_SCALAR);
        }
    }

    for (auto& dstOp : dstOps) {
        if (dstOp.isVectorReg()) {
            generateVirtToPhysMap(dstOp, dstVecRegOps,
                            &RegisterManager::mapVgpr, OpType::DST_VEC);
        } else if (dstOp.isScalarReg()) {
            generateVirtToPhysMap(dstOp, dstScalarRegOps,
                            &RegisterManager::mapSgpr, OpType::DST_SCALAR);
        }
    }
}

int
GPUStaticInst::numSrcVecOperands()
{
    return srcVecRegOps.size();
}

int
GPUStaticInst::numDstVecOperands()
{
    return dstVecRegOps.size();
}

int
GPUStaticInst::numSrcVecDWords()
{
    if (srcVecDWords != -1) {
        return srcVecDWords;
    }

    srcVecDWords = 0;

    for (const auto& srcOp : srcOps)
        if (srcOp.isVectorReg())
            srcVecDWords += srcOp.sizeInDWords();

    return srcVecDWords;
}

int
GPUStaticInst::numDstVecDWords()
{
    if (dstVecDWords != -1) {
        return dstVecDWords;
    }

    dstVecDWords = 0;

    for (const auto& dstOp : dstOps)
        if (dstOp.isVectorReg())
            dstVecDWords += dstOp.sizeInDWords();

    return dstVecDWords;
}

int
GPUStaticInst::numSrcScalarOperands()
{
    return srcScalarRegOps.size();
}

int
GPUStaticInst::numDstScalarOperands()
{
    return dstScalarRegOps.size();
}

int
GPUStaticInst::numSrcScalarDWords()
{
    if (srcScalarDWords != -1)
        return srcScalarDWords;

    srcScalarDWords = 0;

    for (const auto& srcOp : srcOps)
        if (srcOp.isScalarReg())
            srcScalarDWords += srcOp.sizeInDWords();

    return srcScalarDWords;
}

int
GPUStaticInst::numDstScalarDWords()
{
    if (dstScalarDWords != -1)
        return dstScalarDWords;

    dstScalarDWords = 0;

    for (const auto& dstOp : dstOps)
        if (dstOp.isScalarReg())
            dstScalarDWords += dstOp.sizeInDWords();

    return dstScalarDWords;
}

int
GPUStaticInst::maxOperandSize()
{
    if (maxOpSize != -1)
        return maxOpSize;

    maxOpSize = 0;

    for (const auto& dstOp : dstOps)
        if (dstOp.size() > maxOpSize)
            maxOpSize = dstOp.size();

    for (const auto& srcOp : srcOps)
        if (srcOp.size() > maxOpSize)
            maxOpSize = srcOp.size();

    return maxOpSize;
}

} // namespace gem5
