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

#include "dev/arm/gpu_nomali.hh"

#include "debug/NoMali.hh"
#include "dev/arm/base_gic.hh"
#include "dev/arm/realview.hh"
#include "enums/MemoryMode.hh"
#include "mem/packet_access.hh"
#include "nomali/lib/mali_midg_regmap.h"
#include "params/CustomNoMaliGpu.hh"
#include "params/NoMaliGpu.hh"

namespace gem5
{

static const std::map<enums::NoMaliGpuType, nomali_gpu_type_t> gpuTypeMap{
    { enums::T60x, NOMALI_GPU_T60X },
    { enums::T62x, NOMALI_GPU_T62X },
    { enums::T760, NOMALI_GPU_T760 },
};

NoMaliGpu::NoMaliGpu(const NoMaliGpuParams &p)
    : PioDevice(p),
      pioAddr(p.pio_addr),
      platform(p.platform),
      interruptMap{
          { NOMALI_INT_GPU, p.int_gpu },
          { NOMALI_INT_JOB, p.int_job },
          { NOMALI_INT_MMU, p.int_mmu },
      }
{
    if (nomali_api_version() != NOMALI_API_VERSION)
        panic("NoMali library API mismatch!\n");

    /* Setup the GPU configuration based on our param struct */
    nomali_config_t cfg;
    memset(&cfg, 0, sizeof(cfg));

    const auto it_gpu(gpuTypeMap.find(p.gpu_type));
    if (it_gpu == gpuTypeMap.end()) {
        fatal("Unrecognized GPU type: %s (%i)\n",
              enums::NoMaliGpuTypeStrings[p.gpu_type], p.gpu_type);
    }
    cfg.type = it_gpu->second;

    cfg.ver_maj = p.ver_maj;
    cfg.ver_min = p.ver_min;
    cfg.ver_status = p.ver_status;

    panicOnErr(
        nomali_create(&nomali, &cfg),
        "Failed to instantiate NoMali");


    /* Setup an interrupt callback */
    nomali_callback_t cbk_int;
    cbk_int.type = NOMALI_CALLBACK_INT;
    cbk_int.usr = (void *)this;
    cbk_int.func.interrupt = NoMaliGpu::_interrupt;
    setCallback(cbk_int);

    /* Setup a reset callback */
    nomali_callback_t cbk_rst;
    cbk_rst.type = NOMALI_CALLBACK_RESET;
    cbk_rst.usr = (void *)this;
    cbk_rst.func.reset = NoMaliGpu::_reset;
    setCallback(cbk_rst);

    panicOnErr(
        nomali_get_info(nomali, &nomaliInfo),
        "Failed to get NoMali information struct");
}

NoMaliGpu::~NoMaliGpu()
{
    nomali_destroy(nomali);
}


void
NoMaliGpu::init()
{
    PioDevice::init();

    /* Reset the GPU here since the reset callback won't have been
     * installed when the GPU was reset at instantiation time.
     */
    reset();
}

void
NoMaliGpu::serialize(CheckpointOut &cp) const
{
    std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2);

    for (int i = 0; i < nomaliInfo.reg_size; i += 4)
        regs[i >> 2] = readRegRaw(i);

    SERIALIZE_CONTAINER(regs);
}

void
NoMaliGpu::unserialize(CheckpointIn &cp)
{
    std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2);

    UNSERIALIZE_CONTAINER(regs);

    for (int i = 0; i < nomaliInfo.reg_size; i += 4)
        writeRegRaw(i, regs[i >> 2]);
}

Tick
NoMaliGpu::read(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr);
    const Addr addr(pkt->getAddr() - pioAddr);
    const unsigned size(pkt->getSize());

    if (addr + size >= nomaliInfo.reg_size)
        panic("GPU register '0x%x' out of range!\n", addr);

    if (size != 4)
        panic("Unexpected GPU register read size: %i\n", size);
    else if (addr & 0x3)
        panic("Unaligned GPU read: %i\n", size);

    pkt->setLE<uint32_t>(readReg(addr));
    pkt->makeResponse();

    return 0;
}

Tick
NoMaliGpu::write(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr);
    const Addr addr(pkt->getAddr() - pioAddr);
    const unsigned size(pkt->getSize());

    if (addr + size >= nomaliInfo.reg_size)
        panic("GPU register '0x%x' out of range!\n", addr);

    if (size != 4)
        panic("Unexpected GPU register write size: %i\n", size);
    else if (addr & 0x3)
        panic("Unaligned GPU write: %i\n", size);

    writeReg(addr, pkt->getLE<uint32_t>());
    pkt->makeAtomicResponse();

    return 0;
}

AddrRangeList
NoMaliGpu::getAddrRanges() const
{
    return AddrRangeList({ RangeSize(pioAddr, nomaliInfo.reg_size) });
}

void
NoMaliGpu::reset()
{
    DPRINTF(NoMali, "reset()\n");

    panicOnErr(
        nomali_reset(nomali),
        "Failed to reset GPU");
}

uint32_t
NoMaliGpu::readReg(nomali_addr_t reg)
{
    uint32_t value;

    panicOnErr(
        nomali_reg_read(nomali, &value, reg),
        "GPU register read failed");

    DPRINTF(NoMali, "readReg(0x%x): 0x%x\n",
            reg, value);

    return value;
}


void
NoMaliGpu::writeReg(nomali_addr_t reg, uint32_t value)
{
    DPRINTF(NoMali, "writeReg(0x%x, 0x%x)\n",
            reg, value);

    panicOnErr(
        nomali_reg_write(nomali, reg, value),
        "GPU register write failed");
}

uint32_t
NoMaliGpu::readRegRaw(nomali_addr_t reg) const
{
    uint32_t value;

    panicOnErr(
        nomali_reg_read_raw(nomali, &value, reg),
        "GPU raw register read failed");

    return value;
}


void
NoMaliGpu::writeRegRaw(nomali_addr_t reg, uint32_t value)
{
    panicOnErr(
        nomali_reg_write_raw(nomali, reg, value),
        "GPU raw register write failed");
}

bool
NoMaliGpu::intState(nomali_int_t intno)
{
    int state = 0;
    panicOnErr(
        nomali_int_state(nomali, &state, intno),
        "Failed to get interrupt state");

    return !!state;
}

void
NoMaliGpu::gpuPanic(nomali_error_t err, const char *msg)
{
    panic("%s: %s\n", msg, nomali_errstr(err));
}


void
NoMaliGpu::onInterrupt(nomali_int_t intno, bool set)
{
    const auto it_int(interruptMap.find(intno));
    if (it_int == interruptMap.end())
        panic("Unhandled interrupt from NoMali: %i\n", intno);

    DPRINTF(NoMali, "Interrupt %i->%i: %i\n",
            intno, it_int->second, set);

    assert(platform);
    assert(platform->gic);

    if (set)
        platform->gic->sendInt(it_int->second);
    else
        platform->gic->clearInt(it_int->second);
}

void
NoMaliGpu::onReset()
{
    DPRINTF(NoMali, "Reset\n");
}

void
NoMaliGpu::setCallback(const nomali_callback_t &callback)
{
    DPRINTF(NoMali, "Registering callback %i\n",
            callback.type);

    panicOnErr(
        nomali_set_callback(nomali, &callback),
        "Failed to register callback");
}

void
NoMaliGpu::_interrupt(nomali_handle_t h, void *usr,
                      nomali_int_t intno, int set)
{
    NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr));

    _this->onInterrupt(intno, !!set);
}

void
NoMaliGpu::_reset(nomali_handle_t h, void *usr)
{
    NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr));

    _this->onReset();
}


CustomNoMaliGpu::CustomNoMaliGpu(const CustomNoMaliGpuParams &p)
    : NoMaliGpu(p),
      idRegs{
        { GPU_CONTROL_REG(GPU_ID), p.gpu_id },
        { GPU_CONTROL_REG(L2_FEATURES), p.l2_features },
        { GPU_CONTROL_REG(TILER_FEATURES), p.tiler_features },
        { GPU_CONTROL_REG(MEM_FEATURES), p.mem_features },
        { GPU_CONTROL_REG(MMU_FEATURES), p.mmu_features },
        { GPU_CONTROL_REG(AS_PRESENT), p.as_present },
        { GPU_CONTROL_REG(JS_PRESENT), p.js_present },

        { GPU_CONTROL_REG(THREAD_MAX_THREADS), p.thread_max_threads },
        { GPU_CONTROL_REG(THREAD_MAX_WORKGROUP_SIZE),
          p.thread_max_workgroup_size },
        { GPU_CONTROL_REG(THREAD_MAX_BARRIER_SIZE),
          p.thread_max_barrier_size },
        { GPU_CONTROL_REG(THREAD_FEATURES), p.thread_features },

        { GPU_CONTROL_REG(SHADER_PRESENT_LO), bits(p.shader_present, 31, 0) },
        { GPU_CONTROL_REG(SHADER_PRESENT_HI), bits(p.shader_present, 63, 32) },
        { GPU_CONTROL_REG(TILER_PRESENT_LO), bits(p.tiler_present, 31, 0) },
        { GPU_CONTROL_REG(TILER_PRESENT_HI), bits(p.tiler_present, 63, 32) },
        { GPU_CONTROL_REG(L2_PRESENT_LO), bits(p.l2_present, 31, 0) },
        { GPU_CONTROL_REG(L2_PRESENT_HI), bits(p.l2_present, 63, 32) },
      }
{
    fatal_if(p.texture_features.size() > 3,
             "Too many texture feature registers specified (%i)\n",
             p.texture_features.size());

    fatal_if(p.js_features.size() > 16,
             "Too many job slot feature registers specified (%i)\n",
             p.js_features.size());

    for (int i = 0; i < p.texture_features.size(); i++)
        idRegs[TEXTURE_FEATURES_REG(i)] = p.texture_features[i];

    for (int i = 0; i < p.js_features.size(); i++)
        idRegs[JS_FEATURES_REG(i)] = p.js_features[i];
}

CustomNoMaliGpu::~CustomNoMaliGpu()
{
}

void
CustomNoMaliGpu::onReset()
{
    NoMaliGpu::onReset();

    for (const auto &reg : idRegs)
        writeRegRaw(reg.first, reg.second);
}

} // namespace gem5
