/*
 * Copyright (c) 2017-2021 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 "cpu/testers/gpu_ruby_test/tester_thread.hh"

#include <fstream>

#include "debug/ProtocolTest.hh"

namespace gem5
{

TesterThread::TesterThread(const Params &p)
      : ClockedObject(p),
        threadEvent(this, "TesterThread tick"),
        deadlockCheckEvent(this),
        threadId(p.thread_id),
        numLanes(p.num_lanes),
        tester(nullptr), addrManager(nullptr), port(nullptr),
        scalarPort(nullptr), sqcPort(nullptr), curEpisode(nullptr),
        curAction(nullptr), pendingLdStCount(0), pendingFenceCount(0),
        pendingAtomicCount(0), lastActiveCycle(Cycles(0)),
        deadlockThreshold(p.deadlock_threshold)
{
}

TesterThread::~TesterThread()
{
    for (auto ep : episodeHistory) {
        assert(ep != nullptr);
        delete ep;
    }
}

void
TesterThread::wakeup()
{
    // this thread is waken up by one of the following events
    //      - hitCallback is called
    //      - a new episode is created

    // check if this is the first episode in this thread
    if (curEpisode == nullptr) {
        issueNewEpisode();
        assert(curEpisode);
    }

    if (isNextActionReady()) {
        // isNextActionReady should check if the action list is empty
        assert(curAction != nullptr);

        // issue the next action
        issueNextAction();
    } else {
        // check for completion of the current episode
        // completion = no outstanding requests + not having more actions
        if (!curEpisode->hasMoreActions() &&
            pendingLdStCount == 0 &&
            pendingFenceCount == 0 &&
            pendingAtomicCount == 0) {

            curEpisode->completeEpisode();

            // check if it's time to stop the tester
            if (tester->checkExit()) {
                // no more event is scheduled for this thread
                return;
            }

            // issue the next episode
            issueNewEpisode();
            assert(curEpisode);

            // now we get a new episode
            // let's wake up the thread in the next cycle
            if (!threadEvent.scheduled()) {
                scheduleWakeup();
            }
        }
    }
}

void
TesterThread::scheduleWakeup()
{
    assert(!threadEvent.scheduled());
    schedule(threadEvent, nextCycle());
}

void
TesterThread::scheduleDeadlockCheckEvent()
{
    // after this first schedule, the deadlock event is scheduled by itself
    assert(!deadlockCheckEvent.scheduled());
    schedule(deadlockCheckEvent, nextCycle());
}

void
TesterThread::attachTesterThreadToPorts(ProtocolTester *_tester,
                            ProtocolTester::SeqPort *_port,
                            ProtocolTester::GMTokenPort *_tokenPort,
                            ProtocolTester::SeqPort *_scalarPort,
                            ProtocolTester::SeqPort *_sqcPort)
{
    tester = _tester;
    port = _port;
    tokenPort = _tokenPort;
    scalarPort = _scalarPort;
    sqcPort = _sqcPort;

    assert(tester && port);
    addrManager = tester->getAddressManager();
    assert(addrManager);
}

void
TesterThread::issueNewEpisode()
{
    int num_reg_loads = random() % tester->getEpisodeLength();
    int num_reg_stores = tester->getEpisodeLength() - num_reg_loads;

    // create a new episode
    curEpisode = new Episode(tester, this, num_reg_loads, num_reg_stores);
    episodeHistory.push_back(curEpisode);
}

bool
TesterThread::isNextActionReady()
{
    if (!curEpisode->hasMoreActions()) {
        return false;
    } else {
        curAction = curEpisode->peekCurAction();

        // Only GPU wavefront threads have a token port. For all other types
        // of threads evaluate to true.
        bool haveTokens = tokenPort ? tokenPort->haveTokens(numLanes) : true;

        switch(curAction->getType()) {
            case Episode::Action::Type::ATOMIC:
                // an atomic action must wait for all previous requests
                // to complete
                if (pendingLdStCount == 0 &&
                    pendingFenceCount == 0 &&
                    pendingAtomicCount == 0 &&
                    haveTokens) {
                    return true;
                }

                return false;
            case Episode::Action::Type::ACQUIRE:
                // we should not see any outstanding ld_st or fence here
                assert(pendingLdStCount == 0 &&
                       pendingFenceCount == 0);

                // an acquire action must wait for all previous atomic
                // requests to complete
                if (pendingAtomicCount == 0) {
                    return true;
                }

                return false;
            case Episode::Action::Type::RELEASE:
                // we should not see any outstanding atomic or fence here
                assert(pendingAtomicCount == 0 &&
                       pendingFenceCount == 0);

                // a release action must wait for all previous ld/st
                // requests to complete
                if (pendingLdStCount == 0) {
                    return true;
                }

                return false;
            case Episode::Action::Type::LOAD:
            case Episode::Action::Type::STORE:
                // we should not see any outstanding atomic here
                assert(pendingAtomicCount == 0);

                // can't issue if there is a pending fence
                if (pendingFenceCount > 0 || !haveTokens) {
                    return false;
                }

                // a Load or Store is ready if it doesn't overlap
                // with any outstanding request
                for (int lane = 0; lane < numLanes; ++lane) {
                    Location loc = curAction->getLocation(lane);

                    if (loc != AddressManager::INVALID_LOCATION) {
                        Addr addr = addrManager->getAddress(loc);

                        if (outstandingLoads.find(addr) !=
                            outstandingLoads.end()) {
                            return false;
                        }

                        if (outstandingStores.find(addr) !=
                            outstandingStores.end()) {
                            return false;
                        }

                        if (outstandingAtomics.find(addr) !=
                            outstandingAtomics.end()) {
                            // this is not an atomic action, so the address
                            // should not be in outstandingAtomics list
                            assert(false);
                        }
                    }
                }

                return true;
            default:
                panic("The tester got an invalid action\n");
        }
    }
}

void
TesterThread::issueNextAction()
{
    switch(curAction->getType()) {
        case Episode::Action::Type::ATOMIC:
            if (tokenPort) {
                tokenPort->acquireTokens(numLanes);
            }
            issueAtomicOps();
            break;
        case Episode::Action::Type::ACQUIRE:
            issueAcquireOp();
            break;
        case Episode::Action::Type::RELEASE:
            issueReleaseOp();
            break;
        case Episode::Action::Type::LOAD:
            if (tokenPort) {
                tokenPort->acquireTokens(numLanes);
            }
            issueLoadOps();
            break;
        case Episode::Action::Type::STORE:
            if (tokenPort) {
                tokenPort->acquireTokens(numLanes);
            }
            issueStoreOps();
            break;
        default:
            panic("The tester got an invalid action\n");
    }

    // the current action has been issued, pop it from the action list
    curEpisode->popAction();
    lastActiveCycle = curCycle();

    // we may be able to schedule the next action
    // just wake up this thread in the next cycle
    if (!threadEvent.scheduled()) {
        scheduleWakeup();
    }
}

void
TesterThread::addOutstandingReqs(OutstandingReqTable& req_table, Addr address,
                           int lane, Location loc, Value stored_val)
{
    OutstandingReqTable::iterator it = req_table.find(address);
    OutstandingReq req(lane, loc, stored_val, curCycle());

    if (it == req_table.end()) {
        // insert a new list of requests for this address
        req_table.insert(std::pair<Addr, OutstandingReqList>(address,
                                                OutstandingReqList(1, req)));
    } else {
        // add a new request
        (it->second).push_back(req);
    }
}

TesterThread::OutstandingReq
TesterThread::popOutstandingReq(OutstandingReqTable& req_table, Addr addr)
{
    OutstandingReqTable::iterator it = req_table.find(addr);

    // there must be exactly one list of requests for this address in the table
    assert(it != req_table.end());

    // get the request list
    OutstandingReqList& req_list = it->second;
    assert(!req_list.empty());

    // save a request
    OutstandingReq ret_req = req_list.back();

    // remove the request from the list
    req_list.pop_back();

    // if the list is now empty, remove it from req_table
    if (req_list.empty()) {
        req_table.erase(it);
    }

    return ret_req;
}

void
TesterThread::validateAtomicResp(Location loc, int lane, Value ret_val)
{
    if (!addrManager->validateAtomicResp(loc, ret_val)) {
        std::stringstream ss;
        Addr addr = addrManager->getAddress(loc);

        // basic info
        ss << threadName << ": Atomic Op returned unexpected value\n"
           << "\tEpisode " << curEpisode->getEpisodeId() << "\n"
           << "\tLane ID " << lane << "\n"
           << "\tAddress " << ruby::printAddress(addr) << "\n"
           << "\tAtomic Op's return value " << ret_val << "\n";

        // print out basic info
        warn("%s\n", ss.str());

        // TODO add more detailed info

        // dump all error info and exit the simulation
        tester->dumpErrorLog(ss);
    }
}

void
TesterThread::validateLoadResp(Location loc, int lane, Value ret_val)
{
    if (ret_val != addrManager->getLoggedValue(loc)) {
        std::stringstream ss;
        Addr addr = addrManager->getAddress(loc);

        // basic info
        ss << threadName << ": Loaded value is not consistent with "
           << "the last stored value\n"
           << "\tTesterThread " << threadId << "\n"
           << "\tEpisode " << curEpisode->getEpisodeId() << "\n"
           << "\tLane ID " << lane << "\n"
           << "\tAddress " << ruby::printAddress(addr) << "\n"
           << "\tLoaded value " << ret_val << "\n"
           << "\tLast writer " << addrManager->printLastWriter(loc) << "\n";

        // print out basic info
        warn("%s\n", ss.str());

        // TODO add more detailed info

        // dump all error info and exit the simulation
        tester->dumpErrorLog(ss);
    }
}

bool
TesterThread::checkDRF(Location atomic_loc, Location loc, bool isStore) const
{
    if (curEpisode && curEpisode->isEpsActive()) {
        // check against the current episode this thread is executing
        return curEpisode->checkDRF(atomic_loc, loc, isStore, numLanes);
    }

    return true;
}

void
TesterThread::checkDeadlock()
{
    if ((curCycle() - lastActiveCycle) > deadlockThreshold) {
        // deadlock detected
        std::stringstream ss;

        ss << threadName << ": Deadlock detected\n"
           << "\tLast active cycle: " <<  lastActiveCycle << "\n"
           << "\tCurrent cycle: " << curCycle() << "\n"
           << "\tDeadlock threshold: " << deadlockThreshold << "\n";

        // print out basic info
        warn("%s\n", ss.str());

        // dump all error info and exit the simulation
        tester->dumpErrorLog(ss);
    } else if (!tester->checkExit()) {
        // schedule a future deadlock check event
        assert(!deadlockCheckEvent.scheduled());
        schedule(deadlockCheckEvent,
                 deadlockThreshold * clockPeriod() + curTick());
    }
}

void
TesterThread::printOutstandingReqs(const OutstandingReqTable& table,
                             std::stringstream& ss) const
{
    Cycles cur_cycle = curCycle();

    for (const auto& m : table) {
        for (const auto& req : m.second) {
            ss << "\t\t\tAddr " << ruby::printAddress(m.first)
               << ": delta (curCycle - issueCycle) = "
               << (cur_cycle - req.issueCycle) << std::endl;
        }
    }
}

void
TesterThread::printAllOutstandingReqs(std::stringstream& ss) const
{
    // dump all outstanding requests of this thread
    ss << "\t\tOutstanding Loads:\n";
    printOutstandingReqs(outstandingLoads, ss);
    ss << "\t\tOutstanding Stores:\n";
    printOutstandingReqs(outstandingStores, ss);
    ss << "\t\tOutstanding Atomics:\n";
    printOutstandingReqs(outstandingAtomics, ss);
    ss << "\t\tNumber of outstanding acquires & releases: "
       << pendingFenceCount << std::endl;
}

} // namespace gem5
