/* * Copyright (c) 2011-2012, 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_THREAD_CONTEXT_HH__ #define __CPU_CHECKER_THREAD_CONTEXT_HH__ #include "arch/pcstate.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" namespace gem5 { namespace TheISA { class Decoder; } // namespace TheISA /** * 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 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: bool schedule(PCEvent *e) override { GEM5_VAR_USED bool check_ret = checkerTC->schedule(e); bool actual_ret = actualTC->schedule(e); assert(actual_ret == check_ret); return actual_ret; } bool remove(PCEvent *e) override { GEM5_VAR_USED bool check_ret = checkerTC->remove(e); bool actual_ret = actualTC->remove(e); assert(actual_ret == check_ret); return actual_ret; } void scheduleInstCountEvent(Event *event, Tick count) override { actualTC->scheduleInstCountEvent(event, count); } void descheduleInstCountEvent(Event *event) override { actualTC->descheduleInstCountEvent(event); } Tick getCurrentInstCount() override { return actualTC->getCurrentInstCount(); } BaseCPU *getCpuPtr() override { return actualTC->getCpuPtr(); } uint32_t socketId() const override { return actualTC->socketId(); } int cpuId() const override { return actualTC->cpuId(); } ContextID contextId() const override { return actualTC->contextId(); } void setContextId(ContextID id) override { actualTC->setContextId(id); checkerTC->setContextId(id); } /** Returns this thread's ID number. */ int threadId() const override { return actualTC->threadId(); } void setThreadId(int id) override { checkerTC->setThreadId(id); actualTC->setThreadId(id); } BaseMMU *getMMUPtr() override { return actualTC->getMMUPtr(); } CheckerCPU * getCheckerCpuPtr() override { return checkerCPU; } BaseISA *getIsaPtr() override { return actualTC->getIsaPtr(); } TheISA::Decoder * getDecoderPtr() override { return actualTC->getDecoderPtr(); } System *getSystemPtr() override { return actualTC->getSystemPtr(); } Process *getProcessPtr() override { return actualTC->getProcessPtr(); } void setProcessPtr(Process *p) override { actualTC->setProcessPtr(p); } void connectMemPorts(ThreadContext *tc) { actualTC->connectMemPorts(tc); } Status status() const override { return actualTC->status(); } void setStatus(Status new_status) override { actualTC->setStatus(new_status); checkerTC->setStatus(new_status); } /// Set the status to Active. void activate() override { actualTC->activate(); } /// Set the status to Suspended. void suspend() override { actualTC->suspend(); } /// Set the status to Halted. void halt() override { actualTC->halt(); } void takeOverFrom(ThreadContext *oldContext) override { actualTC->takeOverFrom(oldContext); checkerTC->copyState(oldContext); } void regStats(const std::string &name) override { actualTC->regStats(name); checkerTC->regStats(name); } Tick readLastActivate() override { return actualTC->readLastActivate(); } Tick readLastSuspend() override { return actualTC->readLastSuspend(); } // @todo: Do I need this? void copyArchRegs(ThreadContext *tc) override { actualTC->copyArchRegs(tc); checkerTC->copyArchRegs(tc); } void clearArchRegs() override { actualTC->clearArchRegs(); checkerTC->clearArchRegs(); } // // New accessors for new decoder. // RegVal readIntReg(RegIndex reg_idx) const override { return actualTC->readIntReg(reg_idx); } RegVal readFloatReg(RegIndex reg_idx) const override { return actualTC->readFloatReg(reg_idx); } const TheISA::VecRegContainer & readVecReg (const RegId ®) const override { return actualTC->readVecReg(reg); } /** * Read vector register for modification, hierarchical indexing. */ TheISA::VecRegContainer & getWritableVecReg (const RegId ®) override { return actualTC->getWritableVecReg(reg); } const TheISA::VecElem & readVecElem(const RegId& reg) const override { return actualTC->readVecElem(reg); } const TheISA::VecPredRegContainer & readVecPredReg(const RegId& reg) const override { return actualTC->readVecPredReg(reg); } TheISA::VecPredRegContainer & getWritableVecPredReg(const RegId& reg) override { return actualTC->getWritableVecPredReg(reg); } RegVal readCCReg(RegIndex reg_idx) const override { return actualTC->readCCReg(reg_idx); } void setIntReg(RegIndex reg_idx, RegVal val) override { actualTC->setIntReg(reg_idx, val); checkerTC->setIntReg(reg_idx, val); } void setFloatReg(RegIndex reg_idx, RegVal val) override { actualTC->setFloatReg(reg_idx, val); checkerTC->setFloatReg(reg_idx, val); } void setVecReg(const RegId& reg, const TheISA::VecRegContainer& val) override { actualTC->setVecReg(reg, val); checkerTC->setVecReg(reg, val); } void setVecElem(const RegId& reg, const TheISA::VecElem& val) override { actualTC->setVecElem(reg, val); checkerTC->setVecElem(reg, val); } void setVecPredReg(const RegId& reg, const TheISA::VecPredRegContainer& val) override { actualTC->setVecPredReg(reg, val); checkerTC->setVecPredReg(reg, val); } void setCCReg(RegIndex reg_idx, RegVal val) override { actualTC->setCCReg(reg_idx, val); checkerTC->setCCReg(reg_idx, val); } /** Reads this thread's PC state. */ TheISA::PCState pcState() const override { return actualTC->pcState(); } /** Sets this thread's PC state. */ void pcState(const TheISA::PCState &val) override { 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) override { return actualTC->pcState(val); } /** Reads this thread's PC. */ Addr instAddr() const override { return actualTC->instAddr(); } /** Reads this thread's next PC. */ Addr nextInstAddr() const override { return actualTC->nextInstAddr(); } /** Reads this thread's next PC. */ MicroPC microPC() const override { return actualTC->microPC(); } RegVal readMiscRegNoEffect(RegIndex misc_reg) const override { return actualTC->readMiscRegNoEffect(misc_reg); } RegVal readMiscReg(RegIndex misc_reg) override { return actualTC->readMiscReg(misc_reg); } void setMiscRegNoEffect(RegIndex misc_reg, RegVal val) override { 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(RegIndex misc_reg, RegVal val) override { 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 override { return actualTC->flattenRegId(regId); } unsigned readStCondFailures() const override { return actualTC->readStCondFailures(); } void setStCondFailures(unsigned sc_failures) override { actualTC->setStCondFailures(sc_failures); } RegVal readIntRegFlat(RegIndex idx) const override { return actualTC->readIntRegFlat(idx); } void setIntRegFlat(RegIndex idx, RegVal val) override { actualTC->setIntRegFlat(idx, val); } RegVal readFloatRegFlat(RegIndex idx) const override { return actualTC->readFloatRegFlat(idx); } void setFloatRegFlat(RegIndex idx, RegVal val) override { actualTC->setFloatRegFlat(idx, val); } const TheISA::VecRegContainer & readVecRegFlat(RegIndex idx) const override { return actualTC->readVecRegFlat(idx); } /** * Read vector register for modification, flat indexing. */ TheISA::VecRegContainer & getWritableVecRegFlat(RegIndex idx) override { return actualTC->getWritableVecRegFlat(idx); } void setVecRegFlat(RegIndex idx, const TheISA::VecRegContainer& val) override { actualTC->setVecRegFlat(idx, val); } const TheISA::VecElem & readVecElemFlat(RegIndex idx, const ElemIndex& elem_idx) const override { return actualTC->readVecElemFlat(idx, elem_idx); } void setVecElemFlat(RegIndex idx, const ElemIndex& elem_idx, const TheISA::VecElem& val) override { actualTC->setVecElemFlat(idx, elem_idx, val); } const TheISA::VecPredRegContainer & readVecPredRegFlat(RegIndex idx) const override { return actualTC->readVecPredRegFlat(idx); } TheISA::VecPredRegContainer & getWritableVecPredRegFlat(RegIndex idx) override { return actualTC->getWritableVecPredRegFlat(idx); } void setVecPredRegFlat(RegIndex idx, const TheISA::VecPredRegContainer& val) override { actualTC->setVecPredRegFlat(idx, val); } RegVal readCCRegFlat(RegIndex idx) const override { return actualTC->readCCRegFlat(idx); } void setCCRegFlat(RegIndex idx, RegVal val) override { actualTC->setCCRegFlat(idx, val); } // hardware transactional memory void htmAbortTransaction(uint64_t htm_uid, HtmFailureFaultCause cause) override { panic("function not implemented"); } BaseHTMCheckpointPtr& getHtmCheckpointPtr() override { return actualTC->getHtmCheckpointPtr(); } void setHtmCheckpointPtr(BaseHTMCheckpointPtr new_cpt) override { panic("function not implemented"); } }; } // namespace gem5 #endif // __CPU_CHECKER_EXEC_CONTEXT_HH__