arch/alpha/full_cpu_exec.cc
arch/alpha/faults.cc
arch/alpha/isa_traits.cc
+ arch/alpha/ooo_cpu_exec.cc
base/circlebuf.cc
base/copyright.cc
cpu/beta_cpu/rename.cc
cpu/beta_cpu/rename_map.cc
cpu/beta_cpu/rob.cc
+ cpu/beta_cpu/sat_counter.cc
cpu/beta_cpu/store_set.cc
cpu/beta_cpu/tournament_pred.cc
cpu/fast_cpu/fast_cpu.cc
cpu/full_cpu/ls_queue.cc
cpu/full_cpu/machine_queue.cc
cpu/full_cpu/pc_sample_profile.cc
- cpu/full_cpu/pipetrace.cc
- cpu/full_cpu/readyq.cc
- cpu/full_cpu/reg_info.cc
- cpu/full_cpu/rob_station.cc
- cpu/full_cpu/spec_memory.cc
- cpu/full_cpu/spec_state.cc
- cpu/full_cpu/storebuffer.cc
- cpu/full_cpu/writeback.cc
- cpu/full_cpu/iq/iq_station.cc
- cpu/full_cpu/iq/iqueue.cc
- cpu/full_cpu/iq/segmented/chain_info.cc
- cpu/full_cpu/iq/segmented/chain_wire.cc
- cpu/full_cpu/iq/segmented/iq_seg.cc
- cpu/full_cpu/iq/segmented/iq_segmented.cc
- cpu/full_cpu/iq/segmented/seg_chain.cc
- cpu/full_cpu/iq/seznec/iq_seznec.cc
- cpu/full_cpu/iq/standard/iq_standard.cc
- cpu/sampling_cpu/sampling_cpu.cc
- cpu/simple_cpu/simple_cpu.cc
- cpu/inorder_cpu/inorder_cpu.cc
- cpu/trace/reader/mem_trace_reader.cc
- cpu/trace/reader/ibm_reader.cc
- cpu/trace/reader/itx_reader.cc
- cpu/trace/reader/m5_reader.cc
+ cpu/full_cpu/pipetrace.cc
+ cpu/full_cpu/readyq.cc
+ cpu/full_cpu/reg_info.cc
+ cpu/full_cpu/rob_station.cc
+ cpu/full_cpu/spec_memory.cc
+ cpu/full_cpu/spec_state.cc
+ cpu/full_cpu/storebuffer.cc
+ cpu/full_cpu/writeback.cc
+ cpu/full_cpu/iq/iq_station.cc
+ cpu/full_cpu/iq/iqueue.cc
+ cpu/full_cpu/iq/segmented/chain_info.cc
+ cpu/full_cpu/iq/segmented/chain_wire.cc
+ cpu/full_cpu/iq/segmented/iq_seg.cc
+ cpu/full_cpu/iq/segmented/iq_segmented.cc
+ cpu/full_cpu/iq/segmented/seg_chain.cc
+ cpu/full_cpu/iq/seznec/iq_seznec.cc
+ cpu/full_cpu/iq/standard/iq_standard.cc
+ cpu/inorder_cpu/inorder_cpu.cc
+ cpu/ooo_cpu/ea_list.cc
+ cpu/ooo_cpu/ooo_cpu.cc
+ cpu/ooo_cpu/ooo_dyn_inst.cc
+ cpu/ooo_cpu/ooo_sim_obj.cc
+ cpu/sampling_cpu/sampling_cpu.cc
+ cpu/simple_cpu/simple_cpu.cc
+ cpu/trace/reader/mem_trace_reader.cc
+ cpu/trace/reader/ibm_reader.cc
+ cpu/trace/reader/itx_reader.cc
+ cpu/trace/reader/m5_reader.cc
mem/base_hier.cc
mem/base_mem.cc
arch/alpha/fast_cpu_exec.cc
arch/alpha/simple_cpu_exec.cc
arch/alpha/inorder_cpu_exec.cc
- arch/alpha/full_cpu_exec.cc'''),
+ arch/alpha/full_cpu_exec.cc
+ arch/alpha/ooo_cpu_exec.cc'''),
Split('''arch/alpha/isa_desc
arch/isa_parser.py'''),
'$SRCDIR/arch/isa_parser.py $SOURCE $TARGET.dir arch/alpha')
/// Memory request flags. See mem_req_base.hh.
unsigned memAccessFlags;
/// Pointer to EAComp object.
- const StaticInstPtr<AlphaISA> eaCompPtr;
+ StaticInstPtr<AlphaISA> eaCompPtr;
/// Pointer to MemAcc object.
- const StaticInstPtr<AlphaISA> memAccPtr;
+ StaticInstPtr<AlphaISA> memAccPtr;
/// Constructor
Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
public:
- const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
- const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
+ StaticInstPtr<AlphaISA> &eaCompInst() { return eaCompPtr; }
+ StaticInstPtr<AlphaISA> &memAccInst() { return memAccPtr; }
};
/**
NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs
};
+ enum {
+ TotalDataRegs = NumIntRegs + NumFloatRegs
+ };
+
typedef union {
IntReg intreg;
FloatReg fpreg;
CpuModel('AlphaFullCPU', 'alpha_full_cpu_exec.cc',
'#include "cpu/beta_cpu/alpha_dyn_inst.hh"',
{ 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' })
+CpuModel('OoOCPU', 'ooo_cpu_exec.cc',
+ '#include "cpu/ooo_cpu/ooo_dyn_inst.hh"',
+ { 'CPU_exec_context': 'OoODynInst<OoOImpl>' })
# Expand template with CPU-specific references into a dictionary with
# an entry for each CPU model name. The entry key is the model name
'MemDepUnit',
'DynInst',
'FullCPU',
- 'CommitRate'
+ 'CommitRate',
+ 'OoOCPU'
]
#
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __BASE_DYN_INST_CC__
-#define __BASE_DYN_INST_CC__
+#ifndef __CPU_BASE_DYN_INST_CC__
+#define __CPU_BASE_DYN_INST_CC__
#include <iostream>
#include <string>
#include "cpu/base_dyn_inst.hh"
#include "cpu/beta_cpu/alpha_impl.hh"
#include "cpu/beta_cpu/alpha_full_cpu.hh"
+#include "cpu/ooo_cpu/ooo_impl.hh"
+#include "cpu/ooo_cpu/ooo_cpu.hh"
using namespace std;
FullCPU *cpu)
: staticInst(machInst), traceData(NULL), cpu(cpu), xc(cpu->xcBase())
{
- DPRINTF(FullCPU, "DynInst: Creating new DynInst.\n");
+ seqNum = seq_num;
+
+ PC = inst_PC;
+ nextPC = PC + sizeof(MachInst);
+ predPC = pred_PC;
+ initVars();
+}
+
+template <class Impl>
+BaseDynInst<Impl>::BaseDynInst(StaticInstPtr<ISA> &_staticInst)
+ : staticInst(_staticInst), traceData(NULL)
+{
+ initVars();
+}
+
+template <class Impl>
+void
+BaseDynInst<Impl>::initVars()
+{
effAddr = MemReq::inval_addr;
physEffAddr = MemReq::inval_addr;
readyRegs = 0;
- seqNum = seq_num;
-
-// specMemWrite = false;
-
+ completed = false;
canIssue = false;
issued = false;
executed = false;
canCommit = false;
squashed = false;
squashedInIQ = false;
+ eaCalcDone = false;
blockingInst = false;
recoverInst = false;
- specMode = false;
-// btbMissed = false;
+
// Eventually make this a parameter.
threadNumber = 0;
- // Also make this a parameter.
- specMode = true;
+
// Also make this a parameter, or perhaps get it from xc or cpu.
asid = 0;
// Initialize the fault to be unimplemented opcode.
fault = Unimplemented_Opcode_Fault;
- PC = inst_PC;
- nextPC = PC + sizeof(MachInst);
- predPC = pred_PC;
-
- // Make sure to have the renamed register entries set to the same
- // as the normal register entries. It will allow the IQ to work
- // without any modifications.
- for (int i = 0; i < staticInst->numDestRegs(); i++)
- {
- _destRegIdx[i] = staticInst->destRegIdx(i);
- }
-
- for (int i = 0; i < staticInst->numSrcRegs(); i++)
- {
- _srcRegIdx[i] = staticInst->srcRegIdx(i);
- _readySrcRegIdx[i] = 0;
- }
-
++instcount;
-// assert(instcount < 50);
-
DPRINTF(FullCPU, "DynInst: Instruction created. Instcount=%i\n",
instcount);
}
-template <class Impl>
-BaseDynInst<Impl>::BaseDynInst(StaticInstPtr<ISA> &_staticInst)
- : staticInst(_staticInst), traceData(NULL)
-{
- effAddr = MemReq::inval_addr;
- physEffAddr = MemReq::inval_addr;
-
-// specMemWrite = false;
-
- blockingInst = false;
- recoverInst = false;
- specMode = false;
-// btbMissed = false;
-
- // Make sure to have the renamed register entries set to the same
- // as the normal register entries. It will allow the IQ to work
- // without any modifications.
- for (int i = 0; i < staticInst->numDestRegs(); i++)
- {
- _destRegIdx[i] = staticInst->destRegIdx(i);
- }
-
- for (int i = 0; i < staticInst->numSrcRegs(); i++)
- {
- _srcRegIdx[i] = staticInst->srcRegIdx(i);
- }
-}
-
template <class Impl>
BaseDynInst<Impl>::~BaseDynInst()
{
DPRINTF(FullCPU, "DynInst: Instruction destroyed. Instcount=%i\n",
instcount);
}
-
+/*
template <class Impl>
FunctionalMemory *
BaseDynInst<Impl>::getMemory(void)
{
return xc->mem;
}
-/*
+
template <class Impl>
IntReg *
BaseDynInst<Impl>::getIntegerRegs(void)
#endif
+template <class Impl>
+bool
+BaseDynInst<Impl>::eaSrcsReady()
+{
+ // For now I am assuming that src registers 1..n-1 are the ones that the
+ // EA calc depends on. (i.e. src reg 0 is the source of the data to be
+ // stored)
+
+// StaticInstPtr<ISA> eaInst = staticInst->eaCompInst();
+
+ for (int i = 1; i < numSrcRegs(); ++i)
+ {
+ if (!_readySrcRegIdx[i])
+ return false;
+ }
+
+ return true;
+}
+
+// Forward declaration...
+template class BaseDynInst<AlphaSimpleImpl>;
+template class BaseDynInst<OoOImpl>;
+
+template <>
int
BaseDynInst<AlphaSimpleImpl>::instcount = 0;
-// Forward declaration...
-template BaseDynInst<AlphaSimpleImpl>;
+template <>
+int
+BaseDynInst<OoOImpl>::instcount = 0;
-#endif // __BASE_DYN_INST_CC__
+#endif // __CPU_BASE_DYN_INST_CC__
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __BASE_DYN_INST_HH__
-#define __BASE_DYN_INST_HH__
+#ifndef __CPU_BASE_DYN_INST_HH__
+#define __CPU_BASE_DYN_INST_HH__
-#include <vector>
#include <string>
+#include <vector>
#include "base/fast_alloc.hh"
#include "base/trace.hh"
-#include "cpu/static_inst.hh"
#include "cpu/beta_cpu/comm.hh"
+#include "cpu/exetrace.hh"
#include "cpu/full_cpu/bpred_update.hh"
-#include "mem/functional_mem/main_memory.hh"
-#include "cpu/full_cpu/spec_memory.hh"
-#include "cpu/inst_seq.hh"
#include "cpu/full_cpu/op_class.hh"
+#include "cpu/full_cpu/spec_memory.hh"
#include "cpu/full_cpu/spec_state.hh"
+#include "cpu/inst_seq.hh"
+#include "cpu/static_inst.hh"
+#include "mem/functional_mem/main_memory.hh"
/**
* @file
* Defines a dynamic instruction context.
*/
-namespace Trace {
- class InstRecord;
-};
-
// Forward declaration.
-template <class blah>
+template <class ISA>
class StaticInstPtr;
template <class Impl>
////////////////////////////////////////////
Trace::InstRecord *traceData;
-// void setCPSeq(InstSeqNum seq);
-
template <class T>
Fault read(Addr addr, T &data, unsigned flags);
Fault write(T data, Addr addr, unsigned flags,
uint64_t *res);
-
- IntReg *getIntegerRegs(void);
- FunctionalMemory *getMemory(void);
-
void prefetch(Addr addr, unsigned flags);
void writeHint(Addr addr, int size, unsigned flags);
Fault copySrcTranslate(Addr src);
Fault copy(Addr dest);
+ // Probably should be private...
public:
/** Is this instruction valid. */
bool valid;
/** How many source registers are ready. */
unsigned readyRegs;
+ /** Is the instruction completed. */
+ bool completed;
+
/** Can this instruction issue. */
bool canIssue;
/** Is this a thread syncrhonization instruction. */
bool threadsyncWait;
- /** If the BTB missed. */
-// bool btbMissed;
-
- /** The global history of this instruction (branch). */
-// unsigned globalHistory;
-
/** The thread this instruction is from. */
short threadNumber;
- /** If instruction is speculative. */
- short specMode;
-
/** data address space ID, for loads & stores. */
short asid;
/** The data to be stored. */
IntReg storeData;
- /** Result of this instruction, if an integer. */
- uint64_t intResult;
-
- /** Result of this instruction, if a float. */
- float floatResult;
+ union Result {
+ uint64_t integer;
+ float fp;
+ double dbl;
+ };
- /** Result of this instruction, if a double. */
- double doubleResult;
+ /** The result of the instruction; assumes for now that there's only one
+ * destination register.
+ */
+ Result instResult;
/** PC of this instruction. */
Addr PC;
/** Count of total number of dynamic instructions. */
static int instcount;
- /** Did this instruction do a spec write? */
-// bool specMemWrite;
-
- private:
- /** Physical register index of the destination registers of this
- * instruction.
- */
- PhysRegIndex _destRegIdx[MaxInstDestRegs];
-
- /** Physical register index of the source registers of this
- * instruction.
+ /** Whether or not the source register is ready. Not sure this should be
+ * here vs. the derived class.
*/
- PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
-
- /** Whether or not the source register is ready. */
bool _readySrcRegIdx[MaxInstSrcRegs];
- /** Physical register index of the previous producers of the
- * architected destinations.
- */
- PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
-
public:
/** BaseDynInst constructor given a binary instruction. */
BaseDynInst(MachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
/** BaseDynInst destructor. */
~BaseDynInst();
-#if 0
- Fault
- mem_access(MemCmd cmd, // Read or Write access cmd
- Addr addr, // virtual address of access
- void *p, // input/output buffer
- int nbytes); // access size
-#endif
+ private:
+ void initVars();
+ public:
void
trace_mem(Fault fault, // last fault
MemCmd cmd, // last command
bool doneTargCalc() { return false; }
/** Returns the calculated target of the branch. */
- Addr readCalcTarg() { return nextPC; }
+// Addr readCalcTarg() { return nextPC; }
Addr readNextPC() { return nextPC; }
/** Returns whether the instruction mispredicted. */
bool mispredicted() { return (predPC != nextPC); }
-/*
- unsigned readGlobalHist() {
- return globalHistory;
- }
-
- void setGlobalHist(unsigned history) {
- globalHistory = history;
- }
-*/
-
//
// Instruction types. Forward checks to StaticInst object.
//
bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
+ /** Returns the opclass of this instruction. */
+ OpClass opClass() const { return staticInst->opClass(); }
+
+ /** Returns the branch target address. */
+ Addr branchTarget() const { return staticInst->branchTarget(PC); }
+
int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
int8_t numDestRegs() const { return staticInst->numDestRegs(); }
return staticInst->srcRegIdx(i);
}
- /** Returns the physical register index of the i'th destination
- * register.
- */
- PhysRegIndex renamedDestRegIdx(int idx) const
- {
- return _destRegIdx[idx];
- }
-
- /** Returns the physical register index of the i'th source register. */
- PhysRegIndex renamedSrcRegIdx(int idx) const
- {
- return _srcRegIdx[idx];
- }
-
- bool isReadySrcRegIdx(int idx) const
- {
- return _readySrcRegIdx[idx];
- }
-
- /** Returns the physical register index of the previous physical register
- * that remapped to the same logical register index.
- */
- PhysRegIndex prevDestRegIdx(int idx) const
- {
- return _prevDestRegIdx[idx];
- }
-
- /** Renames a destination register to a physical register. Also records
- * the previous physical register that the logical register mapped to.
- */
- void renameDestReg(int idx,
- PhysRegIndex renamed_dest,
- PhysRegIndex previous_rename)
- {
- _destRegIdx[idx] = renamed_dest;
- _prevDestRegIdx[idx] = previous_rename;
- }
-
- /** Renames a source logical register to the physical register which
- * has/will produce that logical register's result.
- * @todo: add in whether or not the source register is ready.
- */
- void renameSrcReg(int idx, PhysRegIndex renamed_src)
- {
- _srcRegIdx[idx] = renamed_src;
- }
+ uint64_t readIntResult() { return instResult.integer; }
+ float readFloatResult() { return instResult.fp; }
+ double readDoubleResult() { return instResult.dbl; }
//Push to .cc file.
/** Records that one of the source registers is ready. */
}
}
+ bool isReadySrcRegIdx(int idx) const
+ {
+ return this->_readySrcRegIdx[idx];
+ }
+
+ void setCompleted() { completed = true; }
+
+ bool isCompleted() const { return completed; }
+
/** Sets this instruction as ready to issue. */
void setCanIssue() { canIssue = true; }
void setIssued() { issued = true; }
/** Returns whether or not this instruction has issued. */
- bool isIssued() { return issued; }
+ bool isIssued() const { return issued; }
/** Sets this instruction as executed. */
void setExecuted() { executed = true; }
/** Returns whether or not this instruction has executed. */
- bool isExecuted() { return executed; }
+ bool isExecuted() const { return executed; }
/** Sets this instruction as ready to commit. */
void setCanCommit() { canCommit = true; }
void setSquashedInIQ() { squashedInIQ = true; }
/** Returns whether or not this instruction is squashed in the IQ. */
- bool isSquashedInIQ() { return squashedInIQ; }
-
- /** Returns the opclass of this instruction. */
- OpClass opClass() const { return staticInst->opClass(); }
-
- /** Returns whether or not the BTB missed. */
-// bool btbMiss() const { return btbMissed; }
-
- /** Returns the branch target address. */
- Addr branchTarget() const { return staticInst->branchTarget(PC); }
-
- // 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 readIntReg(StaticInst<ISA> *si, int idx)
- {
- return cpu->readIntReg(_srcRegIdx[idx]);
- }
-
- float readFloatRegSingle(StaticInst<ISA> *si, int idx)
- {
- return cpu->readFloatRegSingle(_srcRegIdx[idx]);
- }
-
- double readFloatRegDouble(StaticInst<ISA> *si, int idx)
- {
- return cpu->readFloatRegDouble(_srcRegIdx[idx]);
- }
-
- uint64_t readFloatRegInt(StaticInst<ISA> *si, int idx)
- {
- return cpu->readFloatRegInt(_srcRegIdx[idx]);
- }
- /** @todo: Make results into arrays so they can handle multiple dest
- * registers.
- */
- void setIntReg(StaticInst<ISA> *si, int idx, uint64_t val)
- {
- cpu->setIntReg(_destRegIdx[idx], val);
- intResult = val;
- }
-
- void setFloatRegSingle(StaticInst<ISA> *si, int idx, float val)
- {
- cpu->setFloatRegSingle(_destRegIdx[idx], val);
- floatResult = val;
- }
-
- void setFloatRegDouble(StaticInst<ISA> *si, int idx, double val)
- {
- cpu->setFloatRegDouble(_destRegIdx[idx], val);
- doubleResult = val;
- }
-
- void setFloatRegInt(StaticInst<ISA> *si, int idx, uint64_t val)
- {
- cpu->setFloatRegInt(_destRegIdx[idx], val);
- intResult = val;
- }
+ bool isSquashedInIQ() const { return squashedInIQ; }
/** Read the PC of this instruction. */
- Addr readPC() { return PC; }
+ const Addr readPC() const { return PC; }
/** Set the next PC of this instruction (its actual target). */
void setNextPC(uint64_t val) { nextPC = val; }
-// bool misspeculating() { return cpu->misspeculating(); }
ExecContext *xcBase() { return xc; }
+
+ private:
+ Addr instEffAddr;
+ bool eaCalcDone;
+
+ public:
+ void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
+ const Addr &getEA() const { return instEffAddr; }
+ bool doneEACalc() { return eaCalcDone; }
+ bool eaSrcsReady();
};
template<class Impl>
storeSize = sizeof(T);
storeData = data;
-// if (specMode)
-// specMemWrite = true;
MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
return fault;
}
-#endif // __DYN_INST_HH__
+#endif // __CPU_BASE_DYN_INST_HH__
#include "base/trace.hh"
#include "cpu/beta_cpu/2bit_local_pred.hh"
-DefaultBP::SatCounter::SatCounter(unsigned bits)
- : maxVal((1 << bits) - 1), counter(0)
-{
-}
-
-DefaultBP::SatCounter::SatCounter(unsigned bits, unsigned initial_val)
- : maxVal((1 << bits) - 1), counter(initial_val)
-{
- // Check to make sure initial value doesn't exceed the max counter value.
- if (initial_val > maxVal) {
- panic("BP: Initial counter value exceeds max size.");
- }
-}
-
-void
-DefaultBP::SatCounter::increment()
-{
- if(counter < maxVal) {
- ++counter;
- }
-}
-
-void
-DefaultBP::SatCounter::decrement()
-{
- if(counter > 0) {
- --counter;
- }
-}
-
DefaultBP::DefaultBP(unsigned _localPredictorSize,
unsigned _localCtrBits,
unsigned _instShiftAmt)
DPRINTF(Fetch, "Branch predictor: index mask: %#x\n", indexMask);
// Setup the array of counters for the local predictor.
- localCtrs = new SatCounter[localPredictorSize](localCtrBits);
+ localCtrs = new SatCounter[localPredictorSize];
+
+ for (int i = 0; i < localPredictorSize; ++i)
+ localCtrs[i].setBits(_localCtrBits);
DPRINTF(Fetch, "Branch predictor: local predictor size: %i\n",
localPredictorSize);
-#ifndef __2BIT_LOCAL_PRED_HH__
-#define __2BIT_LOCAL_PRED_HH__
+#ifndef __CPU_BETA_CPU_2BIT_LOCAL_PRED_HH__
+#define __CPU_BETA_CPU_2BIT_LOCAL_PRED_HH__
// For Addr type.
#include "arch/alpha/isa_traits.hh"
+#include "cpu/beta_cpu/sat_counter.hh"
class DefaultBP
{
inline unsigned getLocalIndex(Addr &PC);
- /**
- * Private counter class for the internal saturating counters.
- * Implements an n bit saturating counter and provides methods to
- * increment, decrement, and read it.
- * @todo Consider making this something that more closely mimics a
- * built in class so you can use ++ or --.
- */
- class SatCounter
- {
- public:
- /**
- * Constructor for the counter.
- * @param bits How many bits the counter will have.
- */
- SatCounter(unsigned bits);
-
- /**
- * Constructor for the counter.
- * @param bits How many bits the counter will have.
- * @param initial_val Starting value for each counter.
- */
- SatCounter(unsigned bits, unsigned initial_val);
-
- /**
- * Increments the counter's current value.
- */
- void increment();
-
- /**
- * Decrements the counter's current value.
- */
- void decrement();
-
- /**
- * Read the counter's value.
- */
- uint8_t read()
- {
- return counter;
- }
-
- private:
- uint8_t maxVal;
- uint8_t counter;
- };
-
/** Array of counters that make up the local predictor. */
SatCounter *localCtrs;
unsigned indexMask;
};
-#endif // __2BIT_LOCAL_PRED_HH__
+#endif // __CPU_BETA_CPU_2BIT_LOCAL_PRED_HH__
// Force instantiation of AlphaDynInst for all the implementations that
// are needed.
-template AlphaDynInst<AlphaSimpleImpl>;
+template class AlphaDynInst<AlphaSimpleImpl>;
/** BaseDynInst constructor given a static inst pointer. */
AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst);
- /** Executes the instruction. */
+ /** Executes the instruction. Why the hell did I put this here? */
Fault execute()
{
- fault = staticInst->execute(this, traceData);
- return fault;
+ this->fault = this->staticInst->execute(this, this->traceData);
+ return this->fault;
}
public:
void syscall();
#endif
+
+
+ private:
+ /** Physical register index of the destination registers of this
+ * instruction.
+ */
+ PhysRegIndex _destRegIdx[MaxInstDestRegs];
+
+ /** Physical register index of the source registers of this
+ * instruction.
+ */
+ PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
+
+ /** Physical register index of the previous producers of the
+ * architected destinations.
+ */
+ PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
+
+ public:
+
+ // 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 readIntReg(StaticInst<ISA> *si, int idx)
+ {
+ return this->cpu->readIntReg(_srcRegIdx[idx]);
+ }
+
+ float readFloatRegSingle(StaticInst<ISA> *si, int idx)
+ {
+ return this->cpu->readFloatRegSingle(_srcRegIdx[idx]);
+ }
+
+ double readFloatRegDouble(StaticInst<ISA> *si, int idx)
+ {
+ return this->cpu->readFloatRegDouble(_srcRegIdx[idx]);
+ }
+
+ uint64_t readFloatRegInt(StaticInst<ISA> *si, int idx)
+ {
+ return this->cpu->readFloatRegInt(_srcRegIdx[idx]);
+ }
+ /** @todo: Make results into arrays so they can handle multiple dest
+ * registers.
+ */
+ void setIntReg(StaticInst<ISA> *si, int idx, uint64_t val)
+ {
+ this->cpu->setIntReg(_destRegIdx[idx], val);
+ this->instResult.integer = val;
+ }
+
+ void setFloatRegSingle(StaticInst<ISA> *si, int idx, float val)
+ {
+ this->cpu->setFloatRegSingle(_destRegIdx[idx], val);
+ this->instResult.fp = val;
+ }
+
+ void setFloatRegDouble(StaticInst<ISA> *si, int idx, double val)
+ {
+ this->cpu->setFloatRegDouble(_destRegIdx[idx], val);
+ this->instResult.dbl = val;
+ }
+
+ void setFloatRegInt(StaticInst<ISA> *si, int idx, uint64_t val)
+ {
+ this->cpu->setFloatRegInt(_destRegIdx[idx], val);
+ this->instResult.integer = val;
+ }
+
+ /** Returns the physical register index of the i'th destination
+ * register.
+ */
+ PhysRegIndex renamedDestRegIdx(int idx) const
+ {
+ return _destRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the i'th source register. */
+ PhysRegIndex renamedSrcRegIdx(int idx) const
+ {
+ return _srcRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the previous physical register
+ * that remapped to the same logical register index.
+ */
+ PhysRegIndex prevDestRegIdx(int idx) const
+ {
+ return _prevDestRegIdx[idx];
+ }
+
+ /** Renames a destination register to a physical register. Also records
+ * the previous physical register that the logical register mapped to.
+ */
+ void renameDestReg(int idx,
+ PhysRegIndex renamed_dest,
+ PhysRegIndex previous_rename)
+ {
+ _destRegIdx[idx] = renamed_dest;
+ _prevDestRegIdx[idx] = previous_rename;
+ }
+
+ /** Renames a source logical register to the physical register which
+ * has/will produce that logical register's result.
+ * @todo: add in whether or not the source register is ready.
+ */
+ void renameSrcReg(int idx, PhysRegIndex renamed_src)
+ {
+ _srcRegIdx[idx] = renamed_src;
+ }
+
+ public:
+ Fault calcEA()
+ {
+ return this->staticInst->eaCompInst()->execute(this, this->traceData);
+ }
+
+ Fault memAccess()
+ {
+ return this->staticInst->memAccInst()->execute(this, this->traceData);
+ }
};
#endif // __CPU_BETA_CPU_ALPHA_DYN_INST_HH__
template <class Impl>
AlphaDynInst<Impl>::AlphaDynInst(MachInst inst, Addr PC, Addr Pred_PC,
InstSeqNum seq_num, FullCPU *cpu)
- : BaseDynInst<AlphaSimpleImpl>(inst, PC, Pred_PC, seq_num, cpu)
+ : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
{
+ // Make sure to have the renamed register entries set to the same
+ // as the normal register entries. It will allow the IQ to work
+ // without any modifications.
+ for (int i = 0; i < this->staticInst->numDestRegs(); i++)
+ {
+ _destRegIdx[i] = this->staticInst->destRegIdx(i);
+ }
+
+ for (int i = 0; i < this->staticInst->numSrcRegs(); i++)
+ {
+ _srcRegIdx[i] = this->staticInst->srcRegIdx(i);
+ this->_readySrcRegIdx[i] = 0;
+ }
+
}
template <class Impl>
AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst)
- : BaseDynInst<AlphaSimpleImpl>(_staticInst)
+ : BaseDynInst<Impl>(_staticInst)
{
+ // Make sure to have the renamed register entries set to the same
+ // as the normal register entries. It will allow the IQ to work
+ // without any modifications.
+ for (int i = 0; i < _staticInst->numDestRegs(); i++)
+ {
+ _destRegIdx[i] = _staticInst->destRegIdx(i);
+ }
+
+ for (int i = 0; i < _staticInst->numSrcRegs(); i++)
+ {
+ _srcRegIdx[i] = _staticInst->srcRegIdx(i);
+ }
}
template <class Impl>
uint64_t
AlphaDynInst<Impl>::readUniq()
{
- return cpu->readUniq();
+ return this->cpu->readUniq();
}
template <class Impl>
void
AlphaDynInst<Impl>::setUniq(uint64_t val)
{
- cpu->setUniq(val);
+ this->cpu->setUniq(val);
}
template <class Impl>
uint64_t
AlphaDynInst<Impl>::readFpcr()
{
- return cpu->readFpcr();
+ return this->cpu->readFpcr();
}
template <class Impl>
void
AlphaDynInst<Impl>::setFpcr(uint64_t val)
{
- cpu->setFpcr(val);
+ this->cpu->setFpcr(val);
}
#ifdef FULL_SYSTEM
uint64_t
AlphaDynInst<Impl>::readIpr(int idx, Fault &fault)
{
- return cpu->readIpr(idx, fault);
+ return this->cpu->readIpr(idx, fault);
}
template <class Impl>
Fault
AlphaDynInst<Impl>::setIpr(int idx, uint64_t val)
{
- return cpu->setIpr(idx, val);
+ return this->cpu->setIpr(idx, val);
}
template <class Impl>
Fault
AlphaDynInst<Impl>::hwrei()
{
- return cpu->hwrei();
+ return this->cpu->hwrei();
}
template <class Impl>
int
AlphaDynInst<Impl>::readIntrFlag()
{
-return cpu->readIntrFlag();
+return this->cpu->readIntrFlag();
}
template <class Impl>
void
AlphaDynInst<Impl>::setIntrFlag(int val)
{
- cpu->setIntrFlag(val);
+ this->cpu->setIntrFlag(val);
}
template <class Impl>
bool
AlphaDynInst<Impl>::inPalMode()
{
- return cpu->inPalMode();
+ return this->cpu->inPalMode();
}
template <class Impl>
void
AlphaDynInst<Impl>::trap(Fault fault)
{
- cpu->trap(fault);
+ this->cpu->trap(fault);
}
template <class Impl>
bool
AlphaDynInst<Impl>::simPalCheck(int palFunc)
{
- return cpu->simPalCheck(palFunc);
+ return this->cpu->simPalCheck(palFunc);
}
#else
template <class Impl>
void
AlphaDynInst<Impl>::syscall()
{
- cpu->syscall();
+ this->cpu->syscall();
}
#endif
// Force instantiation of AlphaFullCPU for all the implemntations that are
// needed. Consider merging this and alpha_dyn_inst.cc, and maybe all
// classes that depend on a certain impl, into one file (alpha_impl.cc?).
-template AlphaFullCPU<AlphaSimpleImpl>;
+template class AlphaFullCPU<AlphaSimpleImpl>;
// trying to rename source/destination registers...
uint64_t readUniq()
{
- return regFile.readUniq();
+ return this->regFile.readUniq();
}
void setUniq(uint64_t val)
{
- regFile.setUniq(val);
+ this->regFile.setUniq(val);
}
uint64_t readFpcr()
{
- return regFile.readFpcr();
+ return this->regFile.readFpcr();
}
void setFpcr(uint64_t val)
{
- regFile.setFpcr(val);
+ this->regFile.setFpcr(val);
}
#ifdef FULL_SYSTEM
// set the register.
IntReg getSyscallArg(int i)
{
- return xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i];
+ return this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i];
}
// used to shift args for indirect syscall
void setSyscallArg(int i, IntReg val)
{
- xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i] = val;
+ this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i] = val;
}
void setSyscallReturn(int64_t return_value)
const int RegA3 = 19; // only place this is used
if (return_value >= 0) {
// no error
- xc->regs.intRegFile[RegA3] = 0;
- xc->regs.intRegFile[AlphaISA::ReturnValueReg] = return_value;
+ this->xc->regs.intRegFile[RegA3] = 0;
+ this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = return_value;
} else {
// got an error, return details
- xc->regs.intRegFile[RegA3] = (IntReg) -1;
- xc->regs.intRegFile[AlphaISA::ReturnValueReg] = -return_value;
+ this->xc->regs.intRegFile[RegA3] = (IntReg) -1;
+ this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = -return_value;
}
}
#endif
Fault error;
- error = mem->read(req, data);
+ error = this->mem->read(req, data);
data = htoa(data);
return error;
}
// If this is a store conditional, act appropriately
if (req->flags & LOCKED) {
- cregs = &xc->regs.miscRegs;
+ cregs = &this->xc->regs.miscRegs;
if (req->flags & UNCACHEABLE) {
// Don't update result register (see stq_c in isa_desc)
#endif
- return mem->write(req, (T)htoa(data));
+ return this->mem->write(req, (T)htoa(data));
}
};
params.mem = mem;
- params.maxInstsAnyThread = max_insts_any_thread;
- params.maxInstsAllThreads = max_insts_all_threads;
- params.maxLoadsAnyThread = max_loads_any_thread;
- params.maxLoadsAllThreads = max_loads_all_threads;
+ params.max_insts_any_thread = max_insts_any_thread;
+ params.max_insts_all_threads = max_insts_all_threads;
+ params.max_loads_any_thread = max_loads_any_thread;
+ params.max_loads_all_threads = max_loads_all_threads;
//
// Caches
template <class Impl>
AlphaFullCPU<Impl>::AlphaFullCPU(Params ¶ms)
- : FullBetaCPU<AlphaSimpleImpl>(params)
+ : FullBetaCPU<Impl>(params)
{
DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
- fetch.setCPU(this);
- decode.setCPU(this);
- rename.setCPU(this);
- iew.setCPU(this);
- commit.setCPU(this);
+ this->fetch.setCPU(this);
+ this->decode.setCPU(this);
+ this->rename.setCPU(this);
+ this->iew.setCPU(this);
+ this->commit.setCPU(this);
- rob.setCPU(this);
+ this->rob.setCPU(this);
}
template <class Impl>
AlphaFullCPU<Impl>::regStats()
{
// Register stats for everything that has stats.
- fullCPURegStats();
- fetch.regStats();
- decode.regStats();
- rename.regStats();
- iew.regStats();
- commit.regStats();
+ this->fullCPURegStats();
+ this->fetch.regStats();
+ this->decode.regStats();
+ this->rename.regStats();
+ this->iew.regStats();
+ this->commit.regStats();
}
#ifndef FULL_SYSTEM
DPRINTF(FullCPU, "AlphaFullCPU: Syscall() called.\n\n");
// Commit stage needs to run as well.
- commit.tick();
+ this->commit.tick();
squashStages();
// Temporarily increase this by one to account for the syscall
// instruction.
- ++funcExeInst;
+ ++(this->funcExeInst);
// Copy over all important state to xc once all the unrolling is done.
copyToXC();
- process->syscall(xc);
+ this->process->syscall(this->xc);
// Copy over all important state back to CPU.
copyFromXC();
// Decrease funcExeInst by one as the normal commit will handle
// incrememnting it.
- --funcExeInst;
+ --(this->funcExeInst);
}
// This is not a pretty function, and should only be used if it is necessary
void
AlphaFullCPU<Impl>::squashStages()
{
- InstSeqNum rob_head = rob.readHeadSeqNum();
+ InstSeqNum rob_head = this->rob.readHeadSeqNum();
// Now hack the time buffer to put this sequence number in the places
// where the stages might read it.
for (int i = 0; i < 5; ++i)
{
- timeBuffer.access(-i)->commitInfo.doneSeqNum = rob_head;
+ this->timeBuffer.access(-i)->commitInfo.doneSeqNum = rob_head;
}
- fetch.squash(rob.readHeadNextPC());
- fetchQueue.advance();
+ this->fetch.squash(this->rob.readHeadNextPC());
+ this->fetchQueue.advance();
- decode.squash();
- decodeQueue.advance();
+ this->decode.squash();
+ this->decodeQueue.advance();
- rename.squash();
- renameQueue.advance();
- renameQueue.advance();
+ this->rename.squash();
+ this->renameQueue.advance();
+ this->renameQueue.advance();
// Be sure to advance the IEW queues so that the commit stage doesn't
// try to set an instruction as completed at the same time that it
// might be deleting it.
- iew.squash();
- iewQueue.advance();
- iewQueue.advance();
+ this->iew.squash();
+ this->iewQueue.advance();
+ this->iewQueue.advance();
- rob.squash(rob_head);
- commit.setSquashing();
+ this->rob.squash(rob_head);
+ this->commit.setSquashing();
// Now hack the time buffer to clear the sequence numbers in the places
// where the stages might read it.?
for (int i = 0; i < 5; ++i)
{
- timeBuffer.access(-i)->commitInfo.doneSeqNum = 0;
+ this->timeBuffer.access(-i)->commitInfo.doneSeqNum = 0;
}
}
// First loop through the integer registers.
for (int i = 0; i < AlphaISA::NumIntRegs; ++i)
{
- renamed_reg = renameMap.lookup(i);
- xc->regs.intRegFile[i] = regFile.readIntReg(renamed_reg);
+ renamed_reg = this->renameMap.lookup(i);
+ this->xc->regs.intRegFile[i] = this->regFile.readIntReg(renamed_reg);
DPRINTF(FullCPU, "FullCPU: Copying register %i, has data %lli.\n",
- renamed_reg, regFile.intRegFile[renamed_reg]);
+ renamed_reg, this->regFile.intRegFile[renamed_reg]);
}
// Then loop through the floating point registers.
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
{
- renamed_reg = renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
- xc->regs.floatRegFile.d[i] = regFile.readFloatRegDouble(renamed_reg);
- xc->regs.floatRegFile.q[i] = regFile.readFloatRegInt(renamed_reg);
+ renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
+ this->xc->regs.floatRegFile.d[i] =
+ this->regFile.readFloatRegDouble(renamed_reg);
+ this->xc->regs.floatRegFile.q[i] =
+ this->regFile.readFloatRegInt(renamed_reg);
}
- xc->regs.miscRegs.fpcr = regFile.miscRegs.fpcr;
- xc->regs.miscRegs.uniq = regFile.miscRegs.uniq;
- xc->regs.miscRegs.lock_flag = regFile.miscRegs.lock_flag;
- xc->regs.miscRegs.lock_addr = regFile.miscRegs.lock_addr;
+ this->xc->regs.miscRegs.fpcr = this->regFile.miscRegs.fpcr;
+ this->xc->regs.miscRegs.uniq = this->regFile.miscRegs.uniq;
+ this->xc->regs.miscRegs.lock_flag = this->regFile.miscRegs.lock_flag;
+ this->xc->regs.miscRegs.lock_addr = this->regFile.miscRegs.lock_addr;
- xc->regs.pc = rob.readHeadPC();
- xc->regs.npc = xc->regs.pc+4;
+ this->xc->regs.pc = this->rob.readHeadPC();
+ this->xc->regs.npc = this->xc->regs.pc+4;
- xc->func_exe_inst = funcExeInst;
+ this->xc->func_exe_inst = this->funcExeInst;
}
// This function will probably mess things up unless the ROB is empty and
// First loop through the integer registers.
for (int i = 0; i < AlphaISA::NumIntRegs; ++i)
{
- renamed_reg = renameMap.lookup(i);
+ renamed_reg = this->renameMap.lookup(i);
DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
"now has data %lli.\n",
- renamed_reg, regFile.intRegFile[renamed_reg],
- xc->regs.intRegFile[i]);
+ renamed_reg, this->regFile.intRegFile[renamed_reg],
+ this->xc->regs.intRegFile[i]);
- regFile.setIntReg(renamed_reg, xc->regs.intRegFile[i]);
+ this->regFile.setIntReg(renamed_reg, this->xc->regs.intRegFile[i]);
}
// Then loop through the floating point registers.
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
{
- renamed_reg = renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
- regFile.setFloatRegDouble(renamed_reg, xc->regs.floatRegFile.d[i]);
- regFile.setFloatRegInt(renamed_reg, xc->regs.floatRegFile.q[i]);
+ renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
+ this->regFile.setFloatRegDouble(renamed_reg,
+ this->xc->regs.floatRegFile.d[i]);
+ this->regFile.setFloatRegInt(renamed_reg,
+ this->xc->regs.floatRegFile.q[i]);
}
// Then loop through the misc registers.
- regFile.miscRegs.fpcr = xc->regs.miscRegs.fpcr;
- regFile.miscRegs.uniq = xc->regs.miscRegs.uniq;
- regFile.miscRegs.lock_flag = xc->regs.miscRegs.lock_flag;
- regFile.miscRegs.lock_addr = xc->regs.miscRegs.lock_addr;
+ this->regFile.miscRegs.fpcr = this->xc->regs.miscRegs.fpcr;
+ this->regFile.miscRegs.uniq = this->xc->regs.miscRegs.uniq;
+ this->regFile.miscRegs.lock_flag = this->xc->regs.miscRegs.lock_flag;
+ this->regFile.miscRegs.lock_addr = this->xc->regs.miscRegs.lock_addr;
// Then finally set the PC and the next PC.
// regFile.pc = xc->regs.pc;
// regFile.npc = xc->regs.npc;
- funcExeInst = xc->func_exe_inst;
+ this->funcExeInst = this->xc->func_exe_inst;
}
#ifdef FULL_SYSTEM
#include "cpu/beta_cpu/alpha_impl.hh"
#include "cpu/beta_cpu/alpha_dyn_inst.hh"
-template TwobitBPredUnit<AlphaSimpleImpl>;
+template class TwobitBPredUnit<AlphaSimpleImpl>;
using namespace std;
-#ifdef FULL_SYSTEM
-BaseFullCPU::BaseFullCPU(Params ¶ms)
- : BaseCPU(params.name, params.numberOfThreads,
- params.maxInstsAnyThread, params.maxInstsAllThreads,
- params.maxLoadsAnyThread, params.maxLoadsAllThreads,
- params._system, params.freq)
-{
-}
-#else
BaseFullCPU::BaseFullCPU(Params ¶ms)
- : BaseCPU(params.name, params.numberOfThreads,
- params.maxInstsAnyThread, params.maxInstsAllThreads,
- params.maxLoadsAnyThread, params.maxLoadsAllThreads)
+ : BaseCPU(¶ms)
{
}
-#endif // FULL_SYSTEM
template <class Impl>
FullBetaCPU<Impl>::TickEvent::TickEvent(FullBetaCPU<Impl> *c)
}
// Forward declaration of FullBetaCPU.
-template FullBetaCPU<AlphaSimpleImpl>;
+template class FullBetaCPU<AlphaSimpleImpl>;
#endif // __SIMPLE_FULL_CPU_HH__
{
//Stuff that's pretty ISA independent will go here.
public:
- class Params
- {
- public:
-#ifdef FULL_SYSTEM
- std::string name;
- int numberOfThreads;
- Counter maxInstsAnyThread;
- Counter maxInstsAllThreads;
- Counter maxLoadsAnyThread;
- Counter maxLoadsAllThreads;
- System *_system;
- Tick freq;
-#else
- std::string name;
- int numberOfThreads;
- Counter maxInstsAnyThread;
- Counter maxInstsAllThreads;
- Counter maxLoadsAnyThread;
- Counter maxLoadsAllThreads;
-#endif // FULL_SYSTEM
- };
+ typedef BaseCPU::Params Params;
#ifdef FULL_SYSTEM
BaseFullCPU(Params ¶ms);
// Also send PC update information back to prior stages.
toCommit->squashedSeqNum = inst->seqNum;
toCommit->mispredPC = inst->readPC();
- toCommit->nextPC = inst->readCalcTarg();
+ toCommit->nextPC = inst->readNextPC();
toCommit->branchMispredict = true;
// Prediction was incorrect, so send back inverse.
- toCommit->branchTaken = inst->readCalcTarg() !=
+ toCommit->branchTaken = inst->readNextPC() !=
(inst->readPC() + sizeof(MachInst));
}
toCommit->squash = true;
// Also send PC update information back to prior stages.
toCommit->squashedSeqNum = inst->seqNum;
- toCommit->nextPC = inst->readCalcTarg();
+ toCommit->nextPC = inst->readNextPC();
}
template <class Impl, class IQ>
#include "cpu/beta_cpu/inst_queue_impl.hh"
// Force instantiation of InstructionQueue.
-template InstructionQueue<AlphaSimpleImpl>;
+template class InstructionQueue<AlphaSimpleImpl>;
+template<>
unsigned
InstructionQueue<AlphaSimpleImpl>::DependencyEntry::mem_alloc_counter = 0;
// Force instantation of memory dependency unit using store sets and
// AlphaSimpleImpl.
-template MemDepUnit<StoreSet, AlphaSimpleImpl>;
+template class MemDepUnit<StoreSet, AlphaSimpleImpl>;
: numEntries(_numEntries), usedEntries(0),
tos(0)
{
- addrStack = new Addr[numEntries](0);
+ addrStack = new Addr[numEntries];
+
+ for (int i = 0; i < numEntries; ++i)
+ addrStack[i] = 0;
}
void
+#include <vector>
+
#include "cpu/beta_cpu/rename_map.hh"
+using namespace std;
+
// Todo: Consider making functions inline. Avoid having things that are
// using the zero register or misc registers from adding on the registers
// to the free list. Possibly remove the direct communication between
void setEntry(RegIndex arch_reg, PhysRegIndex renamed_reg);
- void squash(vector<RegIndex> freed_regs,
- vector<UnmapInfo> unmaps);
+ void squash(std::vector<RegIndex> freed_regs,
+ std::vector<UnmapInfo> unmaps);
int numFreeEntries();
#include "cpu/beta_cpu/rob_impl.hh"
// Force instantiation of InstructionQueue.
-template ROB<AlphaSimpleImpl>;
+template class ROB<AlphaSimpleImpl>;
--- /dev/null
+#include "base/misc.hh"
+#include "cpu/beta_cpu/sat_counter.hh"
+
+SatCounter::SatCounter()
+ : maxVal(0), counter(0)
+{
+}
+
+SatCounter::SatCounter(unsigned bits)
+ : maxVal((1 << bits) - 1), counter(0)
+{
+}
+
+SatCounter::SatCounter(unsigned bits, unsigned initial_val)
+ : maxVal((1 << bits) - 1), counter(initial_val)
+{
+ // Check to make sure initial value doesn't exceed the max counter value.
+ if (initial_val > maxVal) {
+ panic("BP: Initial counter value exceeds max size.");
+ }
+}
+
+void
+SatCounter::setBits(unsigned bits)
+{
+ maxVal = (1 << bits) - 1;
+}
+
+void
+SatCounter::increment()
+{
+ if(counter < maxVal) {
+ ++counter;
+ }
+}
+
+void
+SatCounter::decrement()
+{
+ if(counter > 0) {
+ --counter;
+ }
+}
--- /dev/null
+#ifndef __CPU_BETA_CPU_SAT_COUNTER_HH__
+#define __CPU_BETA_CPU_SAT_COUNTER_HH__
+
+#include <stdint.h>
+
+/**
+ * Private counter class for the internal saturating counters.
+ * Implements an n bit saturating counter and provides methods to
+ * increment, decrement, and read it.
+ * @todo Consider making this something that more closely mimics a
+ * built in class so you can use ++ or --.
+ */
+class SatCounter
+{
+ public:
+ /**
+ * Constructor for the counter.
+ */
+ SatCounter();
+
+ /**
+ * Constructor for the counter.
+ * @param bits How many bits the counter will have.
+ */
+ SatCounter(unsigned bits);
+
+ /**
+ * Constructor for the counter.
+ * @param bits How many bits the counter will have.
+ * @param initial_val Starting value for each counter.
+ */
+ SatCounter(unsigned bits, unsigned initial_val);
+
+ /**
+ * Sets the number of bits.
+ */
+ void setBits(unsigned bits);
+
+ /**
+ * Increments the counter's current value.
+ */
+ void increment();
+
+ /**
+ * Decrements the counter's current value.
+ */
+ void decrement();
+
+ /**
+ * Read the counter's value.
+ */
+ const uint8_t read() const
+ {
+ return counter;
+ }
+
+ private:
+ uint8_t maxVal;
+ uint8_t counter;
+};
+
+#endif // __CPU_BETA_CPU_SAT_COUNTER_HH__
#include "cpu/beta_cpu/tournament_pred.hh"
-TournamentBP::SatCounter::SatCounter(unsigned bits)
- : maxVal((1 << bits) - 1), counter(0)
-{
-}
-
-TournamentBP::SatCounter::SatCounter(unsigned bits, unsigned initial_val)
- : maxVal((1 << bits) - 1), counter(initial_val)
-{
- // Check to make sure initial value doesn't exceed the max counter value.
- if (initial_val > maxVal) {
- panic("BP: Initial counter value exceeds max size.");
- }
-}
-
-void
-TournamentBP::SatCounter::increment()
-{
- if (counter < maxVal) {
- ++counter;
- }
-}
-
-void
-TournamentBP::SatCounter::decrement()
-{
- if (counter > 0) {
- --counter;
- }
-}
-
TournamentBP::TournamentBP(unsigned _local_predictor_size,
unsigned _local_ctr_bits,
unsigned _local_history_table_size,
//Should do checks here to make sure sizes are correct (powers of 2)
//Setup the array of counters for the local predictor
- local_ctrs = new SatCounter[local_predictor_size](local_ctr_bits);
+ local_ctrs = new SatCounter[local_predictor_size];
+
+ for (int i = 0; i < local_predictor_size; ++i)
+ local_ctrs[i].setBits(local_ctr_bits);
+
//Setup the history table for the local table
- local_history_table = new unsigned[local_history_table_size](0);
+ local_history_table = new unsigned[local_history_table_size];
+
+ for (int i = 0; i < local_history_table_size; ++i)
+ local_history_table[i] = 0;
+
// Setup the local history mask
localHistoryMask = (1 << local_history_bits) - 1;
//Setup the array of counters for the global predictor
- global_ctrs = new SatCounter[global_predictor_size](global_ctr_bits);
+ global_ctrs = new SatCounter[global_predictor_size];
+
+ for (int i = 0; i < global_predictor_size; ++i)
+ global_ctrs[i].setBits(global_ctr_bits);
+
//Clear the global history
global_history = 0;
// Setup the global history mask
globalHistoryMask = (1 << global_history_bits) - 1;
//Setup the array of counters for the choice predictor
- choice_ctrs = new SatCounter[choice_predictor_size](choice_ctr_bits);
+ choice_ctrs = new SatCounter[choice_predictor_size];
+
+ for (int i = 0; i < choice_predictor_size; ++i)
+ choice_ctrs[i].setBits(choice_ctr_bits);
threshold = (1 << (local_ctr_bits - 1)) - 1;
threshold = threshold / 2;
-#ifndef __TOURNAMENT_PRED_HH__
-#define __TOURNAMENT_PRED_HH__
+#ifndef __CPU_BETA_CPU_TOURNAMENT_PRED_HH__
+#define __CPU_BETA_CPU_TOURNAMENT_PRED_HH__
// For Addr type.
#include "arch/alpha/isa_traits.hh"
+#include "cpu/beta_cpu/sat_counter.hh"
class TournamentBP
{
inline void updateHistoriesNotTaken(unsigned local_history_idx);
- /**
- * Private counter class for the internal saturating counters.
- * Implements an n bit saturating counter and provides methods to
- * increment, decrement, and read it.
- * @todo Consider making this something that more closely mimics a
- * built in class so you can use ++ or --.
- */
- class SatCounter
- {
- public:
- /**
- * Constructor for the counter.
- * @param bits How many bits the counter will have.
- */
- SatCounter(unsigned bits);
-
- /**
- * Constructor for the counter.
- * @param bits How many bits the counter will have.
- * @param initial_val Starting value for each counter.
- */
- SatCounter(unsigned bits, unsigned initial_val);
-
- /**
- * Increments the counter's current value.
- */
- void increment();
-
- /**
- * Decrements the counter's current value.
- */
- void decrement();
-
- /**
- * Read the counter's value.
- */
- uint8_t read()
- {
- return counter;
- }
-
- private:
- uint8_t maxVal;
- uint8_t counter;
- };
-
/** Local counters. */
SatCounter *local_ctrs;
unsigned threshold;
};
-#endif // __TOURNAMENT_PRED_HH__
+#endif // __CPU_BETA_CPU_TOURNAMENT_PRED_HH__
--- /dev/null
+
+#include "arch/alpha/isa_traits.hh"
+#include "cpu/inst_seq.hh"
+#include "cpu/ooo_cpu/ea_list.hh"
+
+void
+EAList::addAddr(const InstSeqNum &new_sn, const Addr &new_ea)
+{
+ instEA newEA(new_sn, new_ea);
+
+ eaList.push_back(newEA);
+}
+
+void
+EAList::clearAddr(const InstSeqNum &sn_to_clear, const Addr &ea_to_clear)
+{
+ eaListIt list_it = eaList.begin();
+
+ while (list_it != eaList.end() && (*list_it).first != sn_to_clear) {
+ assert((*list_it).second == ea_to_clear);
+ }
+}
+
+bool
+EAList::checkConflict(const InstSeqNum &check_sn, const Addr &check_ea) const
+{
+ const constEAListIt list_it = eaList.begin();
+
+ while (list_it != eaList.end() && (*list_it).first < check_sn) {
+ if ((*list_it).second == check_ea) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+EAList::clear()
+{
+ eaList.clear();
+}
+
+void
+EAList::commit(const InstSeqNum &commit_sn)
+{
+ while (!eaList.empty() && eaList.front().first <= commit_sn) {
+ eaList.pop_front();
+ }
+}
--- /dev/null
+#ifndef __CPU_EA_LIST_HH__
+#define __CPU_EA_LIST_HH__
+
+#include <list>
+#include <utility>
+
+#include "arch/alpha/isa_traits.hh"
+#include "cpu/inst_seq.hh"
+
+/**
+ * Simple class to hold onto a list of pairs, each pair having a memory
+ * instruction's sequence number and effective addr. This list can be used
+ * for memory disambiguation. However, if I ever want to forward results, I
+ * may have to use a list that holds DynInstPtrs. Hence this may change in
+ * the future.
+ */
+class EAList {
+ private:
+ typedef std::pair<InstSeqNum, Addr> instEA;
+ typedef std::list<instEA>::iterator eaListIt;
+ typedef std::list<instEA>::const_iterator constEAListIt;
+
+ std::list<instEA> eaList;
+
+ public:
+ EAList() { }
+ ~EAList() { }
+
+ void addAddr(const InstSeqNum &new_sn, const Addr &new_ea);
+
+ void clearAddr(const InstSeqNum &sn_to_clear, const Addr &ea_to_clear);
+
+ /** Checks if any instructions older than check_sn have a conflicting
+ * address with check_ea. Note that this function does not handle the
+ * sequence number rolling over.
+ */
+ bool checkConflict(const InstSeqNum &check_sn, const Addr &check_ea) const;
+
+ void clear();
+
+ void commit(const InstSeqNum &commit_sn);
+};
+
+#endif // __CPU_EA_LIST_HH__
--- /dev/null
+
+#include "cpu/ooo_cpu/ooo_cpu_impl.hh"
+#include "cpu/ooo_cpu/ooo_dyn_inst.hh"
+#include "cpu/ooo_cpu/ooo_impl.hh"
+
+template class OoOCPU<OoOImpl>;
--- /dev/null
+/*
+ * Copyright (c) 2002-2005 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_OOO_CPU_OOO_CPU_HH__
+#define __CPU_OOO_CPU_OOO_CPU_HH__
+
+#include "base/statistics.hh"
+#include "cpu/base_cpu.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/full_cpu/fu_pool.hh"
+#include "cpu/ooo_cpu/ea_list.hh"
+#include "cpu/pc_event.hh"
+#include "cpu/static_inst.hh"
+#include "mem/mem_interface.hh"
+#include "sim/eventq.hh"
+
+// forward declarations
+#ifdef FULL_SYSTEM
+class Processor;
+class AlphaITB;
+class AlphaDTB;
+class PhysicalMemory;
+
+class RemoteGDB;
+class GDBListener;
+
+#else
+
+class Process;
+
+#endif // FULL_SYSTEM
+
+class Checkpoint;
+class MemInterface;
+
+namespace Trace {
+ class InstRecord;
+}
+
+/**
+ * Declaration of Out-of-Order CPU class. Basically it is a SimpleCPU with
+ * simple out-of-order capabilities added to it. It is still a 1 CPI machine
+ * (?), but is capable of handling cache misses. Basically it models having
+ * a ROB/IQ by only allowing a certain amount of instructions to execute while
+ * the cache miss is outstanding.
+ */
+
+template <class Impl>
+class OoOCPU : public BaseCPU
+{
+ private:
+ typedef typename Impl::DynInst DynInst;
+ typedef typename Impl::DynInstPtr DynInstPtr;
+ typedef typename Impl::ISA ISA;
+
+ public:
+ // main simulation loop (one cycle)
+ void tick();
+
+ private:
+ struct TickEvent : public Event
+ {
+ OoOCPU *cpu;
+ int width;
+
+ TickEvent(OoOCPU *c, int w);
+ void process();
+ const char *description();
+ };
+
+ TickEvent tickEvent;
+
+ /// Schedule tick event, regardless of its current state.
+ void scheduleTickEvent(int delay)
+ {
+ if (tickEvent.squashed())
+ tickEvent.reschedule(curTick + delay);
+ else if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick + delay);
+ }
+
+ /// Unschedule tick event, regardless of its current state.
+ void unscheduleTickEvent()
+ {
+ if (tickEvent.scheduled())
+ tickEvent.squash();
+ }
+
+ private:
+ Trace::InstRecord *traceData;
+
+ template<typename T>
+ void trace_data(T data);
+
+ public:
+ //
+ enum Status {
+ Running,
+ Idle,
+ IcacheMissStall,
+ IcacheMissComplete,
+ DcacheMissStall,
+ SwitchedOut
+ };
+
+ private:
+ Status _status;
+
+ 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;
+ }
+ };
+
+ struct Params : public BaseCPU::Params
+ {
+ MemInterface *icache_interface;
+ MemInterface *dcache_interface;
+ int width;
+#ifdef FULL_SYSTEM
+ AlphaITB *itb;
+ AlphaDTB *dtb;
+ FunctionalMemory *mem;
+#else
+ Process *process;
+#endif
+ int issueWidth;
+ };
+
+ OoOCPU(Params *params);
+
+ virtual ~OoOCPU();
+
+ private:
+ void copyFromXC();
+
+ public:
+ // execution context
+ ExecContext *xc;
+
+ void switchOut();
+ void takeOverFrom(BaseCPU *oldCPU);
+
+#ifdef FULL_SYSTEM
+ Addr dbg_vtophys(Addr addr);
+
+ bool interval_stats;
+#endif
+
+ // L1 instruction cache
+ MemInterface *icacheInterface;
+
+ // L1 data cache
+ MemInterface *dcacheInterface;
+
+ FuncUnitPool *fuPool;
+
+ // Refcounted pointer to the one memory request.
+ MemReqPtr cacheMemReq;
+
+ class ICacheCompletionEvent : public Event
+ {
+ private:
+ OoOCPU *cpu;
+
+ public:
+ ICacheCompletionEvent(OoOCPU *_cpu);
+
+ virtual void process();
+ virtual const char *description();
+ };
+
+ // Will need to create a cache completion event upon any memory miss.
+ ICacheCompletionEvent iCacheCompletionEvent;
+
+ class DCacheCompletionEvent : public Event
+ {
+ private:
+ OoOCPU *cpu;
+ DynInstPtr inst;
+
+ public:
+ DCacheCompletionEvent(OoOCPU *_cpu, DynInstPtr &_inst);
+
+ virtual void process();
+ virtual const char *description();
+ };
+
+ friend class DCacheCompletionEvent;
+
+ Status status() const { return _status; }
+
+ virtual void activateContext(int thread_num, int delay);
+ virtual void suspendContext(int thread_num);
+ virtual void deallocateContext(int thread_num);
+ virtual void haltContext(int thread_num);
+
+ // statistics
+ virtual void regStats();
+ virtual void resetStats();
+
+ // number of simulated instructions
+ Counter numInst;
+ Counter startNumInst;
+ Stats::Scalar<> numInsts;
+
+ virtual Counter totalInstructions() const
+ {
+ return numInst - startNumInst;
+ }
+
+ // 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 misses
+ Stats::Scalar<> icacheStallCycles;
+ Counter lastIcacheStall;
+
+ // number of cycles stalled for D-cache misses
+ Stats::Scalar<> dcacheStallCycles;
+ Counter lastDcacheStall;
+
+ void processICacheCompletion();
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string §ion);
+
+#ifdef FULL_SYSTEM
+ bool validInstAddr(Addr addr) { return true; }
+ bool validDataAddr(Addr addr) { return true; }
+ int getInstAsid() { return xc->regs.instAsid(); }
+ int getDataAsid() { return xc->regs.dataAsid(); }
+
+ Fault translateInstReq(MemReqPtr &req)
+ {
+ return itb->translate(req);
+ }
+
+ Fault translateDataReadReq(MemReqPtr &req)
+ {
+ return dtb->translate(req, false);
+ }
+
+ Fault translateDataWriteReq(MemReqPtr &req)
+ {
+ return dtb->translate(req, true);
+ }
+
+#else
+ bool validInstAddr(Addr addr)
+ { return xc->validInstAddr(addr); }
+
+ bool validDataAddr(Addr addr)
+ { return xc->validDataAddr(addr); }
+
+ int getInstAsid() { return xc->asid; }
+ int getDataAsid() { return xc->asid; }
+
+ Fault dummyTranslation(MemReqPtr &req)
+ {
+#if 0
+ assert((req->vaddr >> 48 & 0xffff) == 0);
+#endif
+
+ // put the asid in the upper 16 bits of the paddr
+ req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
+ req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
+ return No_Fault;
+ }
+ Fault translateInstReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+ Fault translateDataReadReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+ Fault translateDataWriteReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+
+#endif
+
+ template <class T>
+ Fault read(Addr addr, T &data, unsigned flags, DynInstPtr inst);
+
+ template <class T>
+ Fault write(T data, Addr addr, unsigned flags,
+ uint64_t *res, DynInstPtr inst);
+
+ 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);
+
+ private:
+ bool executeInst(DynInstPtr &inst);
+
+ void renameInst(DynInstPtr &inst);
+
+ void addInst(DynInstPtr &inst);
+
+ void commitHeadInst();
+
+ bool grabInst();
+
+ Fault fetchCacheLine();
+
+ InstSeqNum getAndIncrementInstSeq();
+
+ bool ambigMemAddr;
+
+ private:
+ InstSeqNum globalSeqNum;
+
+ DynInstPtr renameTable[ISA::TotalNumRegs];
+ DynInstPtr commitTable[ISA::TotalNumRegs];
+
+ // Might need a table of the shadow registers as well.
+#ifdef FULL_SYSTEM
+ DynInstPtr palShadowTable[ISA::NumIntRegs];
+#endif
+
+ public:
+ // 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).
+
+ // In the OoO case these shouldn't read from the XC but rather from the
+ // rename table of DynInsts. Also these likely shouldn't be called very
+ // often, other than when adding things into the xc during say a syscall.
+
+ uint64_t readIntReg(StaticInst<TheISA> *si, int idx)
+ {
+ return xc->readIntReg(si->srcRegIdx(idx));
+ }
+
+ float readFloatRegSingle(StaticInst<TheISA> *si, int idx)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return xc->readFloatRegSingle(reg_idx);
+ }
+
+ double readFloatRegDouble(StaticInst<TheISA> *si, int idx)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return xc->readFloatRegDouble(reg_idx);
+ }
+
+ uint64_t readFloatRegInt(StaticInst<TheISA> *si, int idx)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return xc->readFloatRegInt(reg_idx);
+ }
+
+ void setIntReg(StaticInst<TheISA> *si, int idx, uint64_t val)
+ {
+ xc->setIntReg(si->destRegIdx(idx), val);
+ }
+
+ void setFloatRegSingle(StaticInst<TheISA> *si, int idx, float val)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ xc->setFloatRegSingle(reg_idx, val);
+ }
+
+ void setFloatRegDouble(StaticInst<TheISA> *si, int idx, double val)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ xc->setFloatRegDouble(reg_idx, val);
+ }
+
+ void setFloatRegInt(StaticInst<TheISA> *si, int idx, uint64_t val)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ xc->setFloatRegInt(reg_idx, val);
+ }
+
+ uint64_t readPC() { return PC; }
+ void setNextPC(Addr val) { nextPC = val; }
+
+ private:
+ Addr PC;
+ Addr nextPC;
+
+ unsigned issueWidth;
+
+ bool fetchRedirExcp;
+ bool fetchRedirBranch;
+
+ /** Mask to get a cache block's address. */
+ Addr cacheBlkMask;
+
+ unsigned cacheBlkSize;
+
+ Addr cacheBlkPC;
+
+ /** The cache line being fetched. */
+ uint8_t *cacheData;
+
+ protected:
+ bool cacheBlkValid;
+
+ private:
+
+ // Align an address (typically a PC) to the start of an I-cache block.
+ // We fold in the PISA 64- to 32-bit conversion here as well.
+ Addr icacheBlockAlignPC(Addr addr)
+ {
+ addr = ISA::realPCToFetchPC(addr);
+ return (addr & ~(cacheBlkMask));
+ }
+
+ unsigned instSize;
+
+ // ROB tracking stuff.
+ DynInstPtr robHeadPtr;
+ DynInstPtr robTailPtr;
+ unsigned robInsts;
+
+ // List of outstanding EA instructions.
+ protected:
+ EAList eaList;
+
+ public:
+ void branchToTarget(Addr val)
+ {
+ if (!fetchRedirExcp) {
+ fetchRedirBranch = true;
+ PC = val;
+ }
+ }
+
+ // ISA stuff:
+ uint64_t readUniq() { return xc->readUniq(); }
+ void setUniq(uint64_t val) { xc->setUniq(val); }
+
+ uint64_t readFpcr() { return xc->readFpcr(); }
+ void setFpcr(uint64_t val) { xc->setFpcr(val); }
+
+#ifdef FULL_SYSTEM
+ uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
+ Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
+ Fault hwrei() { return xc->hwrei(); }
+ int readIntrFlag() { return xc->readIntrFlag(); }
+ void setIntrFlag(int val) { xc->setIntrFlag(val); }
+ bool inPalMode() { return xc->inPalMode(); }
+ void ev5_trap(Fault fault) { xc->ev5_trap(fault); }
+ bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
+#else
+ void syscall() { xc->syscall(); }
+#endif
+
+ ExecContext *xcBase() { return xc; }
+};
+
+
+// precise architected memory state accessor macros
+template <class Impl>
+template <class T>
+Fault
+OoOCPU<Impl>::read(Addr addr, T &data, unsigned flags, DynInstPtr inst)
+{
+ MemReqPtr readReq = new MemReq();
+ readReq->xc = xc;
+ readReq->asid = 0;
+ readReq->data = new uint8_t[64];
+
+ readReq->reset(addr, sizeof(T), flags);
+
+ // translate to physical address - This might be an ISA impl call
+ Fault fault = translateDataReadReq(readReq);
+
+ // do functional access
+ if (fault == No_Fault)
+ fault = xc->mem->read(readReq, data);
+#if 0
+ if (traceData) {
+ traceData->setAddr(addr);
+ if (fault == No_Fault)
+ traceData->setData(data);
+ }
+#endif
+
+ // if we have a cache, do cache access too
+ if (fault == No_Fault && dcacheInterface) {
+ readReq->cmd = Read;
+ readReq->completionEvent = NULL;
+ readReq->time = curTick;
+ /*MemAccessResult result = */dcacheInterface->access(readReq);
+
+ if (dcacheInterface->doEvents()) {
+ readReq->completionEvent = new DCacheCompletionEvent(this, inst);
+ lastDcacheStall = curTick;
+ unscheduleTickEvent();
+ _status = DcacheMissStall;
+ }
+ }
+
+ if (!dcacheInterface && (readReq->flags & UNCACHEABLE))
+ recordEvent("Uncached Read");
+
+ return fault;
+}
+
+template <class Impl>
+template <class T>
+Fault
+OoOCPU<Impl>::write(T data, Addr addr, unsigned flags,
+ uint64_t *res, DynInstPtr inst)
+{
+ MemReqPtr writeReq = new MemReq();
+ writeReq->xc = xc;
+ writeReq->asid = 0;
+ writeReq->data = new uint8_t[64];
+
+#if 0
+ if (traceData) {
+ traceData->setAddr(addr);
+ traceData->setData(data);
+ }
+#endif
+
+ writeReq->reset(addr, sizeof(T), flags);
+
+ // translate to physical address
+ Fault fault = xc->translateDataWriteReq(writeReq);
+
+ // do functional access
+ if (fault == No_Fault)
+ fault = xc->write(writeReq, data);
+
+ if (fault == No_Fault && dcacheInterface) {
+ writeReq->cmd = Write;
+ memcpy(writeReq->data,(uint8_t *)&data,writeReq->size);
+ writeReq->completionEvent = NULL;
+ writeReq->time = curTick;
+ /*MemAccessResult result = */dcacheInterface->access(writeReq);
+
+ if (dcacheInterface->doEvents()) {
+ writeReq->completionEvent = new DCacheCompletionEvent(this, inst);
+ lastDcacheStall = curTick;
+ unscheduleTickEvent();
+ _status = DcacheMissStall;
+ }
+ }
+
+ if (res && (fault == No_Fault))
+ *res = writeReq->result;
+
+ if (!dcacheInterface && (writeReq->flags & UNCACHEABLE))
+ recordEvent("Uncached Write");
+
+ return fault;
+}
+
+
+#endif // __CPU_OOO_CPU_OOO_CPU_HH__
--- /dev/null
+
+#ifndef __CPU_OOO_CPU_OOO_IMPL_HH__
+#define __CPU_OOO_CPU_OOO_IMPL_HH__
+
+#include "arch/alpha/isa_traits.hh"
+
+template <class Impl>
+class OoOCPU;
+
+template <class Impl>
+class OoODynInst;
+
+struct OoOImpl {
+ typedef AlphaISA ISA;
+ typedef OoOCPU<OoOImpl> OoOCPU;
+ typedef OoOCPU FullCPU;
+ typedef OoODynInst<OoOImpl> DynInst;
+ typedef RefCountingPtr<DynInst> DynInstPtr;
+};
+
+#endif // __CPU_OOO_CPU_OOO_IMPL_HH__
}
#endif // FULL_SYSTEM
-Tick save_cycle = 0;
-
-
void
SimpleCPU::processCacheCompletion()
{
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __STATIC_INST_HH__
-#define __STATIC_INST_HH__
+#ifndef __CPU_STATIC_INST_HH__
+#define __CPU_STATIC_INST_HH__
#include <bitset>
#include <string>
// forward declarations
struct AlphaSimpleImpl;
+struct OoOImpl;
class ExecContext;
class DynInst;
+
template <class Impl>
class AlphaDynInst;
+template <class Impl>
+class OoODynInst;
+
class FastCPU;
class SimpleCPU;
class InorderCPU;
* obtain the dependence info (numSrcRegs and srcRegIdx[]) for
* just the EA computation.
*/
- virtual const
+ virtual
StaticInstPtr<ISA> &eaCompInst() const { return nullStaticInstPtr; }
/**
* obtain the dependence info (numSrcRegs and srcRegIdx[]) for
* just the memory access (not the EA computation).
*/
- virtual const
+ virtual
StaticInstPtr<ISA> &memAccInst() const { return nullStaticInstPtr; }
/// The binary machine instruction.
}
};
-#endif // __STATIC_INST_HH__
+#endif // __CPU_STATIC_INST_HH__