/*
 * Copyright (c) 2017-2021 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * 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
