/*
+ * Copyright (c) 2012-2013 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) 2007 MIPS Technologies, Inc.
* All rights reserved.
*
#include <vector>
#include "arch/isa_traits.hh"
-#include "arch/types.hh"
#include "arch/registers.hh"
+#include "arch/types.hh"
#include "base/statistics.hh"
-#include "base/timebuf.hh"
#include "base/types.hh"
-#include "config/full_system.hh"
#include "config/the_isa.hh"
-#include "cpu/activity.hh"
-#include "cpu/base.hh"
-#include "cpu/simple_thread.hh"
#include "cpu/inorder/inorder_dyn_inst.hh"
-#include "cpu/inorder/pipeline_traits.hh"
#include "cpu/inorder/pipeline_stage.hh"
-#include "cpu/inorder/thread_state.hh"
+#include "cpu/inorder/pipeline_traits.hh"
#include "cpu/inorder/reg_dep_map.hh"
+#include "cpu/inorder/thread_state.hh"
#include "cpu/o3/dep_graph.hh"
#include "cpu/o3/rename_map.hh"
+#include "cpu/activity.hh"
+#include "cpu/base.hh"
+#include "cpu/reg_class.hh"
+#include "cpu/simple_thread.hh"
+#include "cpu/timebuf.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"
#include "sim/process.hh"
+class CacheUnit;
class ThreadContext;
class MemInterface;
class MemObject;
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
+ typedef TheISA::CCReg CCReg;
typedef TheISA::MiscReg MiscReg;
+ typedef TheISA::RegIndex RegIndex;
//DynInstPtr TypeDefs
typedef ThePipeline::DynInstPtr DynInstPtr;
typedef TimeBuffer<InterStageStruct> StageQueue;
friend class Resource;
-
+
public:
/** Constructs a CPU with the given parameters. */
InOrderCPU(Params *params);
+ /* Destructor */
+ ~InOrderCPU();
+
+ void verifyMemoryMode() const;
+
+ /** Return a reference to the data port. */
+ virtual MasterPort &getDataPort() { return dataPort; }
+
+ /** Return a reference to the instruction port. */
+ virtual MasterPort &getInstPort() { return instPort; }
/** CPU ID */
int cpu_id;
+ // SE Mode ASIDs
+ ThreadID asid[ThePipeline::MaxThreads];
+
/** Type of core that this is */
std::string coreType;
+ // Only need for SE MODE
+ enum ThreadModel {
+ Single,
+ SMT,
+ SwitchOnCacheMiss
+ };
+
+ ThreadModel threadModel;
+
int readCpuId() { return cpu_id; }
void setCpuId(int val) { cpu_id = val; }
/** Overall CPU status. */
Status _status;
-
private:
+
+ /**
+ * CachePort class for the in-order CPU, interacting with a
+ * specific CacheUnit in the pipeline.
+ */
+ class CachePort : public MasterPort
+ {
+
+ private:
+ /** Pointer to cache unit */
+ CacheUnit *cacheUnit;
+
+ public:
+ /** Default constructor. */
+ CachePort(CacheUnit *_cacheUnit, const std::string& name);
+
+ protected:
+
+ /** Timing version of receive */
+ bool recvTimingResp(PacketPtr pkt);
+
+ /** Handles doing a retry of a failed timing request. */
+ void recvRetry();
+
+ /** Ignoring snoops for now. */
+ void recvTimingSnoopReq(PacketPtr pkt) { }
+ };
+
/** Define TickEvent for the CPU */
class TickEvent : public Event
{
void process();
/** Returns the description of the tick event. */
- const char *description();
+ const char *description() const;
};
/** The tick event used for scheduling CPU ticks. */
TickEvent tickEvent;
/** Schedule tick event, regardless of its current state. */
- void scheduleTickEvent(int delay)
+ void scheduleTickEvent(Cycles delay)
{
- if (tickEvent.squashed())
- mainEventQueue.reschedule(&tickEvent, nextCycle(curTick + ticks(delay)));
- else if (!tickEvent.scheduled())
- mainEventQueue.schedule(&tickEvent, nextCycle(curTick + ticks(delay)));
+ assert(!tickEvent.scheduled() || tickEvent.squashed());
+ reschedule(&tickEvent, clockEdge(delay), true);
}
/** Unschedule tick event, regardless of its current state. */
// pool event.
enum CPUEventType {
ActivateThread,
- DeallocateThread,
+ ActivateNextReadyThread,
+ DeactivateThread,
+ HaltThread,
SuspendThread,
- DisableThreads,
- EnableThreads,
- DisableVPEs,
- EnableVPEs,
Trap,
- InstGraduated,
- SquashAll,
+ Syscall,
+ SquashFromMemStall,
UpdatePCs,
NumCPUEvents
};
static std::string eventNames[NumCPUEvents];
+ enum CPUEventPri {
+ InOrderCPU_Pri = Event::CPU_Tick_Pri,
+ Syscall_Pri = Event::CPU_Tick_Pri + 9,
+ ActivateNextReadyThread_Pri = Event::CPU_Tick_Pri + 10
+ };
+
/** Define CPU Event */
class CPUEvent : public Event
{
public:
CPUEventType cpuEventType;
ThreadID tid;
- unsigned vpe;
+ DynInstPtr inst;
Fault fault;
-
+ unsigned vpe;
+ short syscall_num;
+
public:
/** Constructs a CPU event. */
CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, Fault fault,
- ThreadID _tid, unsigned _vpe);
+ ThreadID _tid, DynInstPtr inst, CPUEventPri event_pri);
/** Set Type of Event To Be Scheduled */
void setEvent(CPUEventType e_type, Fault _fault, ThreadID _tid,
- unsigned _vpe)
+ DynInstPtr _inst)
{
fault = _fault;
cpuEventType = e_type;
tid = _tid;
- vpe = _vpe;
+ inst = _inst;
+ vpe = 0;
}
- /** Processes a resource event. */
- virtual void process();
+ /** Processes a CPU event. */
+ void process();
- /** Returns the description of the resource event. */
- const char *description();
+ /** Returns the description of the CPU event. */
+ const char *description() const;
/** Schedule Event */
- void scheduleEvent(int delay);
+ void scheduleEvent(Cycles delay);
/** Unschedule This Event */
void unscheduleEvent();
/** Schedule a CPU Event */
void scheduleCpuEvent(CPUEventType cpu_event, Fault fault, ThreadID tid,
- unsigned vpe, unsigned delay = 0);
+ DynInstPtr inst, Cycles delay = Cycles(0),
+ CPUEventPri event_pri = InOrderCPU_Pri);
public:
+
+ /** Width (processing bandwidth) of each stage */
+ int stageWidth;
+
/** Interface between the CPU and CPU resources. */
ResourcePool *resPool;
- /** Instruction used to signify that there is no *real* instruction in buffer slot */
+ /** Instruction used to signify that there is no *real* instruction in
+ buffer slot */
+ DynInstPtr dummyInst[ThePipeline::MaxThreads];
DynInstPtr dummyBufferInst;
+ DynInstPtr dummyReqInst;
+ DynInstPtr dummyTrapInst[ThePipeline::MaxThreads];
/** Used by resources to signify a denied access to a resource. */
- ResourceRequest *dummyReq;
-
- /** Identifies the resource id that identifies a fetch
- * access unit.
- */
- unsigned fetchPortIdx;
-
- /** Identifies the resource id that identifies a ITB */
- unsigned itbIdx;
-
- /** Identifies the resource id that identifies a data
- * access unit.
- */
- unsigned dataPortIdx;
-
- /** Identifies the resource id that identifies a DTB */
- unsigned dtbIdx;
+ ResourceRequest *dummyReq[ThePipeline::MaxThreads];
/** The Pipeline Stages for the CPU */
PipelineStage *pipelineStage[ThePipeline::NumStages];
/** Program Counters */
- TheISA::IntReg PC[ThePipeline::MaxThreads];
- TheISA::IntReg nextPC[ThePipeline::MaxThreads];
- TheISA::IntReg nextNPC[ThePipeline::MaxThreads];
+ TheISA::PCState pc[ThePipeline::MaxThreads];
+
+ /** Last Committed PC */
+ TheISA::PCState lastCommittedPC[ThePipeline::MaxThreads];
/** The Register File for the CPU */
union {
FloatRegBits i[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
} floatRegs;
TheISA::IntReg intRegs[ThePipeline::MaxThreads][TheISA::NumIntRegs];
+#ifdef ISA_HAS_CC_REGS
+ TheISA::CCReg ccRegs[ThePipeline::MaxThreads][TheISA::NumCCRegs];
+#endif
/** ISA state */
- TheISA::ISA isa[ThePipeline::MaxThreads];
+ std::vector<TheISA::ISA *> isa;
/** Dependency Tracker for Integer & Floating Point Regs */
RegDepMap archRegDepMap[ThePipeline::MaxThreads];
TheISA::TLB *getITBPtr();
TheISA::TLB *getDTBPtr();
+ TheISA::Decoder *getDecoderPtr(unsigned tid);
+
+ /** Accessor Type for the SkedCache */
+ typedef uint32_t SkedID;
+
+ /** Cache of Instruction Schedule using the instruction's name as a key */
+ static m5::hash_map<SkedID, ThePipeline::RSkedPtr> skedCache;
+
+ typedef m5::hash_map<SkedID, ThePipeline::RSkedPtr>::iterator SkedCacheIt;
+
+ /** Initialized to last iterator in map, signifying a invalid entry
+ on map searches
+ */
+ SkedCacheIt endOfSkedIt;
+
+ ThePipeline::RSkedPtr frontEndSked;
+ ThePipeline::RSkedPtr faultSked;
+
+ /** Add a new instruction schedule to the schedule cache */
+ void addToSkedCache(DynInstPtr inst, ThePipeline::RSkedPtr inst_sked)
+ {
+ SkedID sked_id = genSkedID(inst);
+ assert(skedCache.find(sked_id) == skedCache.end());
+ skedCache[sked_id] = inst_sked;
+ }
+
+
+ /** Find a instruction schedule */
+ ThePipeline::RSkedPtr lookupSked(DynInstPtr inst)
+ {
+ SkedID sked_id = genSkedID(inst);
+ SkedCacheIt lookup_it = skedCache.find(sked_id);
+
+ if (lookup_it != endOfSkedIt) {
+ return (*lookup_it).second;
+ } else {
+ return NULL;
+ }
+ }
+
+ static const uint8_t INST_OPCLASS = 26;
+ static const uint8_t INST_LOAD = 25;
+ static const uint8_t INST_STORE = 24;
+ static const uint8_t INST_CONTROL = 23;
+ static const uint8_t INST_NONSPEC = 22;
+ static const uint8_t INST_DEST_REGS = 18;
+ static const uint8_t INST_SRC_REGS = 14;
+ static const uint8_t INST_SPLIT_DATA = 13;
+
+ inline SkedID genSkedID(DynInstPtr inst)
+ {
+ SkedID id = 0;
+ id = (inst->opClass() << INST_OPCLASS) |
+ (inst->isLoad() << INST_LOAD) |
+ (inst->isStore() << INST_STORE) |
+ (inst->isControl() << INST_CONTROL) |
+ (inst->isNonSpeculative() << INST_NONSPEC) |
+ (inst->numDestRegs() << INST_DEST_REGS) |
+ (inst->numSrcRegs() << INST_SRC_REGS) |
+ (inst->splitInst << INST_SPLIT_DATA);
+ return id;
+ }
+
+ ThePipeline::RSkedPtr createFrontEndSked();
+ ThePipeline::RSkedPtr createFaultSked();
+ ThePipeline::RSkedPtr createBackEndSked(DynInstPtr inst);
+
+ class StageScheduler {
+ private:
+ ThePipeline::RSkedPtr rsked;
+ int stageNum;
+ int nextTaskPriority;
+
+ public:
+ StageScheduler(ThePipeline::RSkedPtr _rsked, int stage_num)
+ : rsked(_rsked), stageNum(stage_num),
+ nextTaskPriority(0)
+ { }
+
+ void needs(int unit, int request) {
+ rsked->push(new ScheduleEntry(
+ stageNum, nextTaskPriority++, unit, request
+ ));
+ }
+
+ void needs(int unit, int request, int param) {
+ rsked->push(new ScheduleEntry(
+ stageNum, nextTaskPriority++, unit, request, param
+ ));
+ }
+ };
+
+ private:
+
+ /** Data port. Note that it has to appear after the resPool. */
+ CachePort dataPort;
+
+ /** Instruction port. Note that it has to appear after the resPool. */
+ CachePort instPort;
+
public:
/** Registers statistics. */
/** Initialize the CPU */
void init();
- /** Reset State in the CPU */
- void reset();
-
- /** Get a Memory Port */
- Port* getPort(const std::string &if_name, int idx = 0);
-
-#if FULL_SYSTEM
/** HW return from error interrupt. */
Fault hwrei(ThreadID tid);
bool simPalCheck(int palFunc, ThreadID tid);
+ void checkForInterrupts();
+
/** Returns the Fault for any valid interrupt. */
Fault getInterrupts();
/** Halts the CPU. */
void halt() { panic("Halt not implemented!\n"); }
- /** Update the Virt and Phys ports of all ThreadContexts to
- * reflect change in memory connections. */
- void updateMemPorts();
-
/** Check if this address is a valid instruction address. */
bool validInstAddr(Addr addr) { return true; }
/** Check if this address is a valid data address. */
bool validDataAddr(Addr addr) { return true; }
-#endif
- /** trap() - sets up a trap event on the cpuTraps to handle given fault.
- * trapCPU() - Traps to handle given fault
- */
- void trap(Fault fault, ThreadID tid, int delay = 0);
- void trapCPU(Fault fault, ThreadID tid);
+ /** Schedule a syscall on the CPU */
+ void syscallContext(Fault fault, ThreadID tid, DynInstPtr inst,
+ Cycles delay = Cycles(0));
+
+ /** Executes a syscall.*/
+ void syscall(int64_t callnum, ThreadID tid);
+
+ /** Schedule a trap on the CPU */
+ void trapContext(Fault fault, ThreadID tid, DynInstPtr inst,
+ Cycles delay = Cycles(0));
- /** Setup CPU to insert a thread's context */
- void insertThread(ThreadID tid);
+ /** Perform trap to Handle Given Fault */
+ void trap(Fault fault, ThreadID tid, DynInstPtr inst);
- /** Remove all of a thread's context from CPU */
- void removeThread(ThreadID tid);
+ /** Schedule thread activation on the CPU */
+ void activateContext(ThreadID tid, Cycles delay = Cycles(0));
/** Add Thread to Active Threads List. */
- void activateContext(ThreadID tid, int delay = 0);
void activateThread(ThreadID tid);
- /** Remove Thread from Active Threads List */
- void suspendContext(ThreadID tid, int delay = 0);
+ /** Activate Thread In Each Pipeline Stage */
+ void activateThreadInPipeline(ThreadID tid);
+
+ /** Schedule Thread Activation from Ready List */
+ void activateNextReadyContext(Cycles delay = Cycles(0));
+
+ /** Add Thread From Ready List to Active Threads List. */
+ void activateNextReadyThread();
+
+ /** Schedule a thread deactivation on the CPU */
+ void deactivateContext(ThreadID tid, Cycles delay = Cycles(0));
+
+ /** Remove from Active Thread List */
+ void deactivateThread(ThreadID tid);
+
+ /** Schedule a thread suspension on the CPU */
+ void suspendContext(ThreadID tid);
+
+ /** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
void suspendThread(ThreadID tid);
- /** Remove Thread from Active Threads List &&
- * Remove Thread Context from CPU.
+ /** Schedule a thread halt on the CPU */
+ void haltContext(ThreadID tid);
+
+ /** Halt Thread, Remove from Active Thread List, Place Thread on Halted
+ * Threads List
*/
- void deallocateContext(ThreadID tid, int delay = 0);
- void deallocateThread(ThreadID tid);
- void deactivateThread(ThreadID tid);
+ void haltThread(ThreadID tid);
+
+ /** squashFromMemStall() - sets up a squash event
+ * squashDueToMemStall() - squashes pipeline
+ * @note: maybe squashContext/squashThread would be better?
+ */
+ void squashFromMemStall(DynInstPtr inst, ThreadID tid,
+ Cycles delay = Cycles(0));
+ void squashDueToMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid);
+
+ void removePipelineStalls(ThreadID tid);
+ void squashThreadInPipeline(ThreadID tid);
+ void squashBehindMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid);
PipelineStage* getPipeStage(int stage_num);
return 0;
}
- /** Remove Thread from Active Threads List &&
- * Remove Thread Context from CPU.
- */
- void haltContext(ThreadID tid, int delay = 0);
-
- void removePipelineStalls(ThreadID tid);
-
- void squashThreadInPipeline(ThreadID tid);
-
- /// Notify the CPU to enable a virtual processor element.
- virtual void enableVirtProcElement(unsigned vpe);
- void enableVPEs(unsigned vpe);
-
- /// Notify the CPU to disable a virtual processor element.
- virtual void disableVirtProcElement(ThreadID tid, unsigned vpe);
- void disableVPEs(ThreadID tid, unsigned vpe);
-
- /// Notify the CPU that multithreading is enabled.
- virtual void enableMultiThreading(unsigned vpe);
- void enableThreads(unsigned vpe);
-
- /// Notify the CPU that multithreading is disabled.
- virtual void disableMultiThreading(ThreadID tid, unsigned vpe);
- void disableThreads(ThreadID tid, unsigned vpe);
-
- /** Activate a Thread When CPU Resources are Available. */
- void activateWhenReady(ThreadID tid);
-
- /** Add or Remove a Thread Context in the CPU. */
- void doContextSwitch();
-
/** Update The Order In Which We Process Threads. */
void updateThreadPriority();
/** Get & Update Next Event Number */
InstSeqNum getNextEventNum()
{
+#ifdef DEBUG
return cpuEventNum++;
+#else
+ return 0;
+#endif
}
/** Register file accessors */
- uint64_t readIntReg(int reg_idx, ThreadID tid);
+ uint64_t readIntReg(RegIndex reg_idx, ThreadID tid);
- FloatReg readFloatReg(int reg_idx, ThreadID tid);
+ FloatReg readFloatReg(RegIndex reg_idx, ThreadID tid);
- FloatRegBits readFloatRegBits(int reg_idx, ThreadID tid);
+ FloatRegBits readFloatRegBits(RegIndex reg_idx, ThreadID tid);
- void setIntReg(int reg_idx, uint64_t val, ThreadID tid);
+ CCReg readCCReg(RegIndex reg_idx, ThreadID tid);
- void setFloatReg(int reg_idx, FloatReg val, ThreadID tid);
+ void setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid);
- void setFloatRegBits(int reg_idx, FloatRegBits val, ThreadID tid);
+ void setFloatReg(RegIndex reg_idx, FloatReg val, ThreadID tid);
+
+ void setFloatRegBits(RegIndex reg_idx, FloatRegBits val, ThreadID tid);
+
+ void setCCReg(RegIndex reg_idx, CCReg val, ThreadID tid);
+
+ RegIndex flattenRegIdx(RegIndex reg_idx, RegClass ®_type, ThreadID tid);
/** Reads a miscellaneous register. */
MiscReg readMiscRegNoEffect(int misc_reg, ThreadID tid = 0);
ThreadID tid);
/** Reads the commit PC of a specific thread. */
- uint64_t readPC(ThreadID tid);
+ TheISA::PCState
+ pcState(ThreadID tid)
+ {
+ return pc[tid];
+ }
/** Sets the commit PC of a specific thread. */
- void setPC(Addr new_PC, ThreadID tid);
-
- /** Reads the next PC of a specific thread. */
- uint64_t readNextPC(ThreadID tid);
-
- /** Sets the next PC of a specific thread. */
- void setNextPC(uint64_t val, ThreadID tid);
-
- /** Reads the next NPC of a specific thread. */
- uint64_t readNextNPC(ThreadID tid);
+ void
+ pcState(const TheISA::PCState &newPC, ThreadID tid)
+ {
+ pc[tid] = newPC;
+ }
- /** Sets the next NPC of a specific thread. */
- void setNextNPC(uint64_t val, ThreadID tid);
+ Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); }
+ Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); }
+ MicroPC microPC(ThreadID tid) { return pc[tid].microPC(); }
/** Function to add instruction onto the head of the list of the
* instructions. Used when new instructions are fetched.
*/
- ListIt addInst(DynInstPtr &inst);
+ ListIt addInst(DynInstPtr inst);
+
+ /** Find instruction on instruction list */
+ ListIt findInst(InstSeqNum seq_num, ThreadID tid);
/** Function to tell the CPU that an instruction has completed. */
void instDone(DynInstPtr inst, ThreadID tid);
/** Add Instructions to the CPU Remove List*/
- void addToRemoveList(DynInstPtr &inst);
+ void addToRemoveList(DynInstPtr inst);
/** Remove an instruction from CPU */
- void removeInst(DynInstPtr &inst);
+ void removeInst(DynInstPtr inst);
/** Remove all instructions younger than the given sequence number. */
void removeInstsUntil(const InstSeqNum &seq_num,ThreadID tid);
/** Removes the instruction pointed to by the iterator. */
- inline void squashInstIt(const ListIt &instIt, ThreadID tid);
+ inline void squashInstIt(const ListIt inst_it, ThreadID tid);
/** Cleans up all instructions on the instruction remove list. */
void cleanUpRemovedInsts();
- /** Cleans up all instructions on the request remove list. */
- void cleanUpRemovedReqs();
-
- /** Cleans up all instructions on the CPU event remove list. */
+ /** Cleans up all events on the CPU event remove list. */
void cleanUpRemovedEvents();
/** Debug function to print all instructions on the list. */
/** Forwards an instruction read to the appropriate data
* resource (indexes into Resource Pool thru "dataPortIdx")
*/
- template <class T>
- Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags);
+ Fault read(DynInstPtr inst, Addr addr,
+ uint8_t *data, unsigned size, unsigned flags);
/** Forwards an instruction write. to the appropriate data
* resource (indexes into Resource Pool thru "dataPortIdx")
*/
- template <class T>
- Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags,
- uint64_t *write_res = NULL);
-
- /** Forwards an instruction prefetch to the appropriate data
- * resource (indexes into Resource Pool thru "dataPortIdx")
- */
- void prefetch(DynInstPtr inst);
-
- /** Forwards an instruction writeHint to the appropriate data
- * resource (indexes into Resource Pool thru "dataPortIdx")
- */
- void writeHint(DynInstPtr inst);
-
- /** Executes a syscall.*/
- void syscall(int64_t callnum, ThreadID tid);
+ Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *write_res = NULL);
public:
/** Per-Thread List of all the instructions in flight. */
*/
std::queue<ListIt> removeList;
- /** List of all the resource requests that will be removed at the end of this
- * cycle.
- */
- std::queue<ResourceRequest*> reqRemoveList;
+ bool trapPending[ThePipeline::MaxThreads];
/** List of all the cpu event requests that will be removed at the end of
* the current cycle.
/** Active Threads List */
std::list<ThreadID> activeThreads;
- /** Current Threads List */
- std::list<ThreadID> currentThreads;
+ /** Ready Threads List */
+ std::list<ThreadID> readyThreads;
/** Suspended Threads List */
std::list<ThreadID> suspendedThreads;
- /** Thread Status Functions (Unused Currently) */
- bool isThreadInCPU(ThreadID tid);
+ /** Halted Threads List */
+ std::list<ThreadID> haltedThreads;
+
+ /** Thread Status Functions */
bool isThreadActive(ThreadID tid);
+ bool isThreadReady(ThreadID tid);
bool isThreadSuspended(ThreadID tid);
- void addToCurrentThreads(ThreadID tid);
- void removeFromCurrentThreads(ThreadID tid);
private:
/** The activity recorder; used to tell if the CPU has any
/** Number of Active Threads in the CPU */
ThreadID numActiveThreads() { return activeThreads.size(); }
+ /** Thread id of active thread
+ * Only used for SwitchOnCacheMiss model.
+ * Assumes only 1 thread active
+ */
+ ThreadID activeThreadId()
+ {
+ if (numActiveThreads() > 0)
+ return activeThreads.front();
+ else
+ return InvalidThreadID;
+ }
+
+
/** Records that there was time buffer activity this cycle. */
void activityThisCycle() { activityRec.activity(); }
/** Wakes the CPU, rescheduling the CPU if it's not already active. */
void wakeCPU();
-#if FULL_SYSTEM
virtual void wakeup();
-#endif
- /** Gets a free thread id. Use if thread ids change across system. */
- ThreadID getFreeTid();
-
- // LL/SC debug functionality
+ /* LL/SC debug functionality
unsigned stCondFails;
- unsigned readStCondFailures() { return stCondFails; }
- unsigned setStCondFailures(unsigned st_fails) { return stCondFails = st_fails; }
+
+ unsigned readStCondFailures()
+ { return stCondFails; }
+
+ unsigned setStCondFailures(unsigned st_fails)
+ { return stCondFails = st_fails; }
+ */
/** Returns a pointer to a thread context. */
ThreadContext *tcBase(ThreadID tid = 0)
}
/** Count the Total Instructions Committed in the CPU. */
- virtual Counter totalInstructions() const
+ virtual Counter totalInsts() const
{
Counter total(0);
return total;
}
-#if FULL_SYSTEM
+ /** Count the Total Ops Committed in the CPU. */
+ virtual Counter totalOps() const
+ {
+ Counter total(0);
+
+ for (ThreadID tid = 0; tid < (ThreadID)thread.size(); tid++)
+ total += thread[tid]->numOp;
+
+ return total;
+ }
+
/** Pointer to the system. */
System *system;
- /** Pointer to physical memory. */
- PhysicalMemory *physmem;
-#endif
-
/** The global sequence number counter. */
InstSeqNum globalSeqNum[ThePipeline::MaxThreads];
+#ifdef DEBUG
/** The global event number counter. */
InstSeqNum cpuEventNum;
- /** Counter of how many stages have completed switching out. */
- int switchCount;
+ /** Number of resource requests active in CPU **/
+ unsigned resReqCount;
+#endif
- /** Pointers to all of the threads in the CPU. */
- std::vector<Thread *> thread;
+ Addr lockAddr;
- /** Pointer to the icache interface. */
- MemInterface *icacheInterface;
+ /** Temporary fix for the lock flag, works in the UP case. */
+ bool lockFlag;
- /** Pointer to the dcache interface. */
- MemInterface *dcacheInterface;
+ /** Counter of how many stages have completed draining */
+ int drainCount;
- /** Whether or not the CPU should defer its registration. */
- bool deferRegistration;
+ /** Pointers to all of the threads in the CPU. */
+ std::vector<Thread *> thread;
/** Per-Stage Instruction Tracing */
bool stageTracing;
- /** 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 Virtual Processors the CPU can process */
- unsigned numVirtProcs;
-
+ void updateContextSwitchStats();
+ unsigned instsPerSwitch;
+ Stats::Average instsPerCtxtSwitch;
+ Stats::Scalar numCtxtSwitches;
+
/** Update Thread , used for statistic purposes*/
inline void tickThreadStats();
/** Stat for total number of times the CPU is descheduled. */
Stats::Scalar timesIdled;
- /** Stat for total number of cycles the CPU spends descheduled. */
+ /** Stat for total number of cycles the CPU spends descheduled or no
+ * stages active.
+ */
Stats::Scalar idleCycles;
+ /** Stat for total number of cycles the CPU is active. */
+ Stats::Scalar runCycles;
+
+ /** Percentage of cycles a stage was active */
+ Stats::Formula activity;
+
+ /** Instruction Mix Stats */
+ Stats::Scalar comLoads;
+ Stats::Scalar comStores;
+ Stats::Scalar comBranches;
+ Stats::Scalar comNops;
+ Stats::Scalar comNonSpec;
+ Stats::Scalar comInts;
+ Stats::Scalar comFloats;
+
/** Stat for the number of committed instructions per thread. */
Stats::Vector committedInsts;
+ /** Stat for the number of committed ops per thread. */
+ Stats::Vector committedOps;
+
/** Stat for the number of committed instructions per thread. */
Stats::Vector smtCommittedInsts;