/*
 * Copyright (c) 2010-2012, 2015, 2017, 2018 ARM Limited
 * Copyright (c) 2013 Advanced Micro Devices, Inc.
 * 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.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * 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: Steve Reinhardt
 */

#include "cpu/simple/base.hh"

#include "arch/stacktrace.hh"
#include "arch/utility.hh"
#include "arch/vtophys.hh"
#include "base/cp_annotate.hh"
#include "base/cprintf.hh"
#include "base/inifile.hh"
#include "base/loader/symtab.hh"
#include "base/logging.hh"
#include "base/pollevent.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "config/the_isa.hh"
#include "cpu/base.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/checker/thread_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/pred/bpred_unit.hh"
#include "cpu/profile.hh"
#include "cpu/simple/exec_context.hh"
#include "cpu/simple_thread.hh"
#include "cpu/smt.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "debug/Decode.hh"
#include "debug/Fetch.hh"
#include "debug/Quiesce.hh"
#include "mem/packet.hh"
#include "mem/request.hh"
#include "params/BaseSimpleCPU.hh"
#include "sim/byteswap.hh"
#include "sim/debug.hh"
#include "sim/faults.hh"
#include "sim/full_system.hh"
#include "sim/sim_events.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#include "sim/system.hh"

using namespace std;
using namespace TheISA;

BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
    : BaseCPU(p),
      curThread(0),
      branchPred(p->branchPred),
      traceData(NULL),
      inst(),
      _status(Idle)
{
    SimpleThread *thread;

    for (unsigned i = 0; i < numThreads; i++) {
        if (FullSystem) {
            thread = new SimpleThread(this, i, p->system,
                                      p->itb, p->dtb, p->isa[i]);
        } else {
            thread = new SimpleThread(this, i, p->system, p->workload[i],
                                      p->itb, p->dtb, p->isa[i]);
        }
        threadInfo.push_back(new SimpleExecContext(this, thread));
        ThreadContext *tc = thread->getTC();
        threadContexts.push_back(tc);
    }

    if (p->checker) {
        if (numThreads != 1)
            fatal("Checker currently does not support SMT");

        BaseCPU *temp_checker = p->checker;
        checker = dynamic_cast<CheckerCPU *>(temp_checker);
        checker->setSystem(p->system);
        // Manipulate thread context
        ThreadContext *cpu_tc = threadContexts[0];
        threadContexts[0] = new CheckerThreadContext<ThreadContext>(cpu_tc, this->checker);
    } else {
        checker = NULL;
    }
}

void
BaseSimpleCPU::init()
{
    BaseCPU::init();

    for (auto tc : threadContexts) {
        // Initialise the ThreadContext's memory proxies
        tc->initMemProxies(tc);

        if (FullSystem && !params()->switched_out) {
            // initialize CPU, including PC
            TheISA::initCPU(tc, tc->contextId());
        }
    }
}

void
BaseSimpleCPU::checkPcEventQueue()
{
    Addr oldpc, pc = threadInfo[curThread]->thread->instAddr();
    do {
        oldpc = pc;
        system->pcEventQueue.service(threadContexts[curThread]);
        pc = threadInfo[curThread]->thread->instAddr();
    } while (oldpc != pc);
}

void
BaseSimpleCPU::swapActiveThread()
{
    if (numThreads > 1) {
        if ((!curStaticInst || !curStaticInst->isDelayedCommit()) &&
             !threadInfo[curThread]->stayAtPC) {
            // Swap active threads
            if (!activeThreads.empty()) {
                curThread = activeThreads.front();
                activeThreads.pop_front();
                activeThreads.push_back(curThread);
            }
        }
    }
}

void
BaseSimpleCPU::countInst()
{
    SimpleExecContext& t_info = *threadInfo[curThread];

    if (!curStaticInst->isMicroop() || curStaticInst->isLastMicroop()) {
        t_info.numInst++;
        t_info.numInsts++;

        system->totalNumInsts++;
        t_info.thread->funcExeInst++;
    }
    t_info.numOp++;
    t_info.numOps++;
}

Counter
BaseSimpleCPU::totalInsts() const
{
    Counter total_inst = 0;
    for (auto& t_info : threadInfo) {
        total_inst += t_info->numInst;
    }

    return total_inst;
}

Counter
BaseSimpleCPU::totalOps() const
{
    Counter total_op = 0;
    for (auto& t_info : threadInfo) {
        total_op += t_info->numOp;
    }

    return total_op;
}

BaseSimpleCPU::~BaseSimpleCPU()
{
}

void
BaseSimpleCPU::haltContext(ThreadID thread_num)
{
    // for now, these are equivalent
    suspendContext(thread_num);
    updateCycleCounters(BaseCPU::CPU_STATE_SLEEP);
}


void
BaseSimpleCPU::regStats()
{
    using namespace Stats;

    BaseCPU::regStats();

    for (ThreadID tid = 0; tid < numThreads; tid++) {
        SimpleExecContext& t_info = *threadInfo[tid];

        std::string thread_str = name();
        if (numThreads > 1)
            thread_str += ".thread" + std::to_string(tid);

        t_info.numInsts
            .name(thread_str + ".committedInsts")
            .desc("Number of instructions committed")
            ;

        t_info.numOps
            .name(thread_str + ".committedOps")
            .desc("Number of ops (including micro ops) committed")
            ;

        t_info.numIntAluAccesses
            .name(thread_str + ".num_int_alu_accesses")
            .desc("Number of integer alu accesses")
            ;

        t_info.numFpAluAccesses
            .name(thread_str + ".num_fp_alu_accesses")
            .desc("Number of float alu accesses")
            ;

        t_info.numVecAluAccesses
            .name(thread_str + ".num_vec_alu_accesses")
            .desc("Number of vector alu accesses")
            ;

        t_info.numCallsReturns
            .name(thread_str + ".num_func_calls")
            .desc("number of times a function call or return occured")
            ;

        t_info.numCondCtrlInsts
            .name(thread_str + ".num_conditional_control_insts")
            .desc("number of instructions that are conditional controls")
            ;

        t_info.numIntInsts
            .name(thread_str + ".num_int_insts")
            .desc("number of integer instructions")
            ;

        t_info.numFpInsts
            .name(thread_str + ".num_fp_insts")
            .desc("number of float instructions")
            ;

        t_info.numVecInsts
            .name(thread_str + ".num_vec_insts")
            .desc("number of vector instructions")
            ;

        t_info.numIntRegReads
            .name(thread_str + ".num_int_register_reads")
            .desc("number of times the integer registers were read")
            ;

        t_info.numIntRegWrites
            .name(thread_str + ".num_int_register_writes")
            .desc("number of times the integer registers were written")
            ;

        t_info.numFpRegReads
            .name(thread_str + ".num_fp_register_reads")
            .desc("number of times the floating registers were read")
            ;

        t_info.numFpRegWrites
            .name(thread_str + ".num_fp_register_writes")
            .desc("number of times the floating registers were written")
            ;

        t_info.numVecRegReads
            .name(thread_str + ".num_vec_register_reads")
            .desc("number of times the vector registers were read")
            ;

        t_info.numVecRegWrites
            .name(thread_str + ".num_vec_register_writes")
            .desc("number of times the vector registers were written")
            ;

        t_info.numCCRegReads
            .name(thread_str + ".num_cc_register_reads")
            .desc("number of times the CC registers were read")
            .flags(nozero)
            ;

        t_info.numCCRegWrites
            .name(thread_str + ".num_cc_register_writes")
            .desc("number of times the CC registers were written")
            .flags(nozero)
            ;

        t_info.numMemRefs
            .name(thread_str + ".num_mem_refs")
            .desc("number of memory refs")
            ;

        t_info.numStoreInsts
            .name(thread_str + ".num_store_insts")
            .desc("Number of store instructions")
            ;

        t_info.numLoadInsts
            .name(thread_str + ".num_load_insts")
            .desc("Number of load instructions")
            ;

        t_info.notIdleFraction
            .name(thread_str + ".not_idle_fraction")
            .desc("Percentage of non-idle cycles")
            ;

        t_info.idleFraction
            .name(thread_str + ".idle_fraction")
            .desc("Percentage of idle cycles")
            ;

        t_info.numBusyCycles
            .name(thread_str + ".num_busy_cycles")
            .desc("Number of busy cycles")
            ;

        t_info.numIdleCycles
            .name(thread_str + ".num_idle_cycles")
            .desc("Number of idle cycles")
            ;

        t_info.icacheStallCycles
            .name(thread_str + ".icache_stall_cycles")
            .desc("ICache total stall cycles")
            .prereq(t_info.icacheStallCycles)
            ;

        t_info.dcacheStallCycles
            .name(thread_str + ".dcache_stall_cycles")
            .desc("DCache total stall cycles")
            .prereq(t_info.dcacheStallCycles)
            ;

        t_info.statExecutedInstType
            .init(Enums::Num_OpClass)
            .name(thread_str + ".op_class")
            .desc("Class of executed instruction")
            .flags(total | pdf | dist)
            ;

        for (unsigned i = 0; i < Num_OpClasses; ++i) {
            t_info.statExecutedInstType.subname(i, Enums::OpClassStrings[i]);
        }

        t_info.idleFraction = constant(1.0) - t_info.notIdleFraction;
        t_info.numIdleCycles = t_info.idleFraction * numCycles;
        t_info.numBusyCycles = t_info.notIdleFraction * numCycles;

        t_info.numBranches
            .name(thread_str + ".Branches")
            .desc("Number of branches fetched")
            .prereq(t_info.numBranches);

        t_info.numPredictedBranches
            .name(thread_str + ".predictedBranches")
            .desc("Number of branches predicted as taken")
            .prereq(t_info.numPredictedBranches);

        t_info.numBranchMispred
            .name(thread_str + ".BranchMispred")
            .desc("Number of branch mispredictions")
            .prereq(t_info.numBranchMispred);
    }
}

void
BaseSimpleCPU::resetStats()
{
    for (auto &thread_info : threadInfo) {
        thread_info->notIdleFraction = (_status != Idle);
    }
}

void
BaseSimpleCPU::serializeThread(CheckpointOut &cp, ThreadID tid) const
{
    assert(_status == Idle || _status == Running);

    threadInfo[tid]->thread->serialize(cp);
}

void
BaseSimpleCPU::unserializeThread(CheckpointIn &cp, ThreadID tid)
{
    threadInfo[tid]->thread->unserialize(cp);
}

void
change_thread_state(ThreadID tid, int activate, int priority)
{
}

Addr
BaseSimpleCPU::dbg_vtophys(Addr addr)
{
    return vtophys(threadContexts[curThread], addr);
}

void
BaseSimpleCPU::wakeup(ThreadID tid)
{
    getCpuAddrMonitor(tid)->gotWakeup = true;

    if (threadInfo[tid]->thread->status() == ThreadContext::Suspended) {
        DPRINTF(Quiesce,"[tid:%d] Suspended Processor awoke\n", tid);
        threadInfo[tid]->thread->activate();
    }
}

void
BaseSimpleCPU::checkForInterrupts()
{
    SimpleExecContext&t_info = *threadInfo[curThread];
    SimpleThread* thread = t_info.thread;
    ThreadContext* tc = thread->getTC();

    if (checkInterrupts(tc)) {
        Fault interrupt = interrupts[curThread]->getInterrupt(tc);

        if (interrupt != NoFault) {
            t_info.fetchOffset = 0;
            interrupts[curThread]->updateIntrInfo(tc);
            interrupt->invoke(tc);
            thread->decoder.reset();
        }
    }
}


void
BaseSimpleCPU::setupFetchRequest(const RequestPtr &req)
{
    SimpleExecContext &t_info = *threadInfo[curThread];
    SimpleThread* thread = t_info.thread;

    Addr instAddr = thread->instAddr();
    Addr fetchPC = (instAddr & PCMask) + t_info.fetchOffset;

    // set up memory request for instruction fetch
    DPRINTF(Fetch, "Fetch: Inst PC:%08p, Fetch PC:%08p\n", instAddr, fetchPC);

    req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH,
                 instMasterId(), instAddr);
}


void
BaseSimpleCPU::preExecute()
{
    SimpleExecContext &t_info = *threadInfo[curThread];
    SimpleThread* thread = t_info.thread;

    // maintain $r0 semantics
    thread->setIntReg(ZeroReg, 0);
#if THE_ISA == ALPHA_ISA
    thread->setFloatReg(ZeroReg, 0);
#endif // ALPHA_ISA

    // resets predicates
    t_info.setPredicate(true);
    t_info.setMemAccPredicate(true);

    // check for instruction-count-based events
    comInstEventQueue[curThread]->serviceEvents(t_info.numInst);
    system->instEventQueue.serviceEvents(system->totalNumInsts);

    // decode the instruction
    inst = gtoh(inst);

    TheISA::PCState pcState = thread->pcState();

    if (isRomMicroPC(pcState.microPC())) {
        t_info.stayAtPC = false;
        curStaticInst = microcodeRom.fetchMicroop(pcState.microPC(),
                                                  curMacroStaticInst);
    } else if (!curMacroStaticInst) {
        //We're not in the middle of a macro instruction
        StaticInstPtr instPtr = NULL;

        TheISA::Decoder *decoder = &(thread->decoder);

        //Predecode, ie bundle up an ExtMachInst
        //If more fetch data is needed, pass it in.
        Addr fetchPC = (pcState.instAddr() & PCMask) + t_info.fetchOffset;
        //if (decoder->needMoreBytes())
            decoder->moreBytes(pcState, fetchPC, inst);
        //else
        //    decoder->process();

        //Decode an instruction if one is ready. Otherwise, we'll have to
        //fetch beyond the MachInst at the current pc.
        instPtr = decoder->decode(pcState);
        if (instPtr) {
            t_info.stayAtPC = false;
            thread->pcState(pcState);
        } else {
            t_info.stayAtPC = true;
            t_info.fetchOffset += sizeof(MachInst);
        }

        //If we decoded an instruction and it's microcoded, start pulling
        //out micro ops
        if (instPtr && instPtr->isMacroop()) {
            curMacroStaticInst = instPtr;
            curStaticInst =
                curMacroStaticInst->fetchMicroop(pcState.microPC());
        } else {
            curStaticInst = instPtr;
        }
    } else {
        //Read the next micro op from the macro op
        curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC());
    }

    //If we decoded an instruction this "tick", record information about it.
    if (curStaticInst) {
#if TRACING_ON
        traceData = tracer->getInstRecord(curTick(), thread->getTC(),
                curStaticInst, thread->pcState(), curMacroStaticInst);

        DPRINTF(Decode,"Decode: Decoded %s instruction: %#x\n",
                curStaticInst->getName(), curStaticInst->machInst);
#endif // TRACING_ON
    }

    if (branchPred && curStaticInst &&
        curStaticInst->isControl()) {
        // Use a fake sequence number since we only have one
        // instruction in flight at the same time.
        const InstSeqNum cur_sn(0);
        t_info.predPC = thread->pcState();
        const bool predict_taken(
            branchPred->predict(curStaticInst, cur_sn, t_info.predPC,
                                curThread));

        if (predict_taken)
            ++t_info.numPredictedBranches;
    }
}

void
BaseSimpleCPU::postExecute()
{
    SimpleExecContext &t_info = *threadInfo[curThread];
    SimpleThread* thread = t_info.thread;

    assert(curStaticInst);

    TheISA::PCState pc = threadContexts[curThread]->pcState();
    Addr instAddr = pc.instAddr();
    if (FullSystem && thread->profile) {
        bool usermode = TheISA::inUserMode(threadContexts[curThread]);
        thread->profilePC = usermode ? 1 : instAddr;
        ProfileNode *node = thread->profile->consume(threadContexts[curThread],
                                                     curStaticInst);
        if (node)
            thread->profileNode = node;
    }

    if (curStaticInst->isMemRef()) {
        t_info.numMemRefs++;
    }

    if (curStaticInst->isLoad()) {
        ++t_info.numLoad;
        comLoadEventQueue[curThread]->serviceEvents(t_info.numLoad);
    }

    if (CPA::available()) {
        CPA::cpa()->swAutoBegin(threadContexts[curThread], pc.nextInstAddr());
    }

    if (curStaticInst->isControl()) {
        ++t_info.numBranches;
    }

    /* Power model statistics */
    //integer alu accesses
    if (curStaticInst->isInteger()){
        t_info.numIntAluAccesses++;
        t_info.numIntInsts++;
    }

    //float alu accesses
    if (curStaticInst->isFloating()){
        t_info.numFpAluAccesses++;
        t_info.numFpInsts++;
    }

    //vector alu accesses
    if (curStaticInst->isVector()){
        t_info.numVecAluAccesses++;
        t_info.numVecInsts++;
    }

    //number of function calls/returns to get window accesses
    if (curStaticInst->isCall() || curStaticInst->isReturn()){
        t_info.numCallsReturns++;
    }

    //the number of branch predictions that will be made
    if (curStaticInst->isCondCtrl()){
        t_info.numCondCtrlInsts++;
    }

    //result bus acceses
    if (curStaticInst->isLoad()){
        t_info.numLoadInsts++;
    }

    if (curStaticInst->isStore() || curStaticInst->isAtomic()){
        t_info.numStoreInsts++;
    }
    /* End power model statistics */

    t_info.statExecutedInstType[curStaticInst->opClass()]++;

    if (FullSystem)
        traceFunctions(instAddr);

    if (traceData) {
        traceData->dump();
        delete traceData;
        traceData = NULL;
    }

    // Call CPU instruction commit probes
    probeInstCommit(curStaticInst, instAddr);
}

void
BaseSimpleCPU::advancePC(const Fault &fault)
{
    SimpleExecContext &t_info = *threadInfo[curThread];
    SimpleThread* thread = t_info.thread;

    const bool branching(thread->pcState().branching());

    //Since we're moving to a new pc, zero out the offset
    t_info.fetchOffset = 0;
    if (fault != NoFault) {
        curMacroStaticInst = StaticInst::nullStaticInstPtr;
        fault->invoke(threadContexts[curThread], curStaticInst);
        thread->decoder.reset();
    } else {
        if (curStaticInst) {
            if (curStaticInst->isLastMicroop())
                curMacroStaticInst = StaticInst::nullStaticInstPtr;
            TheISA::PCState pcState = thread->pcState();
            TheISA::advancePC(pcState, curStaticInst);
            thread->pcState(pcState);
        }
    }

    if (branchPred && curStaticInst && curStaticInst->isControl()) {
        // Use a fake sequence number since we only have one
        // instruction in flight at the same time.
        const InstSeqNum cur_sn(0);

        if (t_info.predPC == thread->pcState()) {
            // Correctly predicted branch
            branchPred->update(cur_sn, curThread);
        } else {
            // Mis-predicted branch
            branchPred->squash(cur_sn, thread->pcState(), branching, curThread);
            ++t_info.numBranchMispred;
        }
    }
}

void
BaseSimpleCPU::startup()
{
    BaseCPU::startup();
    for (auto& t_info : threadInfo)
        t_info->thread->startup();
}
