/*
+ * 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 "cpu/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;
/* 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;
/** 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)
{
assert(!tickEvent.scheduled() || tickEvent.squashed());
- reschedule(&tickEvent, nextCycle(curTick() + ticks(delay)), true);
+ reschedule(&tickEvent, clockEdge(delay), true);
}
/** Unschedule tick event, regardless of its current state. */
HaltThread,
SuspendThread,
Trap,
- InstGraduated,
+ 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
{
DynInstPtr inst;
Fault fault;
unsigned vpe;
+ short syscall_num;
public:
/** Constructs a CPU event. */
CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, Fault fault,
- ThreadID _tid, DynInstPtr inst, unsigned event_pri_offset);
+ ThreadID _tid, DynInstPtr inst, CPUEventPri event_pri);
/** Set Type of Event To Be Scheduled */
void setEvent(CPUEventType e_type, Fault _fault, ThreadID _tid,
void process();
/** Returns the description of the CPU event. */
- const char *description();
+ 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,
- DynInstPtr inst, unsigned delay = 0,
- unsigned event_pri_offset = 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;
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[ThePipeline::MaxThreads];
- /** 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;
-
/** The Pipeline Stages for the CPU */
PipelineStage *pipelineStage[ThePipeline::NumStages];
- /** Width (processing bandwidth) of each stage */
- int stageWidth;
-
/** Program Counters */
TheISA::PCState pc[ThePipeline::MaxThreads];
+ /** Last Committed PC */
+ TheISA::PCState lastCommittedPC[ThePipeline::MaxThreads];
+
/** The Register File for the CPU */
union {
FloatReg f[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
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 std::map<SkedID, ThePipeline::RSkedPtr> skedCache;
+ static m5::hash_map<SkedID, ThePipeline::RSkedPtr> skedCache;
- typedef std::map<SkedID, ThePipeline::RSkedPtr>::iterator SkedCacheIt;
+ 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)
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)
{
(inst->isControl() << INST_CONTROL) |
(inst->isNonSpeculative() << INST_NONSPEC) |
(inst->numDestRegs() << INST_DEST_REGS) |
- (inst->numSrcRegs() << INST_SRC_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:
+
+ /** 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();
- /** 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, DynInstPtr inst, int delay = 0);
- void trapCPU(Fault fault, ThreadID tid, DynInstPtr inst);
+ /** 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));
+
+ /** Perform trap to Handle Given Fault */
+ void trap(Fault fault, ThreadID tid, DynInstPtr inst);
+
+ /** 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);
+
+ /** Activate Thread In Each Pipeline Stage */
void activateThreadInPipeline(ThreadID tid);
- /** Add Thread to Active Threads List. */
- void activateNextReadyContext(int delay = 0);
+ /** 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 deactivateContext(ThreadID tid, int delay = 0);
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 suspendContext(ThreadID tid, int delay = 0);
void suspendThread(ThreadID tid);
+ /** 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 haltContext(ThreadID tid, int delay = 0);
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, int delay = 0);
+ void squashFromMemStall(DynInstPtr inst, ThreadID tid,
+ Cycles delay = Cycles(0));
void squashDueToMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid);
void removePipelineStalls(ThreadID tid);
}
/** Register file accessors */
- uint64_t readIntReg(int reg_idx, ThreadID tid);
+ uint64_t readIntReg(RegIndex reg_idx, ThreadID tid);
+
+ FloatReg readFloatReg(RegIndex reg_idx, ThreadID tid);
+
+ FloatRegBits readFloatRegBits(RegIndex reg_idx, ThreadID tid);
- FloatReg readFloatReg(int reg_idx, ThreadID tid);
+ CCReg readCCReg(RegIndex reg_idx, ThreadID tid);
- FloatRegBits readFloatRegBits(int reg_idx, ThreadID tid);
+ void setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid);
- void setIntReg(int reg_idx, uint64_t val, ThreadID tid);
+ void setFloatReg(RegIndex reg_idx, FloatReg val, ThreadID tid);
- void setFloatReg(int reg_idx, FloatReg val, ThreadID tid);
+ void setFloatRegBits(RegIndex reg_idx, FloatRegBits val, ThreadID tid);
- void setFloatRegBits(int 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);
/** 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();
Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
Addr addr, unsigned flags, uint64_t *write_res = NULL);
- /** Executes a syscall.*/
- void syscall(int64_t callnum, ThreadID tid);
-
public:
/** Per-Thread List of all the instructions in flight. */
std::list<DynInstPtr> instList[ThePipeline::MaxThreads];
*/
std::queue<ListIt> removeList;
+ bool trapPending[ThePipeline::MaxThreads];
+
/** List of all the cpu event requests that will be removed at the end of
* the current cycle.
*/
/** Wakes the CPU, rescheduling the CPU if it's not already active. */
void wakeCPU();
-#if FULL_SYSTEM
virtual void wakeup();
-#endif
- // LL/SC debug functionality
+ /* LL/SC debug functionality
unsigned stCondFails;
unsigned readStCondFailures()
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];
unsigned resReqCount;
#endif
- /** Counter of how many stages have completed switching out. */
- int switchCount;
+ Addr lockAddr;
- /** Pointers to all of the threads in the CPU. */
- std::vector<Thread *> thread;
-
- /** 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;
/** 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;