/*
 * Copyright (c) 2014-2016 ARM Limited
 * All rights reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Authors: Andreas Sandberg
 */

#include "jobslot.hh"

#include <cassert>
#include <cstdlib>

#include "jobcontrol.hh"
#include "gpu.hh"
#include "regutils.hh"

namespace NoMali {

static const Status STATUS_IDLE(Status::CLASS_NOFAULT, 0, 0);
static const Status STATUS_DONE(Status::CLASS_NOFAULT, 0, 1);
static const Status STATUS_ACTIVE(Status::CLASS_NOFAULT, 1, 0);

const std::vector<JobSlot::cmd_t> JobSlot::cmds {
    &JobSlot::cmdNop,                      // JSn_COMMAND_NOP
    &JobSlot::cmdStart,                    // JSn_COMMAND_START
    &JobSlot::cmdSoftStop,                 // JSn_COMMAND_SOFT_STOP
    &JobSlot::cmdHardStop,                 // JSn_COMMAND_HARD_STOP
    &JobSlot::cmdSoftStop0,                // JSn_COMMAND_SOFT_STOP_0
    &JobSlot::cmdHardStop0,                // JSn_COMMAND_HARD_STOP_0
    &JobSlot::cmdSoftStop1,                // JSn_COMMAND_SOFT_STOP_1
    &JobSlot::cmdHardStop1,                // JSn_COMMAND_HARD_STOP_1
};

JobSlot::JobSlot(GPU &_gpu, JobControl &_jc, uint8_t _id)
    : GPUBlock(_gpu, JSn_NO_REGS),
      id(_id),
      jc(_jc)
{
}

JobSlot::JobSlot(JobSlot &&rhs)
    : GPUBlock(std::move(rhs)),
      id(std::move(rhs.id)),
      jc(rhs.jc)
{
}

JobSlot::~JobSlot()
{
}

void
JobSlot::writeReg(RegAddr addr, uint32_t value)
{
    switch (addr.value) {
      case JSn_COMMAND:
        jobCommand(value);
        break;

      case JSn_COMMAND_NEXT:
        regs[addr] = value;
        tryStart();
        break;

      case JSn_HEAD_NEXT_LO:
      case JSn_HEAD_NEXT_HI:
      case JSn_AFFINITY_NEXT_LO:
      case JSn_AFFINITY_NEXT_HI:
      case JSn_CONFIG_NEXT:
        GPUBlock::writeReg(addr, value);
        break;

      default:
        // Ignore writes by default
        break;
    };
}

bool
JobSlot::active() const
{
    return false;
}

bool
JobSlot::activeNext() const
{
    return regs[RegAddr(JSn_COMMAND_NEXT)] == JSn_COMMAND_START;
}

void
JobSlot::tryStart()
{
    // Only actually start something if the next command is start
    if (regs[RegAddr(JSn_COMMAND_NEXT)] != JSn_COMMAND_START )
        return;

    // Reset the status register
    regs[RegAddr(JSn_STATUS)] = STATUS_ACTIVE.value;

    // Transfer the next job configuration to the active job
    // configuration
    regs.set64(RegAddr(JSn_HEAD_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO)));
    regs.set64(RegAddr(JSn_TAIL_LO), regs.get64(RegAddr(JSn_HEAD_NEXT_LO)));
    regs.set64(RegAddr(JSn_AFFINITY_LO),
               regs.get64(RegAddr(JSn_AFFINITY_NEXT_LO)));
    regs[RegAddr(JSn_CONFIG)] = regs[RegAddr(JSn_CONFIG_NEXT)];

    // Reset the next job configuration
    regs.set64(RegAddr(JSn_HEAD_NEXT_LO), 0);
    regs[RegAddr(JSn_COMMAND_NEXT)] = 0;

    runJob();
}

void
JobSlot::runJob()
{
    exitJob(STATUS_DONE,
            0); // Time stamp counter value
}

void
JobSlot::exitJob(Status status, uint64_t fault_address)
{
    assert(status.statusClass() == Status::CLASS_NOFAULT ||
           status.statusClass() == Status::CLASS_JOB);

    regs[RegAddr(JSn_STATUS)] = status.value;

    if (status.statusClass() == Status::CLASS_NOFAULT) {
        jc.jobDone(id);
    } else {
        jc.jobFailed(id);
    }
}

void
JobSlot::jobCommand(uint32_t cmd)
{
    if (cmd < cmds.size())
        (this->*cmds[cmd])(cmd);
}

void
JobSlot::cmdNop(uint32_t cmd)
{
    assert(cmd == JSn_COMMAND_NOP);
}

void
JobSlot::cmdStart(uint32_t cmd)
{
    assert(cmd == JSn_COMMAND_START);
    // The JSn_COMMAND_START should never be issued through the
    // JSn_COMMAND register. It should use the JSn_COMMAND_NEXT
    // register instead.
    abort();
}

void
JobSlot::cmdSoftStop(uint32_t cmd)
{
    assert(cmd == JSn_COMMAND_SOFT_STOP ||
           cmd == JSn_COMMAND_SOFT_STOP_0 ||
           cmd == JSn_COMMAND_SOFT_STOP_1);
}

void
JobSlot::cmdHardStop(uint32_t cmd)
{
    assert(cmd == JSn_COMMAND_HARD_STOP ||
           cmd == JSn_COMMAND_HARD_STOP_0 ||
           cmd == JSn_COMMAND_HARD_STOP_1);
}

void
JobSlot::cmdSoftStop0(uint32_t cmd)
{
    if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG))
        cmdSoftStop(cmd);
}

void
JobSlot::cmdHardStop0(uint32_t cmd)
{
    if (!(regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG))
        cmdHardStop(cmd);
}

void
JobSlot::cmdSoftStop1(uint32_t cmd)
{
    if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)
        cmdSoftStop(cmd);
}

void
JobSlot::cmdHardStop1(uint32_t cmd)
{
    if (regs[RegAddr(JSn_CONFIG)] & JSn_CONFIG_JOB_CHAIN_FLAG)
        cmdHardStop(cmd);
}

}
