O3: Clean up the O3 structures and try to pack them a bit better.

DynInst is extremely large the hope is that this re-organization will put the
most used members close to each other.
This commit is contained in:
Ali Saidi 2012-06-05 01:23:09 -04:00
parent aec7a44116
commit 6df196b71e
20 changed files with 318 additions and 316 deletions

View file

@ -40,6 +40,9 @@ namespace AlphaISA {
using AlphaISAInst::MaxInstSrcRegs;
using AlphaISAInst::MaxInstDestRegs;
// Locked read/write flags are can't be detected by the ISA parser
const int MaxMiscDestRegs = AlphaISAInst::MaxMiscDestRegs + 1;
typedef uint8_t RegIndex;
typedef uint64_t IntReg;

View file

@ -55,6 +55,7 @@ namespace ArmISA {
const int MaxInstSrcRegs = ArmISAInst::MaxInstDestRegs +
ArmISAInst::MaxInstSrcRegs;
using ArmISAInst::MaxInstDestRegs;
using ArmISAInst::MaxMiscDestRegs;
typedef uint16_t RegIndex;

View file

@ -726,6 +726,7 @@ class OperandList(object):
self.numDestRegs = 0
self.numFPDestRegs = 0
self.numIntDestRegs = 0
self.numMiscDestRegs = 0
self.memOperand = None
for op_desc in self.items:
if op_desc.isReg():
@ -739,6 +740,8 @@ class OperandList(object):
self.numFPDestRegs += 1
elif op_desc.isIntReg():
self.numIntDestRegs += 1
elif op_desc.isControlReg():
self.numMiscDestRegs += 1
elif op_desc.isMem():
if self.memOperand:
error("Code block has more than one memory operand.")
@ -747,6 +750,8 @@ class OperandList(object):
parser.maxInstSrcRegs = self.numSrcRegs
if parser.maxInstDestRegs < self.numDestRegs:
parser.maxInstDestRegs = self.numDestRegs
if parser.maxMiscDestRegs < self.numMiscDestRegs:
parser.maxMiscDestRegs = self.numMiscDestRegs
# now make a final pass to finalize op_desc fields that may depend
# on the register enumeration
for op_desc in self.items:
@ -1001,6 +1006,7 @@ namespace %(namespace)s {
const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
const int MaxInstDestRegs = %(MaxInstDestRegs)d;
const int MaxMiscDestRegs = %(MaxMiscDestRegs)d;
} // namespace %(namespace)s
@ -1036,6 +1042,7 @@ class ISAParser(Grammar):
self.maxInstSrcRegs = 0
self.maxInstDestRegs = 0
self.maxMiscDestRegs = 0
#####################################################################
#
@ -1990,6 +1997,7 @@ StaticInstPtr
# value of the globals.
MaxInstSrcRegs = self.maxInstSrcRegs
MaxInstDestRegs = self.maxInstDestRegs
MaxMiscDestRegs = self.maxMiscDestRegs
# max_inst_regs.hh
self.update_if_needed('max_inst_regs.hh',
max_inst_regs_template % vars())

View file

@ -43,6 +43,7 @@ namespace MipsISA
using MipsISAInst::MaxInstSrcRegs;
using MipsISAInst::MaxInstDestRegs;
using MipsISAInst::MaxMiscDestRegs;
// Constants Related to the number of registers
const int NumIntArchRegs = 32;

View file

@ -38,6 +38,7 @@ namespace PowerISA {
using PowerISAInst::MaxInstSrcRegs;
using PowerISAInst::MaxInstDestRegs;
using PowerISAInst::MaxMiscDestRegs;
typedef uint8_t RegIndex;

View file

@ -42,6 +42,7 @@ namespace SparcISA
using SparcISAInst::MaxInstSrcRegs;
using SparcISAInst::MaxInstDestRegs;
using SparcISAInst::MaxMiscDestRegs;
typedef uint64_t IntReg;
typedef uint64_t MiscReg;

View file

@ -49,6 +49,7 @@ namespace X86ISA
{
using X86ISAInst::MaxInstSrcRegs;
using X86ISAInst::MaxInstDestRegs;
using X86ISAInst::MaxMiscDestRegs;
const int NumMiscArchRegs = NUM_MISCREGS;
const int NumMiscRegs = NUM_MISCREGS;

View file

@ -98,17 +98,202 @@ class BaseDynInst : public RefCounted
MaxInstDestRegs = TheISA::MaxInstDestRegs /// Max dest regs
};
union Result {
uint64_t integer;
double dbl;
void set(uint64_t i) { integer = i; }
void set(double d) { dbl = d; }
void get(uint64_t& i) { i = integer; }
void get(double& d) { d = dbl; }
};
protected:
enum Status {
IqEntry, /// Instruction is in the IQ
RobEntry, /// Instruction is in the ROB
LsqEntry, /// Instruction is in the LSQ
Completed, /// Instruction has completed
ResultReady, /// Instruction has its result
CanIssue, /// Instruction can issue and execute
Issued, /// Instruction has issued
Executed, /// Instruction has executed
CanCommit, /// Instruction can commit
AtCommit, /// Instruction has reached commit
Committed, /// Instruction has committed
Squashed, /// Instruction is squashed
SquashedInIQ, /// Instruction is squashed in the IQ
SquashedInLSQ, /// Instruction is squashed in the LSQ
SquashedInROB, /// Instruction is squashed in the ROB
RecoverInst, /// Is a recover instruction
BlockingInst, /// Is a blocking instruction
ThreadsyncWait, /// Is a thread synchronization instruction
SerializeBefore, /// Needs to serialize on
/// instructions ahead of it
SerializeAfter, /// Needs to serialize instructions behind it
SerializeHandled, /// Serialization has been handled
NumStatus
};
enum Flags {
TranslationStarted,
TranslationCompleted,
PossibleLoadViolation,
HitExternalSnoop,
EffAddrValid,
RecordResult,
Predicate,
PredTaken,
/** Whether or not the effective address calculation is completed.
* @todo: Consider if this is necessary or not.
*/
EACalcDone,
IsUncacheable,
ReqMade,
MemOpDone,
MaxFlags
};
public:
/** The sequence number of the instruction. */
InstSeqNum seqNum;
/** The StaticInst used by this BaseDynInst. */
StaticInstPtr staticInst;
/** Pointer to the Impl's CPU object. */
ImplCPU *cpu;
/** Pointer to the thread state. */
ImplState *thread;
/** The kind of fault this instruction has generated. */
Fault fault;
/** InstRecord that tracks this instructions. */
Trace::InstRecord *traceData;
protected:
/** The result of the instruction; assumes an instruction can have many
* destination registers.
*/
std::queue<Result> instResult;
/** PC state for this instruction. */
TheISA::PCState pc;
/* An amalgamation of a lot of boolean values into one */
std::bitset<MaxFlags> instFlags;
/** The status of this BaseDynInst. Several bits can be set. */
std::bitset<NumStatus> status;
/** Whether or not the source register is ready.
* @todo: Not sure this should be here vs the derived class.
*/
std::bitset<MaxInstSrcRegs> _readySrcRegIdx;
public:
/** The thread this instruction is from. */
ThreadID threadNumber;
/** Iterator pointing to this BaseDynInst in the list of all insts. */
ListIt instListIt;
////////////////////// Branch Data ///////////////
/** Predicted PC state after this instruction. */
TheISA::PCState predPC;
/** The Macroop if one exists */
StaticInstPtr macroop;
/** How many source registers are ready. */
uint8_t readyRegs;
public:
/////////////////////// Load Store Data //////////////////////
/** The effective virtual address (lds & stores only). */
Addr effAddr;
/** The effective physical address. */
Addr physEffAddr;
/** The memory request flags (from translation). */
unsigned memReqFlags;
/** data address space ID, for loads & stores. */
short asid;
/** The size of the request */
uint8_t effSize;
/** Pointer to the data for the memory access. */
uint8_t *memData;
/** Load queue index. */
int16_t lqIdx;
/** Store queue index. */
int16_t sqIdx;
/////////////////////// TLB Miss //////////////////////
/**
* Saved memory requests (needed when the DTB address translation is
* delayed due to a hw page table walk).
*/
RequestPtr savedReq;
RequestPtr savedSreqLow;
RequestPtr savedSreqHigh;
/////////////////////// Checker //////////////////////
// Need a copy of main request pointer to verify on writes.
RequestPtr reqToVerify;
private:
/** Instruction effective address.
* @todo: Consider if this is necessary or not.
*/
Addr instEffAddr;
protected:
/** Flattened register index of the destination registers of this
* instruction.
*/
TheISA::RegIndex _flatDestRegIdx[TheISA::MaxInstDestRegs];
/** Physical register index of the destination registers of this
* instruction.
*/
PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs];
/** Physical register index of the source registers of this
* instruction.
*/
PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs];
/** Physical register index of the previous producers of the
* architected destinations.
*/
PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs];
public:
/** Records changes to result? */
void recordResult(bool f) { instFlags[RecordResult] = f; }
/** Is the effective virtual address valid. */
bool effAddrValid() const { return instFlags[EffAddrValid]; }
/** Whether or not the memory operation is done. */
bool memOpDone() const { return instFlags[MemOpDone]; }
void memOpDone(bool f) { instFlags[MemOpDone] = f; }
////////////////////////////////////////////
//
// INSTRUCTION EXECUTION
//
////////////////////////////////////////////
/** InstRecord that tracks this instructions. */
Trace::InstRecord *traceData;
void demapPage(Addr vaddr, uint64_t asn)
{
@ -141,23 +326,27 @@ class BaseDynInst : public RefCounted
void finishTranslation(WholeTranslationState *state);
/** True if the DTB address translation has started. */
bool translationStarted;
bool translationStarted() const { return instFlags[TranslationStarted]; }
void translationStarted(bool f) { instFlags[TranslationStarted] = f; }
/** True if the DTB address translation has completed. */
bool translationCompleted;
bool translationCompleted() const { return instFlags[TranslationCompleted]; }
void translationCompleted(bool f) { instFlags[TranslationCompleted] = f; }
/** True if this address was found to match a previous load and they issued
* out of order. If that happend, then it's only a problem if an incoming
* snoop invalidate modifies the line, in which case we need to squash.
* If nothing modified the line the order doesn't matter.
*/
bool possibleLoadViolation;
bool possibleLoadViolation() const { return instFlags[PossibleLoadViolation]; }
void possibleLoadViolation(bool f) { instFlags[PossibleLoadViolation] = f; }
/** True if the address hit a external snoop while sitting in the LSQ.
* If this is true and a older instruction sees it, this instruction must
* reexecute
*/
bool hitExternalSnoop;
bool hitExternalSnoop() const { return instFlags[HitExternalSnoop]; }
void hitExternalSnoop(bool f) { instFlags[HitExternalSnoop] = f; }
/**
* Returns true if the DTB address translation is being delayed due to a hw
@ -165,159 +354,14 @@ class BaseDynInst : public RefCounted
*/
bool isTranslationDelayed() const
{
return (translationStarted && !translationCompleted);
return (translationStarted() && !translationCompleted());
}
/**
* Saved memory requests (needed when the DTB address translation is
* delayed due to a hw page table walk).
*/
RequestPtr savedReq;
RequestPtr savedSreqLow;
RequestPtr savedSreqHigh;
// Need a copy of main request pointer to verify on writes.
RequestPtr reqToVerify;
/** @todo: Consider making this private. */
public:
/** The sequence number of the instruction. */
InstSeqNum seqNum;
enum Status {
IqEntry, /// Instruction is in the IQ
RobEntry, /// Instruction is in the ROB
LsqEntry, /// Instruction is in the LSQ
Completed, /// Instruction has completed
ResultReady, /// Instruction has its result
CanIssue, /// Instruction can issue and execute
Issued, /// Instruction has issued
Executed, /// Instruction has executed
CanCommit, /// Instruction can commit
AtCommit, /// Instruction has reached commit
Committed, /// Instruction has committed
Squashed, /// Instruction is squashed
SquashedInIQ, /// Instruction is squashed in the IQ
SquashedInLSQ, /// Instruction is squashed in the LSQ
SquashedInROB, /// Instruction is squashed in the ROB
RecoverInst, /// Is a recover instruction
BlockingInst, /// Is a blocking instruction
ThreadsyncWait, /// Is a thread synchronization instruction
SerializeBefore, /// Needs to serialize on
/// instructions ahead of it
SerializeAfter, /// Needs to serialize instructions behind it
SerializeHandled, /// Serialization has been handled
NumStatus
};
/** The status of this BaseDynInst. Several bits can be set. */
std::bitset<NumStatus> status;
/** The thread this instruction is from. */
ThreadID threadNumber;
/** data address space ID, for loads & stores. */
short asid;
/** How many source registers are ready. */
unsigned readyRegs;
/** Pointer to the Impl's CPU object. */
ImplCPU *cpu;
/** Pointer to the thread state. */
ImplState *thread;
/** The kind of fault this instruction has generated. */
Fault fault;
/** Pointer to the data for the memory access. */
uint8_t *memData;
/** The effective virtual address (lds & stores only). */
Addr effAddr;
/** The size of the request */
Addr effSize;
/** Is the effective virtual address valid. */
bool effAddrValid;
/** The effective physical address. */
Addr physEffAddr;
/** The memory request flags (from translation). */
unsigned memReqFlags;
union Result {
uint64_t integer;
double dbl;
void set(uint64_t i) { integer = i; }
void set(double d) { dbl = d; }
void get(uint64_t& i) { i = integer; }
void get(double& d) { d = dbl; }
};
/** The result of the instruction; assumes an instruction can have many
* destination registers.
*/
std::queue<Result> instResult;
/** Records changes to result? */
bool recordResult;
/** Did this instruction execute, or is it predicated false */
bool predicate;
protected:
/** PC state for this instruction. */
TheISA::PCState pc;
/** Predicted PC state after this instruction. */
TheISA::PCState predPC;
/** If this is a branch that was predicted taken */
bool predTaken;
public:
#ifdef DEBUG
void dumpSNList();
#endif
/** Whether or not the source register is ready.
* @todo: Not sure this should be here vs the derived class.
*/
bool _readySrcRegIdx[MaxInstSrcRegs];
protected:
/** Flattened register index of the destination registers of this
* instruction.
*/
TheISA::RegIndex _flatDestRegIdx[TheISA::MaxInstDestRegs];
/** Flattened register index of the source registers of this
* instruction.
*/
TheISA::RegIndex _flatSrcRegIdx[TheISA::MaxInstSrcRegs];
/** Physical register index of the destination registers of this
* instruction.
*/
PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs];
/** Physical register index of the source registers of this
* instruction.
*/
PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs];
/** Physical register index of the previous producers of the
* architected destinations.
*/
PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs];
public:
/** Returns the physical register index of the i'th destination
* register.
*/
@ -329,6 +373,7 @@ class BaseDynInst : public RefCounted
/** Returns the physical register index of the i'th source register. */
PhysRegIndex renamedSrcRegIdx(int idx) const
{
assert(TheISA::MaxInstSrcRegs > idx);
return _srcRegIdx[idx];
}
@ -340,12 +385,6 @@ class BaseDynInst : public RefCounted
return _flatDestRegIdx[idx];
}
/** Returns the flattened register index of the i'th source register */
TheISA::RegIndex flattenedSrcRegIdx(int idx) const
{
return _flatSrcRegIdx[idx];
}
/** Returns the physical register index of the previous physical register
* that remapped to the same logical register index.
*/
@ -374,13 +413,6 @@ class BaseDynInst : public RefCounted
_srcRegIdx[idx] = renamed_src;
}
/** Flattens a source architectural register index into a logical index.
*/
void flattenSrcReg(int idx, TheISA::RegIndex flattened_src)
{
_flatSrcRegIdx[idx] = flattened_src;
}
/** Flattens a destination architectural register index into a logical
* index.
*/
@ -457,12 +489,12 @@ class BaseDynInst : public RefCounted
/** Returns whether the instruction was predicted taken or not. */
bool readPredTaken()
{
return predTaken;
return instFlags[PredTaken];
}
void setPredTaken(bool predicted_taken)
{
predTaken = predicted_taken;
instFlags[PredTaken] = predicted_taken;
}
/** Returns whether the instruction mispredicted. */
@ -588,7 +620,7 @@ class BaseDynInst : public RefCounted
template <class T>
void setResult(T t)
{
if (recordResult) {
if (instFlags[RecordResult]) {
Result instRes;
instRes.set(t);
instResult.push(instRes);
@ -774,12 +806,12 @@ class BaseDynInst : public RefCounted
bool readPredicate()
{
return predicate;
return instFlags[Predicate];
}
void setPredicate(bool val)
{
predicate = val;
instFlags[Predicate] = val;
if (traceData) {
traceData->setPredicate(val);
@ -798,54 +830,24 @@ class BaseDynInst : public RefCounted
/** Returns the thread context. */
ThreadContext *tcBase() { return thread->getTC(); }
private:
/** Instruction effective address.
* @todo: Consider if this is necessary or not.
*/
Addr instEffAddr;
/** Whether or not the effective address calculation is completed.
* @todo: Consider if this is necessary or not.
*/
bool eaCalcDone;
/** Is this instruction's memory access uncacheable. */
bool isUncacheable;
/** Has this instruction generated a memory request. */
bool reqMade;
public:
/** Sets the effective address. */
void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
void setEA(Addr &ea) { instEffAddr = ea; instFlags[EACalcDone] = true; }
/** Returns the effective address. */
const Addr &getEA() const { return instEffAddr; }
/** Returns whether or not the eff. addr. calculation has been completed. */
bool doneEACalc() { return eaCalcDone; }
bool doneEACalc() { return instFlags[EACalcDone]; }
/** Returns whether or not the eff. addr. source registers are ready. */
bool eaSrcsReady();
/** Whether or not the memory operation is done. */
bool memOpDone;
/** Is this instruction's memory access uncacheable. */
bool uncacheable() { return isUncacheable; }
bool uncacheable() { return instFlags[IsUncacheable]; }
/** Has this instruction generated a memory request. */
bool hasRequest() { return reqMade; }
public:
/** Load queue index. */
int16_t lqIdx;
/** Store queue index. */
int16_t sqIdx;
/** Iterator pointing to this BaseDynInst in the list of all insts. */
ListIt instListIt;
bool hasRequest() { return instFlags[ReqMade]; }
/** Returns iterator to this instruction in the list of all insts. */
ListIt &getInstListIt() { return instListIt; }
@ -868,12 +870,12 @@ Fault
BaseDynInst<Impl>::readMem(Addr addr, uint8_t *data,
unsigned size, unsigned flags)
{
reqMade = true;
instFlags[ReqMade] = true;
Request *req = NULL;
Request *sreqLow = NULL;
Request *sreqHigh = NULL;
if (reqMade && translationStarted) {
if (instFlags[ReqMade] && translationStarted()) {
req = savedReq;
sreqLow = savedSreqLow;
sreqHigh = savedSreqHigh;
@ -888,11 +890,11 @@ BaseDynInst<Impl>::readMem(Addr addr, uint8_t *data,
initiateTranslation(req, sreqLow, sreqHigh, NULL, BaseTLB::Read);
}
if (translationCompleted) {
if (translationCompleted()) {
if (fault == NoFault) {
effAddr = req->getVaddr();
effSize = size;
effAddrValid = true;
instFlags[EffAddrValid] = true;
if (cpu->checker) {
if (reqToVerify != NULL) {
@ -931,12 +933,12 @@ BaseDynInst<Impl>::writeMem(uint8_t *data, unsigned size,
traceData->setAddr(addr);
}
reqMade = true;
instFlags[ReqMade] = true;
Request *req = NULL;
Request *sreqLow = NULL;
Request *sreqHigh = NULL;
if (reqMade && translationStarted) {
if (instFlags[ReqMade] && translationStarted()) {
req = savedReq;
sreqLow = savedSreqLow;
sreqHigh = savedSreqHigh;
@ -951,10 +953,10 @@ BaseDynInst<Impl>::writeMem(uint8_t *data, unsigned size,
initiateTranslation(req, sreqLow, sreqHigh, res, BaseTLB::Write);
}
if (fault == NoFault && translationCompleted) {
if (fault == NoFault && translationCompleted()) {
effAddr = req->getVaddr();
effSize = size;
effAddrValid = true;
instFlags[EffAddrValid] = true;
if (cpu->checker) {
if (reqToVerify != NULL) {
@ -991,7 +993,7 @@ BaseDynInst<Impl>::initiateTranslation(RequestPtr req, RequestPtr sreqLow,
RequestPtr sreqHigh, uint64_t *res,
BaseTLB::Mode mode)
{
translationStarted = true;
translationStarted(true);
if (!TheISA::HasUnalignedMemAcc || sreqLow == NULL) {
WholeTranslationState *state =
@ -1001,7 +1003,7 @@ BaseDynInst<Impl>::initiateTranslation(RequestPtr req, RequestPtr sreqLow,
DataTranslation<BaseDynInstPtr> *trans =
new DataTranslation<BaseDynInstPtr>(this, state);
cpu->dtb->translateTiming(req, thread->getTC(), trans, mode);
if (!translationCompleted) {
if (!translationCompleted()) {
// Save memory requests.
savedReq = state->mainReq;
savedSreqLow = state->sreqLow;
@ -1019,7 +1021,7 @@ BaseDynInst<Impl>::initiateTranslation(RequestPtr req, RequestPtr sreqLow,
cpu->dtb->translateTiming(sreqLow, thread->getTC(), stransLow, mode);
cpu->dtb->translateTiming(sreqHigh, thread->getTC(), stransHigh, mode);
if (!translationCompleted) {
if (!translationCompleted()) {
// Save memory requests.
savedReq = state->mainReq;
savedSreqLow = state->sreqLow;
@ -1034,8 +1036,7 @@ BaseDynInst<Impl>::finishTranslation(WholeTranslationState *state)
{
fault = state->getFault();
if (state->isUncacheable())
isUncacheable = true;
instFlags[IsUncacheable] = state->isUncacheable();
if (fault == NoFault) {
physEffAddr = state->getPaddr();
@ -1051,7 +1052,7 @@ BaseDynInst<Impl>::finishTranslation(WholeTranslationState *state)
}
delete state;
translationCompleted = true;
translationCompleted(true);
}
#endif // __CPU_BASE_DYN_INST_HH__

View file

@ -60,13 +60,12 @@ BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst,
StaticInstPtr _macroop,
TheISA::PCState _pc, TheISA::PCState _predPC,
InstSeqNum seq_num, ImplCPU *cpu)
: staticInst(_staticInst), macroop(_macroop), traceData(NULL), cpu(cpu)
: staticInst(_staticInst), cpu(cpu), traceData(NULL), macroop(_macroop)
{
seqNum = seq_num;
pc = _pc;
predPC = _predPC;
predTaken = false;
initVars();
}
@ -74,7 +73,7 @@ BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst,
template <class Impl>
BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst,
StaticInstPtr _macroop)
: staticInst(_staticInst), macroop(_macroop), traceData(NULL)
: staticInst(_staticInst), traceData(NULL), macroop(_macroop)
{
seqNum = 0;
initVars();
@ -86,25 +85,14 @@ BaseDynInst<Impl>::initVars()
{
memData = NULL;
effAddr = 0;
effAddrValid = false;
physEffAddr = 0;
translationStarted = false;
translationCompleted = false;
possibleLoadViolation = false;
hitExternalSnoop = false;
isUncacheable = false;
reqMade = false;
readyRegs = 0;
recordResult = true;
status.reset();
eaCalcDone = false;
memOpDone = false;
predicate = true;
instFlags.reset();
instFlags[RecordResult] = true;
instFlags[Predicate] = true;
lqIdx = -1;
sqIdx = -1;

View file

@ -206,9 +206,9 @@ class BPredUnit
PredictorHistory(const InstSeqNum &seq_num, Addr instPC,
bool pred_taken, void *bp_history,
ThreadID _tid)
: seqNum(seq_num), pc(instPC), RASTarget(0), RASIndex(0),
tid(_tid), predTaken(pred_taken), usedRAS(0),
wasCall(0), wasReturn(0), validBTB(0), bpHistory(bp_history)
: seqNum(seq_num), pc(instPC), bpHistory(bp_history), RASTarget(0),
RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0),
wasCall(0), wasReturn(0), validBTB(0)
{}
bool operator==(const PredictorHistory &entry) const {
@ -221,6 +221,12 @@ class BPredUnit
/** The PC associated with the sequence number. */
Addr pc;
/** Pointer to the history object passed back from the branch
* predictor. It is used to update or restore state of the
* branch predictor.
*/
void *bpHistory;
/** The RAS target (only valid if a return). */
TheISA::PCState RASTarget;
@ -243,11 +249,6 @@ class BPredUnit
bool wasReturn;
/** Whether or not the instruction had a valid BTB entry. */
bool validBTB;
/** Pointer to the history object passed back from the branch
* predictor. It is used to update or restore state of the
* branch predictor.
*/
void *bpHistory;
};
typedef std::list<PredictorHistory> History;

View file

@ -96,15 +96,14 @@ struct DefaultIEWDefaultCommit {
int size;
DynInstPtr insts[Impl::MaxWidth];
DynInstPtr mispredictInst[Impl::MaxThreads];
Addr mispredPC[Impl::MaxThreads];
InstSeqNum squashedSeqNum[Impl::MaxThreads];
TheISA::PCState pc[Impl::MaxThreads];
bool squash[Impl::MaxThreads];
bool branchMispredict[Impl::MaxThreads];
DynInstPtr mispredictInst[Impl::MaxThreads];
bool branchTaken[Impl::MaxThreads];
Addr mispredPC[Impl::MaxThreads];
TheISA::PCState pc[Impl::MaxThreads];
InstSeqNum squashedSeqNum[Impl::MaxThreads];
bool includeSquashInst[Impl::MaxThreads];
};
@ -122,21 +121,17 @@ template<class Impl>
struct TimeBufStruct {
typedef typename Impl::DynInstPtr DynInstPtr;
struct decodeComm {
bool squash;
bool predIncorrect;
uint64_t branchAddr;
InstSeqNum doneSeqNum;
// @todo: Might want to package this kind of branch stuff into a single
// struct as it is used pretty frequently.
bool branchMispredict;
DynInstPtr mispredictInst;
bool branchTaken;
DynInstPtr squashInst;
Addr mispredPC;
TheISA::PCState nextPC;
DynInstPtr squashInst;
unsigned branchCount;
bool squash;
bool predIncorrect;
bool branchMispredict;
bool branchTaken;
};
decodeComm decodeInfo[Impl::MaxThreads];

View file

@ -1244,11 +1244,11 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
head_inst->microPC(),
head_inst->seqNum,
head_inst->staticInst->disassemble(head_inst->instAddr()));
DPRINTFR(O3PipeView, "O3PipeView:decode:%llu\n", head_inst->decodeTick);
DPRINTFR(O3PipeView, "O3PipeView:rename:%llu\n", head_inst->renameTick);
DPRINTFR(O3PipeView, "O3PipeView:dispatch:%llu\n", head_inst->dispatchTick);
DPRINTFR(O3PipeView, "O3PipeView:issue:%llu\n", head_inst->issueTick);
DPRINTFR(O3PipeView, "O3PipeView:complete:%llu\n", head_inst->completeTick);
DPRINTFR(O3PipeView, "O3PipeView:decode:%llu\n", head_inst->fetchTick + head_inst->decodeTick);
DPRINTFR(O3PipeView, "O3PipeView:rename:%llu\n", head_inst->fetchTick + head_inst->renameTick);
DPRINTFR(O3PipeView, "O3PipeView:dispatch:%llu\n", head_inst->fetchTick + head_inst->dispatchTick);
DPRINTFR(O3PipeView, "O3PipeView:issue:%llu\n", head_inst->fetchTick + head_inst->issueTick);
DPRINTFR(O3PipeView, "O3PipeView:complete:%llu\n", head_inst->fetchTick + head_inst->completeTick);
DPRINTFR(O3PipeView, "O3PipeView:retire:%llu\n", curTick());
#endif

View file

@ -709,7 +709,7 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
--insts_available;
#if TRACING_ON
inst->decodeTick = curTick();
inst->decodeTick = curTick() - inst->fetchTick;
#endif
// Ensure that if it was predicted as a branch, it really is a

View file

@ -107,26 +107,28 @@ class BaseO3DynInst : public BaseDynInst<Impl>
void initVars();
protected:
/** Values to be written to the destination misc. registers. */
MiscReg _destMiscRegVal[TheISA::MaxMiscDestRegs];
/** Indexes of the destination misc. registers. They are needed to defer
* the write accesses to the misc. registers until the commit stage, when
* the instruction is out of its speculative state.
*/
int _destMiscRegIdx[MaxInstDestRegs];
/** Values to be written to the destination misc. registers. */
MiscReg _destMiscRegVal[MaxInstDestRegs];
short _destMiscRegIdx[TheISA::MaxMiscDestRegs];
/** Number of destination misc. registers. */
int _numDestMiscRegs;
uint8_t _numDestMiscRegs;
public:
#if TRACING_ON
/** Tick records used for the pipeline activity viewer. */
Tick fetchTick;
Tick decodeTick;
Tick renameTick;
Tick dispatchTick;
Tick issueTick;
Tick completeTick;
uint32_t decodeTick;
uint32_t renameTick;
uint32_t dispatchTick;
uint32_t issueTick;
uint32_t completeTick;
#endif
/** Reads a misc. register, including any side-effects the read
@ -145,6 +147,7 @@ class BaseO3DynInst : public BaseDynInst<Impl>
/** Writes to misc. registers are recorded and deferred until the
* commit stage, when updateMiscRegs() is called.
*/
assert(_numDestMiscRegs < TheISA::MaxMiscDestRegs);
_destMiscRegIdx[_numDestMiscRegs] = misc_reg;
_destMiscRegVal[_numDestMiscRegs] = val;
_numDestMiscRegs++;

View file

@ -75,9 +75,10 @@ BaseO3DynInst<Impl>::initVars()
for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i);
this->_readySrcRegIdx[i] = 0;
}
this->_readySrcRegIdx.reset();
_numDestMiscRegs = 0;
#if TRACING_ON

View file

@ -1152,7 +1152,7 @@ DefaultIEW<Impl>::dispatchInsts(ThreadID tid)
++iewDispatchedInsts;
#if TRACING_ON
inst->dispatchTick = curTick();
inst->dispatchTick = curTick() - inst->fetchTick;
#endif
}
@ -1617,7 +1617,7 @@ DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
iewExecutedInsts++;
#if TRACING_ON
inst->completeTick = curTick();
inst->completeTick = curTick() - inst->fetchTick;
#endif
//

View file

@ -859,7 +859,7 @@ InstructionQueue<Impl>::scheduleReadyInsts()
++total_issued;
#if TRACING_ON
issuing_inst->issueTick = curTick();
issuing_inst->issueTick = curTick() - issuing_inst->fetchTick;
#endif
if (!issuing_inst->isMemRef()) {
@ -1054,8 +1054,8 @@ InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
DPRINTF(IQ, "Rescheduling mem inst [sn:%lli]\n", resched_inst->seqNum);
// Reset DTB translation state
resched_inst->translationStarted = false;
resched_inst->translationCompleted = false;
resched_inst->translationStarted(false);
resched_inst->translationCompleted(false);
resched_inst->clearCanIssue();
memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
@ -1079,7 +1079,7 @@ InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
++freeEntries;
completed_inst->memOpDone = true;
completed_inst->memOpDone(true);
memDepUnit[tid].completed(completed_inst);
count[tid]--;
@ -1098,7 +1098,7 @@ InstructionQueue<Impl>::getDeferredMemInstToExecute()
{
for (ListIt it = deferredMemInsts.begin(); it != deferredMemInsts.end();
++it) {
if ((*it)->translationCompleted || (*it)->isSquashed()) {
if ((*it)->translationCompleted() || (*it)->isSquashed()) {
DynInstPtr ret = *it;
deferredMemInsts.erase(it);
return ret;
@ -1165,7 +1165,7 @@ InstructionQueue<Impl>::doSquash(ThreadID tid)
if (!squashed_inst->isIssued() ||
(squashed_inst->isMemRef() &&
!squashed_inst->memOpDone)) {
!squashed_inst->memOpDone())) {
DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %s squashed.\n",
tid, squashed_inst->seqNum, squashed_inst->pcState());
@ -1456,7 +1456,7 @@ InstructionQueue<Impl>::dumpInsts()
++valid_num;
cprintf("Count:%i\n", valid_num);
} else if ((*inst_list_it)->isMemRef() &&
!(*inst_list_it)->memOpDone) {
!(*inst_list_it)->memOpDone()) {
// Loads that have not been marked as executed
// still count towards the total instructions.
++valid_num;
@ -1473,7 +1473,7 @@ InstructionQueue<Impl>::dumpInsts()
(*inst_list_it)->isSquashed());
if ((*inst_list_it)->isMemRef()) {
cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone());
}
cprintf("\n");
@ -1498,7 +1498,7 @@ InstructionQueue<Impl>::dumpInsts()
++valid_num;
cprintf("Count:%i\n", valid_num);
} else if ((*inst_list_it)->isMemRef() &&
!(*inst_list_it)->memOpDone) {
!(*inst_list_it)->memOpDone()) {
// Loads that have not been marked as executed
// still count towards the total instructions.
++valid_num;
@ -1515,7 +1515,7 @@ InstructionQueue<Impl>::dumpInsts()
(*inst_list_it)->isSquashed());
if ((*inst_list_it)->isMemRef()) {
cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone());
}
cprintf("\n");

View file

@ -275,28 +275,28 @@ class LSQUnit {
public:
/** Default constructor. */
LSQSenderState()
: noWB(false), isSplit(false), pktToSend(false), outstanding(1),
mainPkt(NULL), pendingPacket(NULL)
{ }
: mainPkt(NULL), pendingPacket(NULL), outstanding(1),
noWB(false), isSplit(false), pktToSend(false)
{ }
/** Instruction who initiated the access to memory. */
DynInstPtr inst;
/** The main packet from a split load, used during writeback. */
PacketPtr mainPkt;
/** A second packet from a split store that needs sending. */
PacketPtr pendingPacket;
/** The LQ/SQ index of the instruction. */
uint8_t idx;
/** Number of outstanding packets to complete. */
uint8_t outstanding;
/** Whether or not it is a load. */
bool isLoad;
/** The LQ/SQ index of the instruction. */
int idx;
/** Whether or not the instruction will need to writeback. */
bool noWB;
/** Whether or not this access is split in two. */
bool isSplit;
/** Whether or not there is a packet that needs sending. */
bool pktToSend;
/** Number of outstanding packets to complete. */
int outstanding;
/** The main packet from a split load, used during writeback. */
PacketPtr mainPkt;
/** A second packet from a split store that needs sending. */
PacketPtr pendingPacket;
/** Completes a packet and returns whether the access is finished. */
inline bool complete() { return --outstanding == 0; }
@ -342,7 +342,8 @@ class LSQUnit {
{
std::memset(data, 0, sizeof(data));
}
/** The store data. */
char data[16];
/** The store instruction. */
DynInstPtr inst;
/** The request for the store. */
@ -351,9 +352,7 @@ class LSQUnit {
RequestPtr sreqLow;
RequestPtr sreqHigh;
/** The size of the store. */
int size;
/** The store data. */
char data[16];
uint8_t size;
/** Whether or not the store is split into two requests. */
bool isSplit;
/** Whether or not the store can writeback. */
@ -593,9 +592,9 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
// Disable recording the result temporarily. Writing to misc
// regs normally updates the result, but this is not the
// desired behavior when handling store conditionals.
load_inst->recordResult = false;
load_inst->recordResult(false);
TheISA::handleLockedRead(load_inst.get(), req);
load_inst->recordResult = true;
load_inst->recordResult(true);
}
if (req->isMmappedIpr()) {
@ -651,7 +650,7 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
else if (storeQueue[store_idx].inst->uncacheable())
continue;
assert(storeQueue[store_idx].inst->effAddrValid);
assert(storeQueue[store_idx].inst->effAddrValid());
// Check if the store data is within the lower and upper bounds of
// addresses that the request needs.

View file

@ -465,7 +465,7 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
while (load_idx != loadTail) {
DynInstPtr ld_inst = loadQueue[load_idx];
if (!ld_inst->effAddrValid || ld_inst->uncacheable()) {
if (!ld_inst->effAddrValid() || ld_inst->uncacheable()) {
incrLdIdx(load_idx);
continue;
}
@ -475,7 +475,7 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
ld_inst->seqNum, load_addr, invalidate_addr);
if (load_addr == invalidate_addr) {
if (ld_inst->possibleLoadViolation) {
if (ld_inst->possibleLoadViolation()) {
DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
ld_inst->physEffAddr, pkt->getAddr(), ld_inst->seqNum);
@ -485,7 +485,7 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
// If a older load checks this and it's true
// then we might have missed the snoop
// in which case we need to invalidate to be sure
ld_inst->hitExternalSnoop = true;
ld_inst->hitExternalSnoop(true);
}
}
incrLdIdx(load_idx);
@ -507,7 +507,7 @@ LSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst)
*/
while (load_idx != loadTail) {
DynInstPtr ld_inst = loadQueue[load_idx];
if (!ld_inst->effAddrValid || ld_inst->uncacheable()) {
if (!ld_inst->effAddrValid() || ld_inst->uncacheable()) {
incrLdIdx(load_idx);
continue;
}
@ -521,7 +521,7 @@ LSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst)
// If this load is to the same block as an external snoop
// invalidate that we've observed then the load needs to be
// squashed as it could have newer data
if (ld_inst->hitExternalSnoop) {
if (ld_inst->hitExternalSnoop()) {
if (!memDepViolator ||
ld_inst->seqNum < memDepViolator->seqNum) {
DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] "
@ -540,7 +540,7 @@ LSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst)
// Otherwise, mark the load has a possible load violation
// and if we see a snoop before it's commited, we need to squash
ld_inst->possibleLoadViolation = true;
ld_inst->possibleLoadViolation(true);
DPRINTF(LSQUnit, "Found possible load violaiton at addr: %#x"
" between instructions [sn:%lli] and [sn:%lli]\n",
inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
@ -610,7 +610,7 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
iewStage->instToCommit(inst);
iewStage->activityThisCycle();
} else if (!loadBlocked()) {
assert(inst->effAddrValid);
assert(inst->effAddrValid());
int load_idx = inst->lqIdx;
incrLdIdx(load_idx);
@ -857,9 +857,9 @@ LSQUnit<Impl>::writebackStores()
// Disable recording the result temporarily. Writing to
// misc regs normally updates the result, but this is not
// the desired behavior when handling store conditionals.
inst->recordResult = false;
inst->recordResult(false);
bool success = TheISA::handleLockedWrite(inst.get(), req);
inst->recordResult = true;
inst->recordResult(true);
if (!success) {
// Instantly complete this store.

View file

@ -692,7 +692,7 @@ DefaultRename<Impl>::renameInsts(ThreadID tid)
++renamed_insts;
#if TRACING_ON
inst->renameTick = curTick();
inst->renameTick = curTick() - inst->fetchTick;
#endif
// Put instruction in rename queue.
@ -997,8 +997,6 @@ DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid)
panic("Reg index is out of bound: %d.", src_reg);
}
inst->flattenSrcReg(src_idx, flat_src_reg);
// Look up the source registers to get the phys. register they've
// been renamed to, and set the sources to those registers.
PhysRegIndex renamed_reg = renameMap[tid]->lookup(flat_src_reg);