/*
 * Copyright (c) 2013, 2018-2019 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/smmu_v3_proc.hh"

#include "dev/arm/smmu_v3.hh"
#include "sim/system.hh"

SMMUProcess::SMMUProcess(const std::string &name, SMMUv3 &_smmu) :
    coroutine(NULL),
    myName(name),
    smmu(_smmu)
{}

SMMUProcess::~SMMUProcess()
{
    delete coroutine;
}

void
SMMUProcess::wakeup()
{
    smmu.runProcess(this, NULL);
}

void
SMMUProcess::reinit()
{
    delete coroutine;
    coroutine = new Coroutine(
        std::bind(&SMMUProcess::main, this, std::placeholders::_1));
}

void
SMMUProcess::doRead(Yield &yield, Addr addr, void *ptr, size_t size)
{
    doSemaphoreDown(yield, smmu.masterPortSem);
    doDelay(yield, Cycles(1)); // request - assume 1 cycle
    doSemaphoreUp(smmu.masterPortSem);

    SMMUAction a;
    a.type = ACTION_SEND_REQ;

    RequestPtr req = std::make_shared<Request>(
        addr, size, 0, smmu.masterId);

    req->taskId(ContextSwitchTaskId::DMA);

    a.pkt = new Packet(req, MemCmd::ReadReq);
    a.pkt->dataStatic(ptr);

    a.delay = 0;

    PacketPtr pkt = yield(a).get();

    assert(pkt);
    // >= because we may get the whole cache line
    assert(pkt->getSize() >= size);

    delete pkt;
}

void
SMMUProcess::doWrite(Yield &yield, Addr addr, const void *ptr, size_t size)
{
    unsigned nbeats = (size + (smmu.masterPortWidth-1)) / smmu.masterPortWidth;

    doSemaphoreDown(yield, smmu.masterPortSem);
    doDelay(yield, Cycles(nbeats));
    doSemaphoreUp(smmu.masterPortSem);


    SMMUAction a;
    a.type = ACTION_SEND_REQ;

    RequestPtr req = std::make_shared<Request>(
        addr, size, 0, smmu.masterId);

    req->taskId(ContextSwitchTaskId::DMA);

    a.pkt = new Packet(req, MemCmd::WriteReq);
    a.pkt->dataStatic(ptr);

    PacketPtr pkt = yield(a).get();

    delete pkt;
}

void
SMMUProcess::doDelay(Yield &yield, Cycles cycles)
{
    if (smmu.system.isTimingMode())
        scheduleWakeup(smmu.clockEdge(cycles));

    SMMUAction a;
    a.type = ACTION_DELAY;
    a.delay = cycles * smmu.clockPeriod();
    yield(a);
}

void
SMMUProcess::doSleep(Yield &yield)
{
    SMMUAction a;
    a.type = ACTION_SLEEP;
    yield(a);
}

void
SMMUProcess::doSemaphoreDown(Yield &yield, SMMUSemaphore &sem)
{
    while (sem.count == 0) {
        sem.queue.push(this);
        doSleep(yield);
    }

    sem.count--;
    return;
}

void
SMMUProcess::doSemaphoreUp(SMMUSemaphore &sem)
{
    sem.count++;
    if (!sem.queue.empty()) {
        SMMUProcess *next_proc = sem.queue.front();
        sem.queue.pop();

        // Schedule event in the current tick instead of
        // calling the function directly to avoid overflowing
        // the stack in this coroutine.
        next_proc->scheduleWakeup(curTick());
    }
}

void
SMMUProcess::doWaitForSignal(Yield &yield, SMMUSignal &sig)
{
    sig.waiting.push_back(this);
    doSleep(yield);
}

void
SMMUProcess::doBroadcastSignal(SMMUSignal &sig)
{
    if (!sig.waiting.empty()) {
        for (auto it : sig.waiting) {
            // Schedule event in the current tick instead of
            // calling the function directly to avoid overflowing
            // the stack in this coroutine.
            it->scheduleWakeup(curTick());
        }

        sig.waiting.clear();
    }
}

void
SMMUProcess::scheduleWakeup(Tick when)
{
    auto *ep = new EventWrapper<
        SMMUProcess, &SMMUProcess::wakeup> (this, true);

    smmu.schedule(ep, when);
}

SMMUAction
SMMUProcess::run(PacketPtr pkt)
{
    assert(coroutine != NULL);
    assert(*coroutine);
    return (*coroutine)(pkt).get();
}
