/*
 * Copyright (c) 2011, 2016-2018, 2020-2021 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.
 */

#ifndef __CPU_CHECKER_CPU_HH__
#define __CPU_CHECKER_CPU_HH__

#include <list>
#include <map>
#include <queue>

#include "arch/generic/pcstate.hh"
#include "base/statistics.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
#include "cpu/inst_res.hh"
#include "cpu/pc_event.hh"
#include "cpu/simple_thread.hh"
#include "cpu/static_inst.hh"
#include "debug/Checker.hh"
#include "mem/request.hh"
#include "params/CheckerCPU.hh"
#include "sim/eventq.hh"

namespace gem5
{

class ThreadContext;
class Request;

/**
 * CheckerCPU class.  Dynamically verifies instructions as they are
 * completed by making sure that the instruction and its results match
 * the independent execution of the benchmark inside the checker.  The
 * checker verifies instructions in order, regardless of the order in
 * which instructions complete.  There are certain results that can
 * not be verified, specifically the result of a store conditional or
 * the values of uncached accesses.  In these cases, and with
 * instructions marked as "IsUnverifiable", the checker assumes that
 * the value from the main CPU's execution is correct and simply
 * copies that value.  It provides a CheckerThreadContext (see
 * checker/thread_context.hh) that provides hooks for updating the
 * Checker's state through any ThreadContext accesses.  This allows the
 * checker to be able to correctly verify instructions, even with
 * external accesses to the ThreadContext that change state.
 */
class CheckerCPU : public BaseCPU, public ExecContext
{
  protected:
    /** id attached to all issued requests */
    RequestorID requestorId;

    const RegIndex zeroReg;

  public:
    void init() override;

    PARAMS(CheckerCPU);
    CheckerCPU(const Params &p);
    virtual ~CheckerCPU();

    void setSystem(System *system);

    void setIcachePort(RequestPort *icache_port);

    void setDcachePort(RequestPort *dcache_port);

    Port &
    getDataPort() override
    {
        // the checker does not have ports on its own so return the
        // data port of the actual CPU core
        assert(dcachePort);
        return *dcachePort;
    }

    Port &
    getInstPort() override
    {
        // the checker does not have ports on its own so return the
        // data port of the actual CPU core
        assert(icachePort);
        return *icachePort;
    }

  protected:

    std::vector<Process*> workload;

    System *systemPtr;

    RequestPort *icachePort;
    RequestPort *dcachePort;

    ThreadContext *tc;

    BaseMMU *mmu;

    // ISAs like ARM can have multiple destination registers to check,
    // keep them all in a std::queue
    std::queue<InstResult> result;

    StaticInstPtr curStaticInst;
    StaticInstPtr curMacroStaticInst;

    // number of simulated instructions
    Counter numInst;
    Counter startNumInst;

    std::queue<int> miscRegIdxs;

  public:

    // Primary thread being run.
    SimpleThread *thread;

    BaseMMU* getMMUPtr() { return mmu; }

    virtual Counter totalInsts() const override { return 0; }

    virtual Counter totalOps() const override { return 0; }

    // number of simulated loads
    Counter numLoad;
    Counter startNumLoad;

    void serialize(CheckpointOut &cp) const override;
    void unserialize(CheckpointIn &cp) override;

    // The register accessor methods provide the index of the
    // instruction's operand (e.g., 0 or 1), not the architectural
    // register index, to simplify the implementation of register
    // renaming.  We find the architectural register index by indexing
    // into the instruction's own operand index table.  Note that a
    // raw pointer to the StaticInst is provided instead of a
    // ref-counted StaticInstPtr to redice overhead.  This is fine as
    // long as these methods don't copy the pointer into any long-term
    // storage (which is pretty hard to imagine they would have reason
    // to do).

    RegVal
    readIntRegOperand(const StaticInst *si, int idx) override
    {
        const RegId& reg = si->srcRegIdx(idx);
        assert(reg.is(IntRegClass));
        return thread->readIntReg(reg.index());
    }

    RegVal
    readFloatRegOperandBits(const StaticInst *si, int idx) override
    {
        const RegId& reg = si->srcRegIdx(idx);
        assert(reg.is(FloatRegClass));
        return thread->readFloatReg(reg.index());
    }

    /**
     * Read source vector register operand.
     */
    const TheISA::VecRegContainer &
    readVecRegOperand(const StaticInst *si, int idx) const override
    {
        const RegId& reg = si->srcRegIdx(idx);
        assert(reg.is(VecRegClass));
        return thread->readVecReg(reg);
    }

    /**
     * Read destination vector register operand for modification.
     */
    TheISA::VecRegContainer &
    getWritableVecRegOperand(const StaticInst *si, int idx) override
    {
        const RegId& reg = si->destRegIdx(idx);
        assert(reg.is(VecRegClass));
        return thread->getWritableVecReg(reg);
    }

    RegVal
    readVecElemOperand(const StaticInst *si, int idx) const override
    {
        const RegId& reg = si->srcRegIdx(idx);
        return thread->readVecElem(reg);
    }

    const TheISA::VecPredRegContainer&
    readVecPredRegOperand(const StaticInst *si, int idx) const override
    {
        const RegId& reg = si->srcRegIdx(idx);
        assert(reg.is(VecPredRegClass));
        return thread->readVecPredReg(reg);
    }

    TheISA::VecPredRegContainer&
    getWritableVecPredRegOperand(const StaticInst *si, int idx) override
    {
        const RegId& reg = si->destRegIdx(idx);
        assert(reg.is(VecPredRegClass));
        return thread->getWritableVecPredReg(reg);
    }

    RegVal
    readCCRegOperand(const StaticInst *si, int idx) override
    {
        const RegId& reg = si->srcRegIdx(idx);
        assert(reg.is(CCRegClass));
        return thread->readCCReg(reg.index());
    }

    void
    setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
    {
        const RegId& reg = si->destRegIdx(idx);
        assert(reg.is(IntRegClass));
        thread->setIntReg(reg.index(), val);
        result.emplace(val);
    }

    void
    setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
    {
        const RegId& reg = si->destRegIdx(idx);
        assert(reg.is(FloatRegClass));
        thread->setFloatReg(reg.index(), val);
        result.emplace(val);
    }

    void
    setCCRegOperand(const StaticInst *si, int idx, RegVal val) override
    {
        const RegId& reg = si->destRegIdx(idx);
        assert(reg.is(CCRegClass));
        thread->setCCReg(reg.index(), val);
        result.emplace(val);
    }

    void
    setVecRegOperand(const StaticInst *si, int idx,
                     const TheISA::VecRegContainer& val) override
    {
        const RegId& reg = si->destRegIdx(idx);
        assert(reg.is(VecRegClass));
        thread->setVecReg(reg, val);
        result.emplace(val);
    }

    void
    setVecElemOperand(const StaticInst *si, int idx, RegVal val) override
    {
        const RegId& reg = si->destRegIdx(idx);
        assert(reg.is(VecElemClass));
        thread->setVecElem(reg, val);
        result.emplace(val);
    }

    void
    setVecPredRegOperand(const StaticInst *si, int idx,
                         const TheISA::VecPredRegContainer& val) override
    {
        const RegId& reg = si->destRegIdx(idx);
        assert(reg.is(VecPredRegClass));
        thread->setVecPredReg(reg, val);
        result.emplace(val);
    }

    bool readPredicate() const override { return thread->readPredicate(); }

    void
    setPredicate(bool val) override
    {
        thread->setPredicate(val);
    }

    bool
    readMemAccPredicate() const override
    {
        return thread->readMemAccPredicate();
    }

    void
    setMemAccPredicate(bool val) override
    {
        thread->setMemAccPredicate(val);
    }

    uint64_t
    getHtmTransactionUid() const override
    {
        panic("not yet supported!");
        return 0;
    };

    uint64_t
    newHtmTransactionUid() const override
    {
        panic("not yet supported!");
        return 0;
    };

    Fault
    initiateHtmCmd(Request::Flags flags) override
    {
        panic("not yet supported!");
        return NoFault;
    }

    bool
    inHtmTransactionalState() const override
    {
        return (getHtmTransactionalDepth() > 0);
    }

    uint64_t
    getHtmTransactionalDepth() const override
    {
        assert(thread->htmTransactionStarts >= thread->htmTransactionStops);
        return (thread->htmTransactionStarts - thread->htmTransactionStops);
    }

    const PCStateBase &
    pcState() const override
    {
        return thread->pcState();
    }
    void
    pcState(const PCStateBase &val) override
    {
        DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
                         val, thread->pcState());
        thread->pcState(val);
    }
    //////////////////////////////////////////

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

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

    void
    setMiscRegNoEffect(int misc_reg, RegVal val)
    {
        DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n",
                misc_reg);
        miscRegIdxs.push(misc_reg);
        return thread->setMiscRegNoEffect(misc_reg, val);
    }

    void
    setMiscReg(int misc_reg, RegVal val) override
    {
        DPRINTF(Checker, "Setting misc reg %d with effect to check later\n",
                misc_reg);
        miscRegIdxs.push(misc_reg);
        return thread->setMiscReg(misc_reg, val);
    }

    RegVal
    readMiscRegOperand(const StaticInst *si, int idx) override
    {
        const RegId& reg = si->srcRegIdx(idx);
        assert(reg.is(MiscRegClass));
        return thread->readMiscReg(reg.index());
    }

    void
    setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override
    {
        const RegId& reg = si->destRegIdx(idx);
        assert(reg.is(MiscRegClass));
        return this->setMiscReg(reg.index(), val);
    }

    /////////////////////////////////////////

    void
    recordPCChange(const PCStateBase &val)
    {
       changedPC = true;
       set(newPCState, val);
    }

    void
    demapPage(Addr vaddr, uint64_t asn) override
    {
        mmu->demapPage(vaddr, asn);
    }

    // monitor/mwait funtions
    void armMonitor(Addr address) override { BaseCPU::armMonitor(0, address); }
    bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }

    void
    mwaitAtomic(ThreadContext *tc) override
    {
        return BaseCPU::mwaitAtomic(0, tc, thread->mmu);
    }

    AddressMonitor *
    getAddrMonitor() override
    {
        return BaseCPU::getCpuAddrMonitor(0);
    }

    /**
     * Helper function used to generate the request for a single fragment of a
     * memory access.
     *
     * Takes care of setting up the appropriate byte-enable mask for the
     * fragment, given the mask for the entire memory access.
     *
     * @param frag_addr Start address of the fragment.
     * @param size Total size of the memory access in bytes.
     * @param flags Request flags.
     * @param byte_enable Byte-enable mask for the entire memory access.
     * @param[out] frag_size Fragment size.
     * @param[in,out] size_left Size left to be processed in the memory access.
     * @return Pointer to the allocated Request, nullptr if the byte-enable
     * mask is all-false for the fragment.
     */
    RequestPtr genMemFragmentRequest(Addr frag_addr, int size,
                                     Request::Flags flags,
                                     const std::vector<bool>& byte_enable,
                                     int& frag_size, int& size_left) const;

    Fault readMem(Addr addr, uint8_t *data, unsigned size,
                  Request::Flags flags,
                  const std::vector<bool>& byte_enable) override;

    Fault writeMem(uint8_t *data, unsigned size, Addr addr,
                   Request::Flags flags, uint64_t *res,
                   const std::vector<bool>& byte_enable) override;

    Fault
    amoMem(Addr addr, uint8_t* data, unsigned size,
           Request::Flags flags, AtomicOpFunctorPtr amo_op) override
    {
        panic("AMO is not supported yet in CPU checker\n");
    }

    unsigned int
    readStCondFailures() const override
    {
        return thread->readStCondFailures();
    }

    void setStCondFailures(unsigned int sc_failures) override {}
    /////////////////////////////////////////////////////

    void wakeup(ThreadID tid) override { }

    void
    handleError()
    {
        if (exitOnError)
            dumpAndExit();
    }

    bool checkFlags(const RequestPtr &unverified_req, Addr vAddr,
                    Addr pAddr, int flags);

    void dumpAndExit();

    ThreadContext *tcBase() const override { return tc; }
    SimpleThread *threadBase() { return thread; }

    InstResult unverifiedResult;
    RequestPtr unverifiedReq;
    uint8_t *unverifiedMemData;

    bool changedPC;
    bool willChangePC;
    std::unique_ptr<PCStateBase> newPCState;
    bool exitOnError;
    bool updateOnError;
    bool warnOnlyOnLoadError;

    InstSeqNum youngestSN;
};

/**
 * Templated Checker class.  This Checker class is templated on the
 * DynInstPtr of the instruction type that will be verified.  Proper
 * template instantiations of the Checker must be placed at the bottom
 * of checker/cpu.cc.
 */
template <class DynInstPtr>
class Checker : public CheckerCPU
{
  public:
    Checker(const Params &p)
        : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
    { }

    void switchOut();
    void takeOverFrom(BaseCPU *oldCPU);

    void advancePC(const Fault &fault);

    void verify(const DynInstPtr &inst);

    void validateInst(const DynInstPtr &inst);
    void validateExecution(const DynInstPtr &inst);
    void validateState();

    void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val,
                    int start_idx);
    void handlePendingInt();

  private:
    void
    handleError(const DynInstPtr &inst)
    {
        if (exitOnError) {
            dumpAndExit(inst);
        } else if (updateOnError) {
            updateThisCycle = true;
        }
    }

    void dumpAndExit(const DynInstPtr &inst);

    bool updateThisCycle;

    DynInstPtr unverifiedInst;

    std::list<DynInstPtr> instList;
    typedef typename std::list<DynInstPtr>::iterator InstListIt;
    void dumpInsts();
};

} // namespace gem5

#endif // __CPU_CHECKER_CPU_HH__
