summaryrefslogtreecommitdiff
path: root/cpu/o3/cpu.hh
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/o3/cpu.hh')
-rw-r--r--cpu/o3/cpu.hh380
1 files changed, 287 insertions, 93 deletions
diff --git a/cpu/o3/cpu.hh b/cpu/o3/cpu.hh
index 6577e46e4..789729e61 100644
--- a/cpu/o3/cpu.hh
+++ b/cpu/o3/cpu.hh
@@ -26,18 +26,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-//Todo: Add in a lot of the functions that are ISA specific. Also define
-//the functions that currently exist within the base cpu class. Define
-//everything for the simobject stuff so it can be serialized and
-//instantiated, add in debugging statements everywhere. Have CPU schedule
-//itself properly. Threads!
-// Avoid running stages and advancing queues if idle/stalled.
-
-#ifndef __CPU_O3_CPU_FULL_CPU_HH__
-#define __CPU_O3_CPU_FULL_CPU_HH__
+#ifndef __CPU_O3_FULL_CPU_HH__
+#define __CPU_O3_FULL_CPU_HH__
#include <iostream>
#include <list>
+#include <queue>
+#include <set>
#include <vector>
#include "base/statistics.hh"
@@ -47,10 +42,14 @@
#include "cpu/cpu_exec_context.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/cpu_policy.hh"
+#include "cpu/o3/scoreboard.hh"
+#include "cpu/o3/thread_state.hh"
#include "sim/process.hh"
+template <class>
+class Checker;
class ExecContext;
-class FunctionalMemory;
+class MemInterface;
class Process;
class BaseFullCPU : public BaseCPU
@@ -59,11 +58,9 @@ class BaseFullCPU : public BaseCPU
public:
typedef BaseCPU::Params Params;
-#if FULL_SYSTEM
- BaseFullCPU(Params &params);
-#else
- BaseFullCPU(Params &params);
-#endif // FULL_SYSTEM
+ BaseFullCPU(Params *params);
+
+ void regStats();
protected:
int cpu_id;
@@ -78,40 +75,52 @@ class FullO3CPU : public BaseFullCPU
typedef typename Impl::Params Params;
typedef typename Impl::DynInstPtr DynInstPtr;
+ typedef O3ThreadState<Impl> Thread;
+
+ typedef typename std::list<DynInstPtr>::iterator ListIt;
+
public:
enum Status {
Running,
Idle,
Halted,
- Blocked // ?
+ Blocked,
+ SwitchedOut
};
+ /** Overall CPU status. */
Status _status;
private:
class TickEvent : public Event
{
private:
+ /** Pointer to the CPU. */
FullO3CPU<Impl> *cpu;
public:
+ /** Constructs a tick event. */
TickEvent(FullO3CPU<Impl> *c);
+
+ /** Processes a tick event, calling tick() on the CPU. */
void process();
+ /** Returns the description of the tick event. */
const char *description();
};
+ /** The tick event used for scheduling CPU ticks. */
TickEvent tickEvent;
- /// Schedule tick event, regardless of its current state.
+ /** Schedule tick event, regardless of its current state. */
void scheduleTickEvent(int delay)
{
if (tickEvent.squashed())
- tickEvent.reschedule(curTick + delay);
+ tickEvent.reschedule(curTick + cycles(delay));
else if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + delay);
+ tickEvent.schedule(curTick + cycles(delay));
}
- /// Unschedule tick event, regardless of its current state.
+ /** Unschedule tick event, regardless of its current state. */
void unscheduleTickEvent()
{
if (tickEvent.scheduled())
@@ -119,25 +128,89 @@ class FullO3CPU : public BaseFullCPU
}
public:
- FullO3CPU(Params &params);
+ /** Constructs a CPU with the given parameters. */
+ FullO3CPU(Params *params);
+ /** Destructor. */
~FullO3CPU();
+ /** Registers statistics. */
void fullCPURegStats();
+ /** Ticks CPU, calling tick() on each stage, and checking the overall
+ * activity to see if the CPU should deschedule itself.
+ */
void tick();
+ /** Initialize the CPU */
void init();
- void activateContext(int thread_num, int delay);
- void suspendContext(int thread_num);
- void deallocateContext(int thread_num);
- void haltContext(int thread_num);
+ /** Setup CPU to insert a thread's context */
+ void insertThread(unsigned tid);
+
+ /** Remove all of a thread's context from CPU */
+ void removeThread(unsigned tid);
+
+ /** Count the Total Instructions Committed in the CPU. */
+ virtual Counter totalInstructions() const
+ {
+ Counter total(0);
+
+ for (int i=0; i < thread.size(); i++)
+ total += thread[i]->numInst;
+
+ return total;
+ }
+
+ /** Add Thread to Active Threads List. */
+ void activateContext(int tid, int delay);
+
+ /** Remove Thread from Active Threads List */
+ void suspendContext(int tid);
+
+ /** Remove Thread from Active Threads List &&
+ * Remove Thread Context from CPU.
+ */
+ void deallocateContext(int tid);
+
+ /** Remove Thread from Active Threads List &&
+ * Remove Thread Context from CPU.
+ */
+ void haltContext(int tid);
+
+ /** Activate a Thread When CPU Resources are Available. */
+ void activateWhenReady(int tid);
- void switchOut();
+ /** Add or Remove a Thread Context in the CPU. */
+ void doContextSwitch();
+
+ /** Update The Order In Which We Process Threads. */
+ void updateThreadPriority();
+
+ /** Executes a syscall on this cycle.
+ * ---------------------------------------
+ * Note: this is a virtual function. CPU-Specific
+ * functionality defined in derived classes
+ */
+ virtual void syscall(int tid) {}
+
+ /** Check if there are any system calls pending. */
+ void checkSyscalls();
+
+ /** Switches out this CPU.
+ * @todo: Implement this.
+ */
+ void switchOut(Sampler *sampler);
+
+ void signalSwitched();
+
+ /** Takes over from another CPU.
+ * @todo: Implement this.
+ */
void takeOverFrom(BaseCPU *oldCPU);
/** Get the current instruction sequence number, and increment it. */
- InstSeqNum getAndIncrementInstSeq();
+ InstSeqNum getAndIncrementInstSeq()
+ { return globalSeqNum++; }
#if FULL_SYSTEM
/** Check if this address is a valid instruction address. */
@@ -147,21 +220,28 @@ class FullO3CPU : public BaseFullCPU
bool validDataAddr(Addr addr) { return true; }
/** Get instruction asid. */
- int getInstAsid()
- { return regFile.miscRegs.getInstAsid(); }
+ int getInstAsid(unsigned tid)
+ { return regFile.miscRegs[tid].getInstAsid(); }
/** Get data asid. */
- int getDataAsid()
- { return regFile.miscRegs.getDataAsid(); }
+ int getDataAsid(unsigned tid)
+ { return regFile.miscRegs[tid].getDataAsid(); }
#else
- bool validInstAddr(Addr addr)
- { return thread[0]->validInstAddr(addr); }
+ /** Check if this address is a valid instruction address. */
+ bool validInstAddr(Addr addr,unsigned tid)
+ { return thread[tid]->validInstAddr(addr); }
- bool validDataAddr(Addr addr)
- { return thread[0]->validDataAddr(addr); }
+ /** Check if this address is a valid data address. */
+ bool validDataAddr(Addr addr,unsigned tid)
+ { return thread[tid]->validDataAddr(addr); }
- int getInstAsid() { return thread[0]->getInstAsid(); }
- int getDataAsid() { return thread[0]->getDataAsid(); }
+ /** Get instruction asid. */
+ int getInstAsid(unsigned tid)
+ { return thread[tid]->asid; }
+
+ /** Get data asid. */
+ int getDataAsid(unsigned tid)
+ { return thread[tid]->asid; }
#endif
@@ -184,29 +264,40 @@ class FullO3CPU : public BaseFullCPU
void setFloatRegInt(int reg_idx, uint64_t val);
- uint64_t readPC();
+ uint64_t readArchIntReg(int reg_idx, unsigned tid);
+
+ float readArchFloatRegSingle(int reg_idx, unsigned tid);
+
+ double readArchFloatRegDouble(int reg_idx, unsigned tid);
+
+ uint64_t readArchFloatRegInt(int reg_idx, unsigned tid);
+
+ void setArchIntReg(int reg_idx, uint64_t val, unsigned tid);
+
+ void setArchFloatRegSingle(int reg_idx, float val, unsigned tid);
+
+ void setArchFloatRegDouble(int reg_idx, double val, unsigned tid);
+
+ void setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid);
- void setNextPC(uint64_t val);
+ uint64_t readPC(unsigned tid);
- void setPC(Addr new_PC);
+ void setPC(Addr new_PC,unsigned tid);
+
+ uint64_t readNextPC(unsigned tid);
+
+ void setNextPC(uint64_t val,unsigned tid);
/** Function to add instruction onto the head of the list of the
* instructions. Used when new instructions are fetched.
*/
- void addInst(DynInstPtr &inst);
+ ListIt addInst(DynInstPtr &inst);
/** Function to tell the CPU that an instruction has completed. */
- void instDone();
-
- /** Remove all instructions in back of the given instruction, but leave
- * that instruction in the list. This is useful in a squash, when there
- * are instructions in this list that don't exist in structures such as
- * the ROB. The instruction doesn't have to be the last instruction in
- * the list, but will be once this function completes.
- * @todo: Remove only up until that inst? Squashed inst is most likely
- * valid.
- */
- void removeBackInst(DynInstPtr &inst);
+ void instDone(unsigned tid);
+
+ /** Add Instructions to the CPU Remove List*/
+ void addToRemoveList(DynInstPtr &inst);
/** Remove an instruction from the front of the list. It is expected
* that there are no instructions in front of it (that is, none are older
@@ -218,10 +309,14 @@ class FullO3CPU : public BaseFullCPU
void removeFrontInst(DynInstPtr &inst);
/** Remove all instructions that are not currently in the ROB. */
- void removeInstsNotInROB();
+ void removeInstsNotInROB(unsigned tid);
/** Remove all instructions younger than the given sequence number. */
- void removeInstsUntil(const InstSeqNum &seq_num);
+ void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
+
+ inline void squashInstIt(const ListIt &instIt, const unsigned &tid);
+
+ void cleanUpRemovedInsts();
/** Remove all instructions from the list. */
void removeAllInsts();
@@ -236,43 +331,38 @@ class FullO3CPU : public BaseFullCPU
public:
/** List of all the instructions in flight. */
- list<DynInstPtr> instList;
+ std::list<DynInstPtr> instList;
+
+ /** List of all the instructions that will be removed at the end of this
+ * cycle.
+ */
+ std::queue<ListIt> removeList;
+
+//#ifdef DEBUG
+ std::set<InstSeqNum> snList;
+//#endif
+
+ /** Records if instructions need to be removed this cycle due to being
+ * retired or squashed.
+ */
+ bool removeInstsThisCycle;
- //not sure these should be private.
protected:
/** The fetch stage. */
typename CPUPolicy::Fetch fetch;
- /** The fetch stage's status. */
- typename CPUPolicy::Fetch::Status fetchStatus;
-
/** The decode stage. */
typename CPUPolicy::Decode decode;
- /** The decode stage's status. */
- typename CPUPolicy::Decode::Status decodeStatus;
-
/** The dispatch stage. */
typename CPUPolicy::Rename rename;
- /** The dispatch stage's status. */
- typename CPUPolicy::Rename::Status renameStatus;
-
/** The issue/execute/writeback stages. */
typename CPUPolicy::IEW iew;
- /** The issue/execute/writeback stage's status. */
- typename CPUPolicy::IEW::Status iewStatus;
-
/** The commit stage. */
typename CPUPolicy::Commit commit;
- /** The fetch stage's status. */
- typename CPUPolicy::Commit::Status commitStatus;
-
- //Might want to just pass these objects in to the constructors of the
- //appropriate stage. regFile is in iew, freeList in dispatch, renameMap
- //in dispatch, and the rob in commit.
/** The register file. */
typename CPUPolicy::RegFile regFile;
@@ -280,12 +370,33 @@ class FullO3CPU : public BaseFullCPU
typename CPUPolicy::FreeList freeList;
/** The rename map. */
- typename CPUPolicy::RenameMap renameMap;
+ typename CPUPolicy::RenameMap renameMap[Impl::MaxThreads];
+
+ /** The commit rename map. */
+ typename CPUPolicy::RenameMap commitRenameMap[Impl::MaxThreads];
/** The re-order buffer. */
typename CPUPolicy::ROB rob;
+ /** Active Threads List */
+ std::list<unsigned> activeThreads;
+
+ /** Integer Register Scoreboard */
+ Scoreboard scoreboard;
+
public:
+ /** Enum to give each stage a specific index, so when calling
+ * activateStage() or deactivateStage(), they can specify which stage
+ * is being activated/deactivated.
+ */
+ enum StageIdx {
+ FetchIdx,
+ DecodeIdx,
+ RenameIdx,
+ IEWIdx,
+ CommitIdx,
+ NumStages };
+
/** Typedefs from the Impl to get the structs that each of the
* time buffers should use.
*/
@@ -314,46 +425,129 @@ class FullO3CPU : public BaseFullCPU
/** The IEW stage's instruction queue. */
TimeBuffer<IEWStruct> iewQueue;
+ private:
+ /** Time buffer that tracks if any cycles has active communication in them.
+ * It should be as long as the longest communication latency in the system.
+ * Each time any time buffer is written, the activity buffer should also
+ * be written to. The activityBuffer is advanced along with all the other
+ * time buffers, so it should always have a 1 somewhere in it only if there
+ * is active communication in a time buffer.
+ */
+ TimeBuffer<bool> activityBuffer;
+
+ /** Tracks how many stages and cycles of time buffer have activity. Stages
+ * increment this count when they switch to active, and decrement it when
+ * they switch to inactive. Whenever a cycle that previously had no
+ * information is written in the time buffer, this is incremented. When
+ * a cycle that had information exits the time buffer due to age, this
+ * count is decremented. When the count is 0, there is no activity in the
+ * CPU, and it can be descheduled.
+ */
+ int activityCount;
+
+ /** Records if there has been activity this cycle. */
+ bool activity;
+
+ /** Records which stages are active/inactive. */
+ bool stageActive[NumStages];
+
public:
- /** The temporary exec context to support older accessors. */
- CPUExecContext *cpuXC;
+ /** Wakes the CPU, rescheduling the CPU if it's not already active. */
+ void wakeCPU();
+ /** Records that there is activity this cycle. */
+ void activityThisCycle();
+ /** Advances the activity buffer, decrementing the activityCount if active
+ * communication just left the time buffer, and descheduling the CPU if
+ * there is no activity.
+ */
+ void advanceActivityBuffer();
+ /** Marks a stage as active. */
+ void activateStage(const StageIdx idx);
+ /** Deactivates a stage. */
+ void deactivateStage(const StageIdx idx);
- /** Temporary function to get pointer to exec context. */
- ExecContext *xcBase()
- {
- return thread[0]->getProxy();
- }
+ /** Gets a free thread id. Use if thread ids change across system. */
+ int getFreeTid();
- CPUExecContext *cpuXCBase()
+ public:
+ /** Temporary function to get pointer to exec context. */
+ ExecContext *xcBase(unsigned tid)
{
- return thread[0];
+ return thread[tid]->getXCProxy();
}
+ /** The global sequence number counter. */
InstSeqNum globalSeqNum;
+ Checker<DynInstPtr> *checker;
+
#if FULL_SYSTEM
+ /** Pointer to the system. */
System *system;
+ /** Pointer to the memory controller. */
MemoryController *memCtrl;
+ /** Pointer to physical memory. */
PhysicalMemory *physmem;
-
- AlphaITB *itb;
- AlphaDTB *dtb;
-
-// SWContext *swCtx;
#endif
- std::vector<CPUExecContext *> thread;
+ /** Pointer to memory. */
FunctionalMemory *mem;
+ Sampler *sampler;
+
+ int switchCount;
+
+ // List of all ExecContexts.
+ std::vector<Thread *> thread;
+
+#if 0
+ /** Page table pointer. */
+ PageTable *pTable;
+#endif
+
+ /** Pointer to the icache interface. */
MemInterface *icacheInterface;
+ /** Pointer to the dcache interface. */
MemInterface *dcacheInterface;
+ /** Whether or not the CPU should defer its registration. */
bool deferRegistration;
- Counter numInsts;
-
- Counter funcExeInst;
+ /** Is there a context switch pending? */
+ bool contextSwitch;
+
+ /** Threads Scheduled to Enter CPU */
+ std::list<int> cpuWaitList;
+
+ /** The cycle that the CPU was last running, used for statistics. */
+ Tick lastRunningCycle;
+
+ /** Number of Threads CPU can process */
+ unsigned numThreads;
+
+ /** Mapping for system thread id to cpu id */
+ std::map<unsigned,unsigned> threadMap;
+
+ /** Available thread ids in the cpu*/
+ std::vector<unsigned> tids;
+
+ /** Stat for total number of times the CPU is descheduled. */
+ Stats::Scalar<> timesIdled;
+ /** Stat for total number of cycles the CPU spends descheduled. */
+ Stats::Scalar<> idleCycles;
+ /** Stat for the number of committed instructions per thread. */
+ Stats::Vector<> committedInsts;
+ /** Stat for the total number of committed instructions. */
+ Stats::Scalar<> totalCommittedInsts;
+ /** Stat for the CPI per thread. */
+ Stats::Formula cpi;
+ /** Stat for the total CPI. */
+ Stats::Formula totalCpi;
+ /** Stat for the IPC per thread. */
+ Stats::Formula ipc;
+ /** Stat for the total IPC. */
+ Stats::Formula totalIpc;
};
#endif