/*
+ * Copyright (c) 2011-2012,2015 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) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
#ifndef __CPU_SIMPLE_BASE_HH__
#define __CPU_SIMPLE_BASE_HH__
-#include "arch/predecoder.hh"
#include "base/statistics.hh"
-#include "config/full_system.hh"
+#include "config/the_isa.hh"
#include "cpu/base.hh"
-#include "cpu/simple_thread.hh"
+#include "cpu/checker/cpu.hh"
+#include "cpu/exec_context.hh"
#include "cpu/pc_event.hh"
+#include "cpu/simple_thread.hh"
#include "cpu/static_inst.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"
+#include "sim/full_system.hh"
#include "sim/system.hh"
// forward declarations
-#if FULL_SYSTEM
-class Processor;
-namespace TheISA
-{
- class ITB;
- class DTB;
-}
-class MemObject;
-
-#else
-
+class Checkpoint;
class Process;
-
-#endif // FULL_SYSTEM
-
-class RemoteGDB;
-class GDBListener;
+class Processor;
+class ThreadContext;
namespace TheISA
{
- class Predecoder;
+ class DTB;
+ class ITB;
}
-class ThreadContext;
-class Checkpoint;
namespace Trace {
class InstRecord;
}
+struct BaseSimpleCPUParams;
+class BPredUnit;
+class SimpleExecContext;
class BaseSimpleCPU : public BaseCPU
{
protected:
- typedef TheISA::MiscReg MiscReg;
- typedef TheISA::FloatReg FloatReg;
- typedef TheISA::FloatRegBits FloatRegBits;
+ ThreadID curThread;
+ BPredUnit *branchPred;
- protected:
- Trace::InstRecord *traceData;
-
- inline void checkPcEventQueue() {
- Addr oldpc;
- do {
- oldpc = thread->readPC();
- system->pcEventQueue.service(tc);
- } while (oldpc != thread->readPC());
- }
-
- public:
- void post_interrupt(int int_num, int index);
-
- void zero_fill_64(Addr addr) {
- static int warned = 0;
- if (!warned) {
- warn ("WH64 is not implemented");
- warned = 1;
- }
- };
+ void checkPcEventQueue();
+ void swapActiveThread();
public:
- struct Params : public BaseCPU::Params
- {
- TheISA::ITB *itb;
- TheISA::DTB *dtb;
-#if !FULL_SYSTEM
- Process *process;
-#endif
- };
- BaseSimpleCPU(Params *params);
+ BaseSimpleCPU(BaseSimpleCPUParams *params);
virtual ~BaseSimpleCPU();
-
+ void wakeup(ThreadID tid) override;
+ void init() override;
public:
- /** SimpleThread object, provides all the architectural state. */
- SimpleThread *thread;
-
- /** ThreadContext object, provides an interface for external
- * objects to modify this thread's state.
- */
- ThreadContext *tc;
- protected:
- int cpuId;
-
- public:
-
-#if FULL_SYSTEM
- Addr dbg_vtophys(Addr addr);
+ Trace::InstRecord *traceData;
+ CheckerCPU *checker;
- bool interval_stats;
-#endif
+ std::vector<SimpleExecContext*> threadInfo;
+ std::list<ThreadID> activeThreads;
- // current instruction
+ /** Current instruction */
TheISA::MachInst inst;
-
- // The predecoder
- TheISA::Predecoder predecoder;
-
StaticInstPtr curStaticInst;
StaticInstPtr curMacroStaticInst;
- //This is the offset from the current pc that fetch should be performed at
- Addr fetchOffset;
- //This flag says to stay at the current pc. This is useful for
- //instructions which go beyond MachInst boundaries.
- bool stayAtPC;
+ protected:
+ enum Status {
+ Idle,
+ Running,
+ Faulting,
+ ITBWaitResponse,
+ IcacheRetry,
+ IcacheWaitResponse,
+ IcacheWaitSwitch,
+ DTBWaitResponse,
+ DcacheRetry,
+ DcacheWaitResponse,
+ DcacheWaitSwitch,
+ };
+
+ Status _status;
+
+ public:
+ Addr dbg_vtophys(Addr addr);
+
void checkForInterrupts();
- Fault setupFetchRequest(Request *req);
+ void setupFetchRequest(Request *req);
void preExecute();
void postExecute();
- void advancePC(Fault fault);
+ void advancePC(const Fault &fault);
- virtual void deallocateContext(int thread_num);
- virtual void haltContext(int thread_num);
+ void haltContext(ThreadID thread_num) override;
// statistics
- virtual void regStats();
- virtual void resetStats();
-
- // number of simulated instructions
- Counter numInst;
- Counter startNumInst;
- Stats::Scalar<> numInsts;
-
- void countInst()
- {
- numInst++;
- numInsts++;
-
- thread->funcExeInst++;
- }
-
- virtual Counter totalInstructions() const
- {
- return numInst - startNumInst;
- }
-
- // Mask to align PCs to MachInst sized boundaries
- static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1);
-
- // number of simulated memory references
- Stats::Scalar<> numMemRefs;
-
- // number of simulated loads
- Counter numLoad;
- Counter startNumLoad;
-
- // number of idle cycles
- Stats::Average<> notIdleFraction;
- Stats::Formula idleFraction;
-
- // number of cycles stalled for I-cache responses
- Stats::Scalar<> icacheStallCycles;
- Counter lastIcacheStall;
-
- // number of cycles stalled for I-cache retries
- Stats::Scalar<> icacheRetryCycles;
- Counter lastIcacheRetry;
-
- // number of cycles stalled for D-cache responses
- Stats::Scalar<> dcacheStallCycles;
- Counter lastDcacheStall;
-
- // number of cycles stalled for D-cache retries
- Stats::Scalar<> dcacheRetryCycles;
- Counter lastDcacheRetry;
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string §ion);
-
- // These functions are only used in CPU models that split
- // effective address computation from the actual memory access.
- void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); }
- Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n");
- M5_DUMMY_RETURN}
-
- void prefetch(Addr addr, unsigned flags)
- {
- // need to do this...
- }
-
- void writeHint(Addr addr, int size, unsigned flags)
- {
- // need to do this...
- }
-
-
- Fault copySrcTranslate(Addr src);
-
- Fault copy(Addr dest);
-
- // 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).
-
- uint64_t readIntRegOperand(const StaticInst *si, int idx)
- {
- return thread->readIntReg(si->srcRegIdx(idx));
- }
-
- FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return thread->readFloatReg(reg_idx, width);
- }
-
- FloatReg readFloatRegOperand(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return thread->readFloatReg(reg_idx);
- }
-
- FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx,
- int width)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return thread->readFloatRegBits(reg_idx, width);
- }
-
- FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return thread->readFloatRegBits(reg_idx);
- }
-
- void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
- {
- thread->setIntReg(si->destRegIdx(idx), val);
- }
-
- void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
- int width)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- thread->setFloatReg(reg_idx, val, width);
- }
-
- void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- thread->setFloatReg(reg_idx, val);
- }
-
- void setFloatRegOperandBits(const StaticInst *si, int idx,
- FloatRegBits val, int width)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- thread->setFloatRegBits(reg_idx, val, width);
- }
-
- void setFloatRegOperandBits(const StaticInst *si, int idx,
- FloatRegBits val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- thread->setFloatRegBits(reg_idx, val);
- }
-
- uint64_t readPC() { return thread->readPC(); }
- uint64_t readMicroPC() { return thread->readMicroPC(); }
- uint64_t readNextPC() { return thread->readNextPC(); }
- uint64_t readNextMicroPC() { return thread->readNextMicroPC(); }
- uint64_t readNextNPC() { return thread->readNextNPC(); }
-
- void setPC(uint64_t val) { thread->setPC(val); }
- void setMicroPC(uint64_t val) { thread->setMicroPC(val); }
- void setNextPC(uint64_t val) { thread->setNextPC(val); }
- void setNextMicroPC(uint64_t val) { thread->setNextMicroPC(val); }
- void setNextNPC(uint64_t val) { thread->setNextNPC(val); }
-
- MiscReg readMiscRegNoEffect(int misc_reg)
- {
- return thread->readMiscRegNoEffect(misc_reg);
- }
-
- MiscReg readMiscReg(int misc_reg)
- {
- return thread->readMiscReg(misc_reg);
- }
-
- void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
- {
- return thread->setMiscRegNoEffect(misc_reg, val);
- }
-
- void setMiscReg(int misc_reg, const MiscReg &val)
- {
- return thread->setMiscReg(misc_reg, val);
- }
-
- MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
- return thread->readMiscRegNoEffect(reg_idx);
- }
-
- MiscReg readMiscRegOperand(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
- return thread->readMiscReg(reg_idx);
- }
-
- void setMiscRegOperandNoEffect(const StaticInst *si, int idx, const MiscReg &val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
- return thread->setMiscRegNoEffect(reg_idx, val);
- }
-
- void setMiscRegOperand(
- const StaticInst *si, int idx, const MiscReg &val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
- return thread->setMiscReg(reg_idx, val);
- }
+ void regStats() override;
+ void resetStats() override;
- unsigned readStCondFailures() {
- return thread->readStCondFailures();
- }
+ void startup() override;
- void setStCondFailures(unsigned sc_failures) {
- thread->setStCondFailures(sc_failures);
- }
+ virtual Fault readMem(Addr addr, uint8_t* data, unsigned size,
+ Request::Flags flags) = 0;
- MiscReg readRegOtherThread(int regIdx, int tid = -1)
- {
- panic("Simple CPU models do not support multithreaded "
- "register access.\n");
- }
+ virtual Fault initiateMemRead(Addr addr, unsigned size,
+ Request::Flags flags) = 0;
- void setRegOtherThread(int regIdx, const MiscReg &val, int tid = -1)
- {
- panic("Simple CPU models do not support multithreaded "
- "register access.\n");
- }
+ virtual Fault writeMem(uint8_t* data, unsigned size, Addr addr,
+ Request::Flags flags, uint64_t* res) = 0;
- //Fault CacheOp(uint8_t Op, Addr EA);
+ void countInst();
+ Counter totalInsts() const override;
+ Counter totalOps() const override;
-#if FULL_SYSTEM
- Fault hwrei() { return thread->hwrei(); }
- void ev5_trap(Fault fault) { fault->invoke(tc); }
- bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
-#else
- void syscall(int64_t callnum) { thread->syscall(callnum); }
-#endif
+ void serializeThread(CheckpointOut &cp, ThreadID tid) const override;
+ void unserializeThread(CheckpointIn &cp, ThreadID tid) override;
- bool misspeculating() { return thread->misspeculating(); }
- ThreadContext *tcBase() { return tc; }
};
#endif // __CPU_SIMPLE_BASE_HH__