/*
 * 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.
 *
 * Authors: Stan Czerniawski
 */

#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();
}
