/*
 * Copyright (c) 2011-2012, 2016-2018, 2020 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) 2001-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_SIMPLE_THREAD_HH__
#define __CPU_SIMPLE_THREAD_HH__

#include <algorithm>
#include <vector>

#include "arch/generic/htm.hh"
#include "arch/generic/mmu.hh"
#include "arch/generic/pcstate.hh"
#include "arch/generic/tlb.hh"
#include "arch/isa.hh"
#include "arch/vecregs.hh"
#include "base/logging.hh"
#include "base/types.hh"
#include "config/the_isa.hh"
#include "cpu/regfile.hh"
#include "cpu/thread_context.hh"
#include "cpu/thread_state.hh"
#include "debug/CCRegs.hh"
#include "debug/FloatRegs.hh"
#include "debug/IntRegs.hh"
#include "debug/VecPredRegs.hh"
#include "debug/VecRegs.hh"
#include "mem/htm.hh"
#include "mem/page_table.hh"
#include "mem/request.hh"
#include "sim/byteswap.hh"
#include "sim/eventq.hh"
#include "sim/full_system.hh"
#include "sim/process.hh"
#include "sim/serialize.hh"
#include "sim/system.hh"

namespace gem5
{

class BaseCPU;
class CheckerCPU;

/**
 * The SimpleThread object provides a combination of the ThreadState
 * object and the ThreadContext interface. It implements the
 * ThreadContext interface and adds to the ThreadState object by adding all
 * the objects needed for simple functional execution, including a
 * simple architectural register file, and pointers to the ITB and DTB
 * in full system mode. For CPU models that do not need more advanced
 * ways to hold state (i.e. a separate physical register file, or
 * separate fetch and commit PC's), this SimpleThread class provides
 * all the necessary state for full architecture-level functional
 * simulation.  See the AtomicSimpleCPU or TimingSimpleCPU for
 * examples.
 */

class SimpleThread : public ThreadState, public ThreadContext
{
  public:
    typedef ThreadContext::Status Status;

  protected:
    std::array<RegFile, CCRegClass + 1> regFiles;

    TheISA::ISA *const isa;    // one "instance" of the current ISA.

    std::unique_ptr<PCStateBase> _pcState;

    // hardware transactional memory
    std::unique_ptr<BaseHTMCheckpoint> _htmCheckpoint;

    /** Did this instruction execute or is it predicated false */
    bool predicate;

    /** True if the memory access should be skipped for this instruction */
    bool memAccPredicate;

  public:
    std::string
    name() const
    {
        return csprintf("%s.[tid:%i]", baseCpu->name(), threadId());
    }

    PCEventQueue pcEventQueue;
    /**
     * An instruction-based event queue. Used for scheduling events based on
     * number of instructions committed.
     */
    EventQueue comInstEventQueue;

    System *system;

    BaseMMU *mmu;

    InstDecoder *decoder;

    // hardware transactional memory
    int64_t htmTransactionStarts;
    int64_t htmTransactionStops;

    // constructor: initialize SimpleThread from given process structure
    // FS
    SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
                 BaseMMU *_mmu, BaseISA *_isa, InstDecoder *_decoder);
    // SE
    SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
                 Process *_process, BaseMMU *_mmu,
                 BaseISA *_isa, InstDecoder *_decoder);

    virtual ~SimpleThread() {}

    void takeOverFrom(ThreadContext *oldContext) override;

    void copyState(ThreadContext *oldContext);

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

    /***************************************************************
     *  SimpleThread functions to provide CPU with access to various
     *  state.
     **************************************************************/

    /** Returns the pointer to this SimpleThread's ThreadContext. Used
     *  when a ThreadContext must be passed to objects outside of the
     *  CPU.
     */
    ThreadContext *getTC() { return this; }

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

    /*******************************************
     * ThreadContext interface functions.
     ******************************************/

    bool schedule(PCEvent *e) override { return pcEventQueue.schedule(e); }
    bool remove(PCEvent *e) override { return pcEventQueue.remove(e); }

    void
    scheduleInstCountEvent(Event *event, Tick count) override
    {
        comInstEventQueue.schedule(event, count);
    }
    void
    descheduleInstCountEvent(Event *event) override
    {
        comInstEventQueue.deschedule(event);
    }
    Tick
    getCurrentInstCount() override
    {
        return comInstEventQueue.getCurTick();
    }

    BaseCPU *getCpuPtr() override { return baseCpu; }

    int cpuId() const override { return ThreadState::cpuId(); }
    uint32_t socketId() const override { return ThreadState::socketId(); }
    int threadId() const override { return ThreadState::threadId(); }
    void setThreadId(int id) override { ThreadState::setThreadId(id); }
    ContextID contextId() const override { return ThreadState::contextId(); }
    void setContextId(ContextID id) override { ThreadState::setContextId(id); }

    BaseMMU *getMMUPtr() override { return mmu; }

    CheckerCPU *getCheckerCpuPtr() override { return NULL; }

    BaseISA *getIsaPtr() const override { return isa; }

    InstDecoder *getDecoderPtr() override { return decoder; }

    System *getSystemPtr() override { return system; }

    Process *getProcessPtr() override { return ThreadState::getProcessPtr(); }
    void setProcessPtr(Process *p) override { ThreadState::setProcessPtr(p); }

    Status status() const override { return _status; }

    void setStatus(Status newStatus) override { _status = newStatus; }

    /// Set the status to Active.
    void activate() override;

    /// Set the status to Suspended.
    void suspend() override;

    /// Set the status to Halted.
    void halt() override;

    Tick
    readLastActivate() override
    {
        return ThreadState::readLastActivate();
    }
    Tick
    readLastSuspend() override
    {
        return ThreadState::readLastSuspend();
    }

    void copyArchRegs(ThreadContext *tc) override;

    void
    clearArchRegs() override
    {
        set(_pcState, isa->newPCState());
        for (auto &rf: regFiles)
            rf.clear();
        isa->clear();
    }

    //
    // New accessors for new decoder.
    //
    const PCStateBase &pcState() const override { return *_pcState; }
    void pcState(const PCStateBase &val) override { set(_pcState, val); }

    void
    pcStateNoRecord(const PCStateBase &val) override
    {
        set(_pcState, val);
    }

    bool readPredicate() const { return predicate; }
    void setPredicate(bool val) { predicate = val; }

    RegVal
    readMiscRegNoEffect(RegIndex misc_reg) const override
    {
        return isa->readMiscRegNoEffect(misc_reg);
    }

    RegVal
    readMiscReg(RegIndex misc_reg) override
    {
        return isa->readMiscReg(misc_reg);
    }

    void
    setMiscRegNoEffect(RegIndex misc_reg, RegVal val) override
    {
        return isa->setMiscRegNoEffect(misc_reg, val);
    }

    void
    setMiscReg(RegIndex misc_reg, RegVal val) override
    {
        return isa->setMiscReg(misc_reg, val);
    }

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

    unsigned readStCondFailures() const override { return storeCondFailures; }

    bool
    readMemAccPredicate()
    {
        return memAccPredicate;
    }

    void
    setMemAccPredicate(bool val)
    {
        memAccPredicate = val;
    }

    void
    setStCondFailures(unsigned sc_failures) override
    {
        storeCondFailures = sc_failures;
    }

    RegVal
    getReg(const RegId &arch_reg) const override
    {
        const RegId reg = flattenRegId(arch_reg);

        const RegIndex idx = reg.index();

        const auto &reg_file = regFiles[reg.classValue()];
        const auto &reg_class = reg_file.regClass;

        RegVal val = reg_file.reg(idx);
        DPRINTFV(reg_class.debug(), "Reading %s reg %s (%d) as %#x.\n",
                reg.className(), reg_class.regName(arch_reg), idx, val);
        return val;
    }

    RegVal
    getRegFlat(const RegId &reg) const override
    {
        const RegIndex idx = reg.index();

        const auto &reg_file = regFiles[reg.classValue()];
        const auto &reg_class = reg_file.regClass;

        RegVal val = reg_file.reg(idx);
        DPRINTFV(reg_class.debug(), "Reading %s reg %d as %#x.\n",
                reg.className(), idx, val);
        return val;
    }

    void
    getReg(const RegId &arch_reg, void *val) const override
    {
        const RegId reg = flattenRegId(arch_reg);

        const RegIndex idx = reg.index();

        const auto &reg_file = regFiles[reg.classValue()];
        const auto &reg_class = reg_file.regClass;

        reg_file.get(idx, val);
        DPRINTFV(reg_class.debug(), "Reading %s register %s (%d) as %s.\n",
                reg.className(), reg_class.regName(arch_reg), idx,
                reg_class.valString(val));
    }

    void
    getRegFlat(const RegId &reg, void *val) const override
    {
        const RegIndex idx = reg.index();

        const auto &reg_file = regFiles[reg.classValue()];
        const auto &reg_class = reg_file.regClass;

        reg_file.get(idx, val);
        DPRINTFV(reg_class.debug(), "Reading %s register %d as %s.\n",
                reg.className(), idx, reg_class.valString(val));
    }

    void *
    getWritableReg(const RegId &arch_reg) override
    {
        const RegId reg = flattenRegId(arch_reg);
        const RegIndex idx = reg.index();
        auto &reg_file = regFiles[reg.classValue()];

        return reg_file.ptr(idx);
    }

    void *
    getWritableRegFlat(const RegId &reg) override
    {
        const RegIndex idx = reg.index();
        auto &reg_file = regFiles[reg.classValue()];

        return reg_file.ptr(idx);
    }

    void
    setReg(const RegId &arch_reg, RegVal val) override
    {
        const RegId reg = flattenRegId(arch_reg);

        const RegIndex idx = reg.index();

        auto &reg_file = regFiles[reg.classValue()];
        const auto &reg_class = reg_file.regClass;

        if (reg.index() == reg_class.zeroReg())
            return;

        DPRINTFV(reg_class.debug(), "Setting %s register %s (%d) to %#x.\n",
                reg.className(), reg_class.regName(arch_reg), idx, val);
        reg_file.reg(idx) = val;
    }

    void
    setRegFlat(const RegId &reg, RegVal val) override
    {
        const RegIndex idx = reg.index();

        auto &reg_file = regFiles[reg.classValue()];
        const auto &reg_class = reg_file.regClass;

        if (reg.index() == reg_class.zeroReg())
            return;

        DPRINTFV(reg_class.debug(), "Setting %s register %d to %#x.\n",
                reg.className(), idx, val);
        reg_file.reg(idx) = val;
    }

    void
    setReg(const RegId &arch_reg, const void *val) override
    {
        const RegId reg = flattenRegId(arch_reg);

        const RegIndex idx = reg.index();

        auto &reg_file = regFiles[reg.classValue()];
        const auto &reg_class = reg_file.regClass;

        DPRINTFV(reg_class.debug(), "Setting %s register %s (%d) to %s.\n",
                reg.className(), reg_class.regName(arch_reg), idx,
                reg_class.valString(val));
        reg_file.set(idx, val);
    }

    void
    setRegFlat(const RegId &reg, const void *val) override
    {
        const RegIndex idx = reg.index();

        auto &reg_file = regFiles[reg.classValue()];
        const auto &reg_class = reg_file.regClass;

        DPRINTFV(reg_class.debug(), "Setting %s register %d to %s.\n",
                reg.className(), idx, reg_class.valString(val));
        reg_file.set(idx, val);
    }

    // hardware transactional memory
    void htmAbortTransaction(uint64_t htm_uid,
                             HtmFailureFaultCause cause) override;

    BaseHTMCheckpointPtr& getHtmCheckpointPtr() override;
    void setHtmCheckpointPtr(BaseHTMCheckpointPtr new_cpt) override;
};

} // namespace gem5

#endif // __CPU_SIMPLE_THREAD_HH__
