/*
 * Copyright (c) 2011-2012, 2016 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) 2006 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: Kevin Lim
 */

#ifndef __CPU_CHECKER_THREAD_CONTEXT_HH__
#define __CPU_CHECKER_THREAD_CONTEXT_HH__

#include "arch/types.hh"
#include "config/the_isa.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
#include "debug/Checker.hh"

class EndQuiesceEvent;
namespace TheISA {
    namespace Kernel {
        class Statistics;
    };
    class Decoder;
};

/**
 * Derived ThreadContext class for use with the Checker.  The template
 * parameter is the ThreadContext class used by the specific CPU being
 * verified.  This CheckerThreadContext is then used by the main CPU
 * in place of its usual ThreadContext class.  It handles updating the
 * checker's state any time state is updated externally through the
 * ThreadContext.
 */
template <class TC>
class CheckerThreadContext : public ThreadContext
{
  public:
    CheckerThreadContext(TC *actual_tc,
                         CheckerCPU *checker_cpu)
        : actualTC(actual_tc), checkerTC(checker_cpu->thread),
          checkerCPU(checker_cpu)
    { }

  private:
    /** The main CPU's ThreadContext, or class that implements the
     * ThreadContext interface. */
    TC *actualTC;
    /** The checker's own SimpleThread. Will be updated any time
     * anything uses this ThreadContext to externally update a
     * thread's state. */
    SimpleThread *checkerTC;
    /** Pointer to the checker CPU. */
    CheckerCPU *checkerCPU;

  public:

    BaseCPU *getCpuPtr() { return actualTC->getCpuPtr(); }

    uint32_t socketId() const { return actualTC->socketId(); }

    int cpuId() const { return actualTC->cpuId(); }

    ContextID contextId() const { return actualTC->contextId(); }

    void setContextId(ContextID id)
    {
       actualTC->setContextId(id);
       checkerTC->setContextId(id);
    }

    /** Returns this thread's ID number. */
    int threadId() const { return actualTC->threadId(); }
    void setThreadId(int id)
    {
        checkerTC->setThreadId(id);
        actualTC->setThreadId(id);
    }

    BaseTLB *getITBPtr() { return actualTC->getITBPtr(); }

    BaseTLB *getDTBPtr() { return actualTC->getDTBPtr(); }

    CheckerCPU *getCheckerCpuPtr()
    {
        return checkerCPU;
    }

    TheISA::Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); }

    System *getSystemPtr() { return actualTC->getSystemPtr(); }

    TheISA::Kernel::Statistics *getKernelStats()
    { return actualTC->getKernelStats(); }

    Process *getProcessPtr() { return actualTC->getProcessPtr(); }

    void setProcessPtr(Process *p) { actualTC->setProcessPtr(p); }

    PortProxy &getPhysProxy() { return actualTC->getPhysProxy(); }

    FSTranslatingPortProxy &getVirtProxy()
    { return actualTC->getVirtProxy(); }

    void initMemProxies(ThreadContext *tc)
    { actualTC->initMemProxies(tc); }

    void connectMemPorts(ThreadContext *tc)
    {
        actualTC->connectMemPorts(tc);
    }

    SETranslatingPortProxy &getMemProxy() { return actualTC->getMemProxy(); }

    /** Executes a syscall in SE mode. */
    void syscall(int64_t callnum, Fault *fault)
    { return actualTC->syscall(callnum, fault); }

    Status status() const { return actualTC->status(); }

    void setStatus(Status new_status)
    {
        actualTC->setStatus(new_status);
        checkerTC->setStatus(new_status);
    }

    /// Set the status to Active.
    void activate() { actualTC->activate(); }

    /// Set the status to Suspended.
    void suspend() { actualTC->suspend(); }

    /// Set the status to Halted.
    void halt() { actualTC->halt(); }

    void dumpFuncProfile() { actualTC->dumpFuncProfile(); }

    void takeOverFrom(ThreadContext *oldContext)
    {
        actualTC->takeOverFrom(oldContext);
        checkerTC->copyState(oldContext);
    }

    void regStats(const std::string &name)
    {
        actualTC->regStats(name);
        checkerTC->regStats(name);
    }

    EndQuiesceEvent *getQuiesceEvent() { return actualTC->getQuiesceEvent(); }

    Tick readLastActivate() { return actualTC->readLastActivate(); }
    Tick readLastSuspend() { return actualTC->readLastSuspend(); }

    void profileClear() { return actualTC->profileClear(); }
    void profileSample() { return actualTC->profileSample(); }

    // @todo: Do I need this?
    void copyArchRegs(ThreadContext *tc)
    {
        actualTC->copyArchRegs(tc);
        checkerTC->copyArchRegs(tc);
    }

    void clearArchRegs()
    {
        actualTC->clearArchRegs();
        checkerTC->clearArchRegs();
    }

    //
    // New accessors for new decoder.
    //
    RegVal readIntReg(int reg_idx) { return actualTC->readIntReg(reg_idx); }

    RegVal
    readFloatRegBits(int reg_idx)
    {
        return actualTC->readFloatRegBits(reg_idx);
    }

    const VecRegContainer& readVecReg(const RegId& reg) const
    { return actualTC->readVecReg(reg); }

    /**
     * Read vector register for modification, hierarchical indexing.
     */
    VecRegContainer& getWritableVecReg(const RegId& reg)
    { return actualTC->getWritableVecReg(reg); }

    /** Vector Register Lane Interfaces. */
    /** @{ */
    /** Reads source vector 8bit operand. */
    ConstVecLane8
    readVec8BitLaneReg(const RegId& reg) const
    { return actualTC->readVec8BitLaneReg(reg); }

    /** Reads source vector 16bit operand. */
    ConstVecLane16
    readVec16BitLaneReg(const RegId& reg) const
    { return actualTC->readVec16BitLaneReg(reg); }

    /** Reads source vector 32bit operand. */
    ConstVecLane32
    readVec32BitLaneReg(const RegId& reg) const
    { return actualTC->readVec32BitLaneReg(reg); }

    /** Reads source vector 64bit operand. */
    ConstVecLane64
    readVec64BitLaneReg(const RegId& reg) const
    { return actualTC->readVec64BitLaneReg(reg); }

    /** Write a lane of the destination vector register. */
    virtual void setVecLane(const RegId& reg,
            const LaneData<LaneSize::Byte>& val)
    { return actualTC->setVecLane(reg, val); }
    virtual void setVecLane(const RegId& reg,
            const LaneData<LaneSize::TwoByte>& val)
    { return actualTC->setVecLane(reg, val); }
    virtual void setVecLane(const RegId& reg,
            const LaneData<LaneSize::FourByte>& val)
    { return actualTC->setVecLane(reg, val); }
    virtual void setVecLane(const RegId& reg,
            const LaneData<LaneSize::EightByte>& val)
    { return actualTC->setVecLane(reg, val); }
    /** @} */

    const VecElem& readVecElem(const RegId& reg) const
    { return actualTC->readVecElem(reg); }

    CCReg readCCReg(int reg_idx)
    { return actualTC->readCCReg(reg_idx); }

    void
    setIntReg(int reg_idx, RegVal val)
    {
        actualTC->setIntReg(reg_idx, val);
        checkerTC->setIntReg(reg_idx, val);
    }

    void
    setFloatRegBits(int reg_idx, RegVal val)
    {
        actualTC->setFloatRegBits(reg_idx, val);
        checkerTC->setFloatRegBits(reg_idx, val);
    }

    void
    setVecReg(const RegId& reg, const VecRegContainer& val)
    {
        actualTC->setVecReg(reg, val);
        checkerTC->setVecReg(reg, val);
    }

    void
    setVecElem(const RegId& reg, const VecElem& val)
    {
        actualTC->setVecElem(reg, val);
        checkerTC->setVecElem(reg, val);
    }

    void
    setCCReg(int reg_idx, CCReg val)
    {
        actualTC->setCCReg(reg_idx, val);
        checkerTC->setCCReg(reg_idx, val);
    }

    /** Reads this thread's PC state. */
    TheISA::PCState pcState()
    { return actualTC->pcState(); }

    /** Sets this thread's PC state. */
    void
    pcState(const TheISA::PCState &val)
    {
        DPRINTF(Checker, "Changing PC to %s, old PC %s\n",
                         val, checkerTC->pcState());
        checkerTC->pcState(val);
        checkerCPU->recordPCChange(val);
        return actualTC->pcState(val);
    }

    void
    setNPC(Addr val)
    {
        checkerTC->setNPC(val);
        actualTC->setNPC(val);
    }

    void
    pcStateNoRecord(const TheISA::PCState &val)
    {
        return actualTC->pcState(val);
    }

    /** Reads this thread's PC. */
    Addr instAddr()
    { return actualTC->instAddr(); }

    /** Reads this thread's next PC. */
    Addr nextInstAddr()
    { return actualTC->nextInstAddr(); }

    /** Reads this thread's next PC. */
    MicroPC microPC()
    { return actualTC->microPC(); }

    RegVal readMiscRegNoEffect(int misc_reg) const
    { return actualTC->readMiscRegNoEffect(misc_reg); }

    RegVal readMiscReg(int misc_reg)
    { return actualTC->readMiscReg(misc_reg); }

    void
    setMiscRegNoEffect(int misc_reg, const RegVal &val)
    {
        DPRINTF(Checker, "Setting misc reg with no effect: %d to both Checker"
                         " and O3..\n", misc_reg);
        checkerTC->setMiscRegNoEffect(misc_reg, val);
        actualTC->setMiscRegNoEffect(misc_reg, val);
    }

    void
    setMiscReg(int misc_reg, const RegVal &val)
    {
        DPRINTF(Checker, "Setting misc reg with effect: %d to both Checker"
                         " and O3..\n", misc_reg);
        checkerTC->setMiscReg(misc_reg, val);
        actualTC->setMiscReg(misc_reg, val);
    }

    RegId
    flattenRegId(const RegId& regId) const
    {
        return actualTC->flattenRegId(regId);
    }

    unsigned readStCondFailures()
    { return actualTC->readStCondFailures(); }

    void
    setStCondFailures(unsigned sc_failures)
    {
        actualTC->setStCondFailures(sc_failures);
    }

    Counter readFuncExeInst() { return actualTC->readFuncExeInst(); }

    RegVal readIntRegFlat(int idx) { return actualTC->readIntRegFlat(idx); }

    void
    setIntRegFlat(int idx, RegVal val)
    {
        actualTC->setIntRegFlat(idx, val);
    }

    RegVal
    readFloatRegBitsFlat(int idx)
    {
        return actualTC->readFloatRegBitsFlat(idx);
    }

    void
    setFloatRegBitsFlat(int idx, RegVal val)
    {
        actualTC->setFloatRegBitsFlat(idx, val);
    }

    const VecRegContainer &
    readVecRegFlat(int idx) const
    {
        return actualTC->readVecRegFlat(idx);
    }

    /**
     * Read vector register for modification, flat indexing.
     */
    VecRegContainer &
    getWritableVecRegFlat(int idx)
    {
        return actualTC->getWritableVecRegFlat(idx);
    }

    void setVecRegFlat(int idx, const VecRegContainer& val)
    { actualTC->setVecRegFlat(idx, val); }

    const VecElem& readVecElemFlat(const RegIndex& idx,
                                   const ElemIndex& elem_idx) const
    { return actualTC->readVecElemFlat(idx, elem_idx); }

    void setVecElemFlat(const RegIndex& idx,
                        const ElemIndex& elem_idx, const VecElem& val)
    { actualTC->setVecElemFlat(idx, elem_idx, val); }

    CCReg readCCRegFlat(int idx)
    { return actualTC->readCCRegFlat(idx); }

    void setCCRegFlat(int idx, CCReg val)
    { actualTC->setCCRegFlat(idx, val); }
};

#endif // __CPU_CHECKER_EXEC_CONTEXT_HH__
