blob: 1de5b370aed4a1b087e39a987bae644b8840469e [file] [log] [blame]
/*
* 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);
if (reg.is(InvalidRegClass))
return;
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 %#x.\n",
reg.className(), reg_class.regName(arch_reg), idx, val);
reg_file.reg(idx) = val;
}
void
setRegFlat(const RegId &reg, RegVal val) override
{
if (reg.is(InvalidRegClass))
return;
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 %#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__