Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/tmp/clean2 src/cpu/base_dyn_inst.hh: Hand merge. Line is no longer needed because it's handled in the ISA. --HG-- extra : convert_revision : 0be4067aa38759a5631c6940f0167d48fde2b680
This commit is contained in:
commit
047f77102b
21 changed files with 353 additions and 148 deletions
|
@ -728,8 +728,10 @@ decode OPCODE default Unknown::unknown() {
|
||||||
0: OpcdecFault::hw_st_quad();
|
0: OpcdecFault::hw_st_quad();
|
||||||
1: decode HW_LDST_QUAD {
|
1: decode HW_LDST_QUAD {
|
||||||
format HwLoad {
|
format HwLoad {
|
||||||
0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }}, L);
|
0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }},
|
||||||
1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }}, Q);
|
L, IsSerializing, IsSerializeBefore);
|
||||||
|
1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }},
|
||||||
|
Q, IsSerializing, IsSerializeBefore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -740,9 +742,9 @@ decode OPCODE default Unknown::unknown() {
|
||||||
1: decode HW_LDST_COND {
|
1: decode HW_LDST_COND {
|
||||||
0: decode HW_LDST_QUAD {
|
0: decode HW_LDST_QUAD {
|
||||||
0: hw_st({{ EA = (Rb + disp) & ~3; }},
|
0: hw_st({{ EA = (Rb + disp) & ~3; }},
|
||||||
{{ Mem.ul = Ra<31:0>; }}, L);
|
{{ Mem.ul = Ra<31:0>; }}, L, IsSerializing, IsSerializeBefore);
|
||||||
1: hw_st({{ EA = (Rb + disp) & ~7; }},
|
1: hw_st({{ EA = (Rb + disp) & ~7; }},
|
||||||
{{ Mem.uq = Ra.uq; }}, Q);
|
{{ Mem.uq = Ra.uq; }}, Q, IsSerializing, IsSerializeBefore);
|
||||||
}
|
}
|
||||||
|
|
||||||
1: FailUnimpl::hw_st_cond();
|
1: FailUnimpl::hw_st_cond();
|
||||||
|
|
|
@ -226,7 +226,8 @@ BaseCPU::startup()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (params->progress_interval) {
|
if (params->progress_interval) {
|
||||||
new CPUProgressEvent(&mainEventQueue, params->progress_interval,
|
new CPUProgressEvent(&mainEventQueue,
|
||||||
|
cycles(params->progress_interval),
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,15 +171,15 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
/** The kind of fault this instruction has generated. */
|
/** The kind of fault this instruction has generated. */
|
||||||
Fault fault;
|
Fault fault;
|
||||||
|
|
||||||
/** The memory request. */
|
|
||||||
Request *req;
|
|
||||||
|
|
||||||
/** Pointer to the data for the memory access. */
|
/** Pointer to the data for the memory access. */
|
||||||
uint8_t *memData;
|
uint8_t *memData;
|
||||||
|
|
||||||
/** The effective virtual address (lds & stores only). */
|
/** The effective virtual address (lds & stores only). */
|
||||||
Addr effAddr;
|
Addr effAddr;
|
||||||
|
|
||||||
|
/** Is the effective virtual address valid. */
|
||||||
|
bool effAddrValid;
|
||||||
|
|
||||||
/** The effective physical address. */
|
/** The effective physical address. */
|
||||||
Addr physEffAddr;
|
Addr physEffAddr;
|
||||||
|
|
||||||
|
@ -601,12 +601,18 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
/** Returns whether or not this instruction is ready to issue. */
|
/** Returns whether or not this instruction is ready to issue. */
|
||||||
bool readyToIssue() const { return status[CanIssue]; }
|
bool readyToIssue() const { return status[CanIssue]; }
|
||||||
|
|
||||||
|
/** Clears this instruction being able to issue. */
|
||||||
|
void clearCanIssue() { status.reset(CanIssue); }
|
||||||
|
|
||||||
/** Sets this instruction as issued from the IQ. */
|
/** Sets this instruction as issued from the IQ. */
|
||||||
void setIssued() { status.set(Issued); }
|
void setIssued() { status.set(Issued); }
|
||||||
|
|
||||||
/** Returns whether or not this instruction has issued. */
|
/** Returns whether or not this instruction has issued. */
|
||||||
bool isIssued() const { return status[Issued]; }
|
bool isIssued() const { return status[Issued]; }
|
||||||
|
|
||||||
|
/** Clears this instruction as being issued. */
|
||||||
|
void clearIssued() { status.reset(Issued); }
|
||||||
|
|
||||||
/** Sets this instruction as executed. */
|
/** Sets this instruction as executed. */
|
||||||
void setExecuted() { status.set(Executed); }
|
void setExecuted() { status.set(Executed); }
|
||||||
|
|
||||||
|
@ -729,6 +735,12 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
*/
|
*/
|
||||||
bool eaCalcDone;
|
bool eaCalcDone;
|
||||||
|
|
||||||
|
/** Is this instruction's memory access uncacheable. */
|
||||||
|
bool isUncacheable;
|
||||||
|
|
||||||
|
/** Has this instruction generated a memory request. */
|
||||||
|
bool reqMade;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Sets the effective address. */
|
/** Sets the effective address. */
|
||||||
void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
|
void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
|
||||||
|
@ -745,6 +757,12 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
/** Whether or not the memory operation is done. */
|
/** Whether or not the memory operation is done. */
|
||||||
bool memOpDone;
|
bool memOpDone;
|
||||||
|
|
||||||
|
/** Is this instruction's memory access uncacheable. */
|
||||||
|
bool uncacheable() { return isUncacheable; }
|
||||||
|
|
||||||
|
/** Has this instruction generated a memory request. */
|
||||||
|
bool hasRequest() { return reqMade; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Load queue index. */
|
/** Load queue index. */
|
||||||
int16_t lqIdx;
|
int16_t lqIdx;
|
||||||
|
@ -776,25 +794,25 @@ template<class T>
|
||||||
inline Fault
|
inline Fault
|
||||||
BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
||||||
{
|
{
|
||||||
// Sometimes reads will get retried, so they may come through here
|
reqMade = true;
|
||||||
// twice.
|
Request *req = new Request();
|
||||||
if (!req) {
|
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
|
||||||
req = new Request();
|
req->setThreadContext(thread->readCpuId(), threadNumber);
|
||||||
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
|
|
||||||
req->setThreadContext(thread->readCpuId(), threadNumber);
|
|
||||||
} else {
|
|
||||||
assert(addr == req->getVaddr());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() >
|
if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() >
|
||||||
TheISA::VMPageSize) {
|
TheISA::VMPageSize) {
|
||||||
|
delete req;
|
||||||
return TheISA::genAlignmentFault();
|
return TheISA::genAlignmentFault();
|
||||||
}
|
}
|
||||||
|
|
||||||
fault = cpu->translateDataReadReq(req, thread);
|
fault = cpu->translateDataReadReq(req, thread);
|
||||||
|
|
||||||
|
if (req->isUncacheable())
|
||||||
|
isUncacheable = true;
|
||||||
|
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
effAddr = req->getVaddr();
|
effAddr = req->getVaddr();
|
||||||
|
effAddrValid = true;
|
||||||
physEffAddr = req->getPaddr();
|
physEffAddr = req->getPaddr();
|
||||||
memReqFlags = req->getFlags();
|
memReqFlags = req->getFlags();
|
||||||
|
|
||||||
|
@ -817,6 +835,7 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
|
||||||
// Commit will have to clean up whatever happened. Set this
|
// Commit will have to clean up whatever happened. Set this
|
||||||
// instruction as executed.
|
// instruction as executed.
|
||||||
this->setExecuted();
|
this->setExecuted();
|
||||||
|
delete req;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
|
@ -837,21 +856,25 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
traceData->setData(data);
|
traceData->setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(req == NULL);
|
reqMade = true;
|
||||||
|
Request *req = new Request();
|
||||||
req = new Request();
|
|
||||||
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
|
req->setVirt(asid, addr, sizeof(T), flags, this->PC);
|
||||||
req->setThreadContext(thread->readCpuId(), threadNumber);
|
req->setThreadContext(thread->readCpuId(), threadNumber);
|
||||||
|
|
||||||
if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() >
|
if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() >
|
||||||
TheISA::VMPageSize) {
|
TheISA::VMPageSize) {
|
||||||
|
delete req;
|
||||||
return TheISA::genAlignmentFault();
|
return TheISA::genAlignmentFault();
|
||||||
}
|
}
|
||||||
|
|
||||||
fault = cpu->translateDataWriteReq(req, thread);
|
fault = cpu->translateDataWriteReq(req, thread);
|
||||||
|
|
||||||
|
if (req->isUncacheable())
|
||||||
|
isUncacheable = true;
|
||||||
|
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
effAddr = req->getVaddr();
|
effAddr = req->getVaddr();
|
||||||
|
effAddrValid = true;
|
||||||
physEffAddr = req->getPaddr();
|
physEffAddr = req->getPaddr();
|
||||||
memReqFlags = req->getFlags();
|
memReqFlags = req->getFlags();
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -863,12 +886,8 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
#else
|
#else
|
||||||
fault = cpu->write(req, data, sqIdx);
|
fault = cpu->write(req, data, sqIdx);
|
||||||
#endif
|
#endif
|
||||||
}
|
} else {
|
||||||
|
delete req;
|
||||||
if (res) {
|
|
||||||
// always return some result to keep misspeculated paths
|
|
||||||
// (which will ignore faults) deterministic
|
|
||||||
*res = (fault == NoFault) ? req->getExtraData() : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fault;
|
return fault;
|
||||||
|
|
|
@ -92,11 +92,13 @@ template <class Impl>
|
||||||
void
|
void
|
||||||
BaseDynInst<Impl>::initVars()
|
BaseDynInst<Impl>::initVars()
|
||||||
{
|
{
|
||||||
req = NULL;
|
|
||||||
memData = NULL;
|
memData = NULL;
|
||||||
effAddr = 0;
|
effAddr = 0;
|
||||||
|
effAddrValid = false;
|
||||||
physEffAddr = 0;
|
physEffAddr = 0;
|
||||||
|
|
||||||
|
isUncacheable = false;
|
||||||
|
reqMade = false;
|
||||||
readyRegs = 0;
|
readyRegs = 0;
|
||||||
|
|
||||||
instResult.integer = 0;
|
instResult.integer = 0;
|
||||||
|
@ -140,10 +142,6 @@ BaseDynInst<Impl>::initVars()
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
BaseDynInst<Impl>::~BaseDynInst()
|
BaseDynInst<Impl>::~BaseDynInst()
|
||||||
{
|
{
|
||||||
if (req) {
|
|
||||||
delete req;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memData) {
|
if (memData) {
|
||||||
delete [] memData;
|
delete [] memData;
|
||||||
}
|
}
|
||||||
|
@ -271,7 +269,7 @@ void
|
||||||
BaseDynInst<Impl>::markSrcRegReady()
|
BaseDynInst<Impl>::markSrcRegReady()
|
||||||
{
|
{
|
||||||
if (++readyRegs == numSrcRegs()) {
|
if (++readyRegs == numSrcRegs()) {
|
||||||
status.set(CanIssue);
|
setCanIssue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,11 +50,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
|
||||||
Param<int> clock;
|
Param<int> clock;
|
||||||
Param<int> phase;
|
Param<int> phase;
|
||||||
Param<int> numThreads;
|
Param<int> numThreads;
|
||||||
|
Param<int> cpu_id;
|
||||||
Param<int> activity;
|
Param<int> activity;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
SimObjectParam<System *> system;
|
SimObjectParam<System *> system;
|
||||||
Param<int> cpu_id;
|
|
||||||
SimObjectParam<AlphaISA::ITB *> itb;
|
SimObjectParam<AlphaISA::ITB *> itb;
|
||||||
SimObjectParam<AlphaISA::DTB *> dtb;
|
SimObjectParam<AlphaISA::DTB *> dtb;
|
||||||
Param<Tick> profile;
|
Param<Tick> profile;
|
||||||
|
@ -161,11 +161,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
|
||||||
INIT_PARAM(clock, "clock speed"),
|
INIT_PARAM(clock, "clock speed"),
|
||||||
INIT_PARAM_DFLT(phase, "clock phase", 0),
|
INIT_PARAM_DFLT(phase, "clock phase", 0),
|
||||||
INIT_PARAM(numThreads, "number of HW thread contexts"),
|
INIT_PARAM(numThreads, "number of HW thread contexts"),
|
||||||
|
INIT_PARAM(cpu_id, "processor ID"),
|
||||||
INIT_PARAM_DFLT(activity, "Initial activity count", 0),
|
INIT_PARAM_DFLT(activity, "Initial activity count", 0),
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
INIT_PARAM(system, "System object"),
|
INIT_PARAM(system, "System object"),
|
||||||
INIT_PARAM(cpu_id, "processor ID"),
|
|
||||||
INIT_PARAM(itb, "Instruction translation buffer"),
|
INIT_PARAM(itb, "Instruction translation buffer"),
|
||||||
INIT_PARAM(dtb, "Data translation buffer"),
|
INIT_PARAM(dtb, "Data translation buffer"),
|
||||||
INIT_PARAM(profile, ""),
|
INIT_PARAM(profile, ""),
|
||||||
|
@ -305,14 +305,15 @@ CREATE_SIM_OBJECT(DerivO3CPU)
|
||||||
AlphaSimpleParams *params = new AlphaSimpleParams;
|
AlphaSimpleParams *params = new AlphaSimpleParams;
|
||||||
|
|
||||||
params->clock = clock;
|
params->clock = clock;
|
||||||
|
params->phase = phase;
|
||||||
|
|
||||||
params->name = getInstanceName();
|
params->name = getInstanceName();
|
||||||
params->numberOfThreads = actual_num_threads;
|
params->numberOfThreads = actual_num_threads;
|
||||||
|
params->cpu_id = cpu_id;
|
||||||
params->activity = activity;
|
params->activity = activity;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
params->system = system;
|
params->system = system;
|
||||||
params->cpu_id = cpu_id;
|
|
||||||
params->itb = itb;
|
params->itb = itb;
|
||||||
params->dtb = dtb;
|
params->dtb = dtb;
|
||||||
params->profile = profile;
|
params->profile = profile;
|
||||||
|
|
|
@ -114,6 +114,7 @@ AlphaO3CPU<Impl>::AlphaO3CPU(Params *params) : FullO3CPU<Impl>(params)
|
||||||
#endif
|
#endif
|
||||||
// Give the thread the TC.
|
// Give the thread the TC.
|
||||||
this->thread[i]->tc = tc;
|
this->thread[i]->tc = tc;
|
||||||
|
this->thread[i]->setCpuId(params->cpu_id);
|
||||||
|
|
||||||
// Add the TC to the CPU's list of TC's.
|
// Add the TC to the CPU's list of TC's.
|
||||||
this->threadContexts.push_back(tc);
|
this->threadContexts.push_back(tc);
|
||||||
|
|
|
@ -247,6 +247,11 @@ class DefaultCommit
|
||||||
/** Handles squashing due to an TC write. */
|
/** Handles squashing due to an TC write. */
|
||||||
void squashFromTC(unsigned tid);
|
void squashFromTC(unsigned tid);
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
/** Handles processing an interrupt. */
|
||||||
|
void handleInterrupt();
|
||||||
|
#endif // FULL_SYSTEM
|
||||||
|
|
||||||
/** Commits as many instructions as possible. */
|
/** Commits as many instructions as possible. */
|
||||||
void commitInsts();
|
void commitInsts();
|
||||||
|
|
||||||
|
@ -409,6 +414,16 @@ class DefaultCommit
|
||||||
/** The sequence number of the youngest valid instruction in the ROB. */
|
/** The sequence number of the youngest valid instruction in the ROB. */
|
||||||
InstSeqNum youngestSeqNum[Impl::MaxThreads];
|
InstSeqNum youngestSeqNum[Impl::MaxThreads];
|
||||||
|
|
||||||
|
/** Records if there is a trap currently in flight. */
|
||||||
|
bool trapInFlight[Impl::MaxThreads];
|
||||||
|
|
||||||
|
/** Records if there were any stores committed this cycle. */
|
||||||
|
bool committedStores[Impl::MaxThreads];
|
||||||
|
|
||||||
|
/** Records if commit should check if the ROB is truly empty (see
|
||||||
|
commit_impl.hh). */
|
||||||
|
bool checkEmptyROB[Impl::MaxThreads];
|
||||||
|
|
||||||
/** Pointer to the list of active threads. */
|
/** Pointer to the list of active threads. */
|
||||||
std::list<unsigned> *activeThreads;
|
std::list<unsigned> *activeThreads;
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,9 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
|
||||||
for (int i=0; i < numThreads; i++) {
|
for (int i=0; i < numThreads; i++) {
|
||||||
commitStatus[i] = Idle;
|
commitStatus[i] = Idle;
|
||||||
changedROBNumEntries[i] = false;
|
changedROBNumEntries[i] = false;
|
||||||
|
checkEmptyROB[i] = false;
|
||||||
|
trapInFlight[i] = false;
|
||||||
|
committedStores[i] = false;
|
||||||
trapSquash[i] = false;
|
trapSquash[i] = false;
|
||||||
tcSquash[i] = false;
|
tcSquash[i] = false;
|
||||||
PC[i] = nextPC[i] = nextNPC[i] = 0;
|
PC[i] = nextPC[i] = nextNPC[i] = 0;
|
||||||
|
@ -335,6 +338,7 @@ DefaultCommit<Impl>::initStage()
|
||||||
for (int i=0; i < numThreads; i++) {
|
for (int i=0; i < numThreads; i++) {
|
||||||
toIEW->commitInfo[i].usedROB = true;
|
toIEW->commitInfo[i].usedROB = true;
|
||||||
toIEW->commitInfo[i].freeROBEntries = rob->numFreeEntries(i);
|
toIEW->commitInfo[i].freeROBEntries = rob->numFreeEntries(i);
|
||||||
|
toIEW->commitInfo[i].emptyROB = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->activityThisCycle();
|
cpu->activityThisCycle();
|
||||||
|
@ -473,14 +477,14 @@ DefaultCommit<Impl>::generateTrapEvent(unsigned tid)
|
||||||
TrapEvent *trap = new TrapEvent(this, tid);
|
TrapEvent *trap = new TrapEvent(this, tid);
|
||||||
|
|
||||||
trap->schedule(curTick + trapLatency);
|
trap->schedule(curTick + trapLatency);
|
||||||
|
trapInFlight[tid] = true;
|
||||||
thread[tid]->trapPending = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
DefaultCommit<Impl>::generateTCEvent(unsigned tid)
|
DefaultCommit<Impl>::generateTCEvent(unsigned tid)
|
||||||
{
|
{
|
||||||
|
assert(!trapInFlight[tid]);
|
||||||
DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
|
DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
|
||||||
|
|
||||||
tcSquash[tid] = true;
|
tcSquash[tid] = true;
|
||||||
|
@ -495,7 +499,7 @@ DefaultCommit<Impl>::squashAll(unsigned tid)
|
||||||
// Hopefully this doesn't mess things up. Basically I want to squash
|
// Hopefully this doesn't mess things up. Basically I want to squash
|
||||||
// all instructions of this thread.
|
// all instructions of this thread.
|
||||||
InstSeqNum squashed_inst = rob->isEmpty() ?
|
InstSeqNum squashed_inst = rob->isEmpty() ?
|
||||||
0 : rob->readHeadInst(tid)->seqNum - 1;;
|
0 : rob->readHeadInst(tid)->seqNum - 1;
|
||||||
|
|
||||||
// All younger instructions will be squashed. Set the sequence
|
// All younger instructions will be squashed. Set the sequence
|
||||||
// number as the youngest instruction in the ROB (0 in this case.
|
// number as the youngest instruction in the ROB (0 in this case.
|
||||||
|
@ -532,6 +536,7 @@ DefaultCommit<Impl>::squashFromTrap(unsigned tid)
|
||||||
|
|
||||||
thread[tid]->trapPending = false;
|
thread[tid]->trapPending = false;
|
||||||
thread[tid]->inSyscall = false;
|
thread[tid]->inSyscall = false;
|
||||||
|
trapInFlight[tid] = false;
|
||||||
|
|
||||||
trapSquash[tid] = false;
|
trapSquash[tid] = false;
|
||||||
|
|
||||||
|
@ -580,6 +585,10 @@ DefaultCommit<Impl>::tick()
|
||||||
while (threads != end) {
|
while (threads != end) {
|
||||||
unsigned tid = *threads++;
|
unsigned tid = *threads++;
|
||||||
|
|
||||||
|
// Clear the bit saying if the thread has committed stores
|
||||||
|
// this cycle.
|
||||||
|
committedStores[tid] = false;
|
||||||
|
|
||||||
if (commitStatus[tid] == ROBSquashing) {
|
if (commitStatus[tid] == ROBSquashing) {
|
||||||
|
|
||||||
if (rob->isDoneSquashing(tid)) {
|
if (rob->isDoneSquashing(tid)) {
|
||||||
|
@ -635,16 +644,11 @@ DefaultCommit<Impl>::tick()
|
||||||
updateStatus();
|
updateStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
DefaultCommit<Impl>::commit()
|
DefaultCommit<Impl>::handleInterrupt()
|
||||||
{
|
{
|
||||||
|
|
||||||
//////////////////////////////////////
|
|
||||||
// Check for interrupts
|
|
||||||
//////////////////////////////////////
|
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
|
||||||
if (interrupt != NoFault) {
|
if (interrupt != NoFault) {
|
||||||
// Wait until the ROB is empty and all stores have drained in
|
// Wait until the ROB is empty and all stores have drained in
|
||||||
// order to enter the interrupt.
|
// order to enter the interrupt.
|
||||||
|
@ -653,6 +657,12 @@ DefaultCommit<Impl>::commit()
|
||||||
// an interrupt needed to be handled.
|
// an interrupt needed to be handled.
|
||||||
DPRINTF(Commit, "Interrupt detected.\n");
|
DPRINTF(Commit, "Interrupt detected.\n");
|
||||||
|
|
||||||
|
Fault new_interrupt = cpu->getInterrupts();
|
||||||
|
assert(new_interrupt == interrupt);
|
||||||
|
|
||||||
|
// Clear the interrupt now that it's going to be handled
|
||||||
|
toIEW->commitInfo[0].clearInterrupt = true;
|
||||||
|
|
||||||
assert(!thread[0]->inSyscall);
|
assert(!thread[0]->inSyscall);
|
||||||
thread[0]->inSyscall = true;
|
thread[0]->inSyscall = true;
|
||||||
|
|
||||||
|
@ -666,16 +676,14 @@ DefaultCommit<Impl>::commit()
|
||||||
// Generate trap squash event.
|
// Generate trap squash event.
|
||||||
generateTrapEvent(0);
|
generateTrapEvent(0);
|
||||||
|
|
||||||
// Clear the interrupt now that it's been handled
|
|
||||||
toIEW->commitInfo[0].clearInterrupt = true;
|
|
||||||
interrupt = NoFault;
|
interrupt = NoFault;
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
|
DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
|
||||||
}
|
}
|
||||||
} else if (cpu->check_interrupts(cpu->tcBase(0)) &&
|
} else if (commitStatus[0] != TrapPending &&
|
||||||
commitStatus[0] != TrapPending &&
|
cpu->check_interrupts(cpu->tcBase(0)) &&
|
||||||
!trapSquash[0] &&
|
!trapSquash[0] &&
|
||||||
!tcSquash[0]) {
|
!tcSquash[0]) {
|
||||||
// Process interrupts if interrupts are enabled, not in PAL
|
// Process interrupts if interrupts are enabled, not in PAL
|
||||||
// mode, and no other traps or external squashes are currently
|
// mode, and no other traps or external squashes are currently
|
||||||
// pending.
|
// pending.
|
||||||
|
@ -691,7 +699,21 @@ DefaultCommit<Impl>::commit()
|
||||||
toIEW->commitInfo[0].interruptPending = true;
|
toIEW->commitInfo[0].interruptPending = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif // FULL_SYSTEM
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
void
|
||||||
|
DefaultCommit<Impl>::commit()
|
||||||
|
{
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
// Check for any interrupt, and start processing it. Or if we
|
||||||
|
// have an outstanding interrupt and are at a point when it is
|
||||||
|
// valid to take an interrupt, process it.
|
||||||
|
if (cpu->check_interrupts(cpu->tcBase(0))) {
|
||||||
|
handleInterrupt();
|
||||||
|
}
|
||||||
#endif // FULL_SYSTEM
|
#endif // FULL_SYSTEM
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
@ -709,6 +731,7 @@ DefaultCommit<Impl>::commit()
|
||||||
assert(!tcSquash[tid]);
|
assert(!tcSquash[tid]);
|
||||||
squashFromTrap(tid);
|
squashFromTrap(tid);
|
||||||
} else if (tcSquash[tid] == true) {
|
} else if (tcSquash[tid] == true) {
|
||||||
|
assert(commitStatus[tid] != TrapPending);
|
||||||
squashFromTC(tid);
|
squashFromTC(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,6 +776,7 @@ DefaultCommit<Impl>::commit()
|
||||||
bdelay_done_seq_num--;
|
bdelay_done_seq_num--;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// All younger instructions will be squashed. Set the sequence
|
// All younger instructions will be squashed. Set the sequence
|
||||||
// number as the youngest instruction in the ROB.
|
// number as the youngest instruction in the ROB.
|
||||||
youngestSeqNum[tid] = squashed_inst;
|
youngestSeqNum[tid] = squashed_inst;
|
||||||
|
@ -817,13 +841,29 @@ DefaultCommit<Impl>::commit()
|
||||||
toIEW->commitInfo[tid].usedROB = true;
|
toIEW->commitInfo[tid].usedROB = true;
|
||||||
toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
|
toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
|
||||||
|
|
||||||
if (rob->isEmpty(tid)) {
|
|
||||||
toIEW->commitInfo[tid].emptyROB = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
wroteToTimeBuffer = true;
|
wroteToTimeBuffer = true;
|
||||||
changedROBNumEntries[tid] = false;
|
changedROBNumEntries[tid] = false;
|
||||||
|
if (rob->isEmpty(tid))
|
||||||
|
checkEmptyROB[tid] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ROB is only considered "empty" for previous stages if: a)
|
||||||
|
// ROB is empty, b) there are no outstanding stores, c) IEW
|
||||||
|
// stage has received any information regarding stores that
|
||||||
|
// committed.
|
||||||
|
// c) is checked by making sure to not consider the ROB empty
|
||||||
|
// on the same cycle as when stores have been committed.
|
||||||
|
// @todo: Make this handle multi-cycle communication between
|
||||||
|
// commit and IEW.
|
||||||
|
if (checkEmptyROB[tid] && rob->isEmpty(tid) &&
|
||||||
|
!iewStage->hasStoresToWB() && !committedStores[tid]) {
|
||||||
|
checkEmptyROB[tid] = false;
|
||||||
|
toIEW->commitInfo[tid].usedROB = true;
|
||||||
|
toIEW->commitInfo[tid].emptyROB = true;
|
||||||
|
toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
|
||||||
|
wroteToTimeBuffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,8 +1006,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
// and committed this instruction.
|
// and committed this instruction.
|
||||||
thread[tid]->funcExeInst--;
|
thread[tid]->funcExeInst--;
|
||||||
|
|
||||||
head_inst->setAtCommit();
|
|
||||||
|
|
||||||
if (head_inst->isNonSpeculative() ||
|
if (head_inst->isNonSpeculative() ||
|
||||||
head_inst->isStoreConditional() ||
|
head_inst->isStoreConditional() ||
|
||||||
head_inst->isMemBarrier() ||
|
head_inst->isMemBarrier() ||
|
||||||
|
@ -977,19 +1015,9 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
"instruction [sn:%lli] at the head of the ROB, PC %#x.\n",
|
"instruction [sn:%lli] at the head of the ROB, PC %#x.\n",
|
||||||
head_inst->seqNum, head_inst->readPC());
|
head_inst->seqNum, head_inst->readPC());
|
||||||
|
|
||||||
// Hack to make sure syscalls/memory barriers/quiesces
|
if (inst_num > 0 || iewStage->hasStoresToWB()) {
|
||||||
// aren't executed until all stores write back their data.
|
|
||||||
// This direct communication shouldn't be used for
|
|
||||||
// anything other than this.
|
|
||||||
if ((head_inst->isMemBarrier() || head_inst->isWriteBarrier() ||
|
|
||||||
head_inst->isQuiesce()) &&
|
|
||||||
iewStage->hasStoresToWB())
|
|
||||||
{
|
|
||||||
DPRINTF(Commit, "Waiting for all stores to writeback.\n");
|
DPRINTF(Commit, "Waiting for all stores to writeback.\n");
|
||||||
return false;
|
return false;
|
||||||
} else if (inst_num > 0 || iewStage->hasStoresToWB()) {
|
|
||||||
DPRINTF(Commit, "Waiting to become head of commit.\n");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
|
toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
|
||||||
|
@ -1002,6 +1030,12 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} else if (head_inst->isLoad()) {
|
} else if (head_inst->isLoad()) {
|
||||||
|
if (inst_num > 0 || iewStage->hasStoresToWB()) {
|
||||||
|
DPRINTF(Commit, "Waiting for all stores to writeback.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(head_inst->uncacheable());
|
||||||
DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n",
|
DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n",
|
||||||
head_inst->seqNum, head_inst->readPC());
|
head_inst->seqNum, head_inst->readPC());
|
||||||
|
|
||||||
|
@ -1025,8 +1059,11 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
panic("Thread sync instructions are not handled yet.\n");
|
panic("Thread sync instructions are not handled yet.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the instruction caused a fault. If so, trap.
|
||||||
|
Fault inst_fault = head_inst->getFault();
|
||||||
|
|
||||||
// Stores mark themselves as completed.
|
// Stores mark themselves as completed.
|
||||||
if (!head_inst->isStore()) {
|
if (!head_inst->isStore() && inst_fault == NoFault) {
|
||||||
head_inst->setCompleted();
|
head_inst->setCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1038,9 +1075,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check if the instruction caused a fault. If so, trap.
|
|
||||||
Fault inst_fault = head_inst->getFault();
|
|
||||||
|
|
||||||
// DTB will sometimes need the machine instruction for when
|
// DTB will sometimes need the machine instruction for when
|
||||||
// faults happen. So we will set it here, prior to the DTB
|
// faults happen. So we will set it here, prior to the DTB
|
||||||
// possibly needing it for its fault.
|
// possibly needing it for its fault.
|
||||||
|
@ -1048,7 +1082,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
static_cast<TheISA::MachInst>(head_inst->staticInst->machInst));
|
static_cast<TheISA::MachInst>(head_inst->staticInst->machInst));
|
||||||
|
|
||||||
if (inst_fault != NoFault) {
|
if (inst_fault != NoFault) {
|
||||||
head_inst->setCompleted();
|
|
||||||
DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
|
DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
|
||||||
head_inst->seqNum, head_inst->readPC());
|
head_inst->seqNum, head_inst->readPC());
|
||||||
|
|
||||||
|
@ -1057,6 +1090,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
head_inst->setCompleted();
|
||||||
|
|
||||||
#if USE_CHECKER
|
#if USE_CHECKER
|
||||||
if (cpu->checker && head_inst->isStore()) {
|
if (cpu->checker && head_inst->isStore()) {
|
||||||
cpu->checker->verify(head_inst);
|
cpu->checker->verify(head_inst);
|
||||||
|
@ -1082,6 +1117,13 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
|
|
||||||
commitStatus[tid] = TrapPending;
|
commitStatus[tid] = TrapPending;
|
||||||
|
|
||||||
|
if (head_inst->traceData) {
|
||||||
|
head_inst->traceData->setFetchSeq(head_inst->seqNum);
|
||||||
|
head_inst->traceData->setCPSeq(thread[tid]->numInst);
|
||||||
|
head_inst->traceData->finalize();
|
||||||
|
head_inst->traceData = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Generate trap squash event.
|
// Generate trap squash event.
|
||||||
generateTrapEvent(tid);
|
generateTrapEvent(tid);
|
||||||
// warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC());
|
// warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC());
|
||||||
|
@ -1123,6 +1165,10 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
|
||||||
// Finally clear the head ROB entry.
|
// Finally clear the head ROB entry.
|
||||||
rob->retireHead(tid);
|
rob->retireHead(tid);
|
||||||
|
|
||||||
|
// If this was a store, record it for this cycle.
|
||||||
|
if (head_inst->isStore())
|
||||||
|
committedStores[tid] = true;
|
||||||
|
|
||||||
// Return true to indicate that we have committed an instruction.
|
// Return true to indicate that we have committed an instruction.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1167,7 +1213,8 @@ DefaultCommit<Impl>::getInsts()
|
||||||
int tid = inst->threadNumber;
|
int tid = inst->threadNumber;
|
||||||
|
|
||||||
if (!inst->isSquashed() &&
|
if (!inst->isSquashed() &&
|
||||||
commitStatus[tid] != ROBSquashing) {
|
commitStatus[tid] != ROBSquashing &&
|
||||||
|
commitStatus[tid] != TrapPending) {
|
||||||
changedROBNumEntries[tid] = true;
|
changedROBNumEntries[tid] = true;
|
||||||
|
|
||||||
DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n",
|
DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n",
|
||||||
|
|
|
@ -466,7 +466,7 @@ FullO3CPU<Impl>::tick()
|
||||||
lastRunningCycle = curTick;
|
lastRunningCycle = curTick;
|
||||||
timesIdled++;
|
timesIdled++;
|
||||||
} else {
|
} else {
|
||||||
tickEvent.schedule(curTick + cycles(1));
|
tickEvent.schedule(nextCycle(curTick + cycles(1)));
|
||||||
DPRINTF(O3CPU, "Scheduling next tick!\n");
|
DPRINTF(O3CPU, "Scheduling next tick!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -886,7 +886,7 @@ FullO3CPU<Impl>::resume()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!tickEvent.scheduled())
|
if (!tickEvent.scheduled())
|
||||||
tickEvent.schedule(curTick);
|
tickEvent.schedule(nextCycle());
|
||||||
_status = Running;
|
_status = Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,11 +979,11 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
|
||||||
ThreadContext *tc = threadContexts[i];
|
ThreadContext *tc = threadContexts[i];
|
||||||
if (tc->status() == ThreadContext::Active && _status != Running) {
|
if (tc->status() == ThreadContext::Active && _status != Running) {
|
||||||
_status = Running;
|
_status = Running;
|
||||||
tickEvent.schedule(curTick);
|
tickEvent.schedule(nextCycle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tickEvent.scheduled())
|
if (!tickEvent.scheduled())
|
||||||
tickEvent.schedule(curTick);
|
tickEvent.schedule(nextCycle());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
|
@ -1393,7 +1393,7 @@ FullO3CPU<Impl>::wakeCPU()
|
||||||
|
|
||||||
idleCycles += (curTick - 1) - lastRunningCycle;
|
idleCycles += (curTick - 1) - lastRunningCycle;
|
||||||
|
|
||||||
tickEvent.schedule(curTick);
|
tickEvent.schedule(nextCycle());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
|
|
|
@ -146,9 +146,9 @@ class FullO3CPU : public BaseO3CPU
|
||||||
void scheduleTickEvent(int delay)
|
void scheduleTickEvent(int delay)
|
||||||
{
|
{
|
||||||
if (tickEvent.squashed())
|
if (tickEvent.squashed())
|
||||||
tickEvent.reschedule(curTick + cycles(delay));
|
tickEvent.reschedule(nextCycle(curTick + cycles(delay)));
|
||||||
else if (!tickEvent.scheduled())
|
else if (!tickEvent.scheduled())
|
||||||
tickEvent.schedule(curTick + cycles(delay));
|
tickEvent.schedule(nextCycle(curTick + cycles(delay)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unschedule tick event, regardless of its current state. */
|
/** Unschedule tick event, regardless of its current state. */
|
||||||
|
@ -186,9 +186,11 @@ class FullO3CPU : public BaseO3CPU
|
||||||
{
|
{
|
||||||
// Schedule thread to activate, regardless of its current state.
|
// Schedule thread to activate, regardless of its current state.
|
||||||
if (activateThreadEvent[tid].squashed())
|
if (activateThreadEvent[tid].squashed())
|
||||||
activateThreadEvent[tid].reschedule(curTick + cycles(delay));
|
activateThreadEvent[tid].
|
||||||
|
reschedule(nextCycle(curTick + cycles(delay)));
|
||||||
else if (!activateThreadEvent[tid].scheduled())
|
else if (!activateThreadEvent[tid].scheduled())
|
||||||
activateThreadEvent[tid].schedule(curTick + cycles(delay));
|
activateThreadEvent[tid].
|
||||||
|
schedule(nextCycle(curTick + cycles(delay)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unschedule actiavte thread event, regardless of its current state. */
|
/** Unschedule actiavte thread event, regardless of its current state. */
|
||||||
|
@ -235,9 +237,11 @@ class FullO3CPU : public BaseO3CPU
|
||||||
{
|
{
|
||||||
// Schedule thread to activate, regardless of its current state.
|
// Schedule thread to activate, regardless of its current state.
|
||||||
if (deallocateContextEvent[tid].squashed())
|
if (deallocateContextEvent[tid].squashed())
|
||||||
deallocateContextEvent[tid].reschedule(curTick + cycles(delay));
|
deallocateContextEvent[tid].
|
||||||
|
reschedule(nextCycle(curTick + cycles(delay)));
|
||||||
else if (!deallocateContextEvent[tid].scheduled())
|
else if (!deallocateContextEvent[tid].scheduled())
|
||||||
deallocateContextEvent[tid].schedule(curTick + cycles(delay));
|
deallocateContextEvent[tid].
|
||||||
|
schedule(nextCycle(curTick + cycles(delay)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unschedule thread deallocation in CPU */
|
/** Unschedule thread deallocation in CPU */
|
||||||
|
|
|
@ -620,6 +620,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
|
||||||
fault = TheISA::genMachineCheckFault();
|
fault = TheISA::genMachineCheckFault();
|
||||||
delete mem_req;
|
delete mem_req;
|
||||||
memReq[tid] = NULL;
|
memReq[tid] = NULL;
|
||||||
|
warn("Bad address!\n");
|
||||||
}
|
}
|
||||||
assert(retryPkt == NULL);
|
assert(retryPkt == NULL);
|
||||||
assert(retryTid == -1);
|
assert(retryTid == -1);
|
||||||
|
@ -670,11 +671,12 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC,
|
||||||
// Get rid of the retrying packet if it was from this thread.
|
// Get rid of the retrying packet if it was from this thread.
|
||||||
if (retryTid == tid) {
|
if (retryTid == tid) {
|
||||||
assert(cacheBlocked);
|
assert(cacheBlocked);
|
||||||
cacheBlocked = false;
|
if (retryPkt) {
|
||||||
retryTid = -1;
|
delete retryPkt->req;
|
||||||
delete retryPkt->req;
|
delete retryPkt;
|
||||||
delete retryPkt;
|
}
|
||||||
retryPkt = NULL;
|
retryPkt = NULL;
|
||||||
|
retryTid = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchStatus[tid] = Squashing;
|
fetchStatus[tid] = Squashing;
|
||||||
|
@ -1150,7 +1152,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
|
|
||||||
///FIXME This needs to be more robust in dealing with delay slots
|
///FIXME This needs to be more robust in dealing with delay slots
|
||||||
#if !ISA_HAS_DELAY_SLOT
|
#if !ISA_HAS_DELAY_SLOT
|
||||||
predicted_branch |=
|
// predicted_branch |=
|
||||||
#endif
|
#endif
|
||||||
lookupAndUpdateNextPC(instruction, next_PC, next_NPC);
|
lookupAndUpdateNextPC(instruction, next_PC, next_NPC);
|
||||||
predicted_branch |= (next_PC != fetch_NPC);
|
predicted_branch |= (next_PC != fetch_NPC);
|
||||||
|
@ -1221,7 +1223,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
// until commit handles the fault. The only other way it can
|
// until commit handles the fault. The only other way it can
|
||||||
// wake up is if a squash comes along and changes the PC.
|
// wake up is if a squash comes along and changes the PC.
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
assert(numInst != fetchWidth);
|
assert(numInst < fetchWidth);
|
||||||
// Get a sequence number.
|
// Get a sequence number.
|
||||||
inst_seq = cpu->getAndIncrementInstSeq();
|
inst_seq = cpu->getAndIncrementInstSeq();
|
||||||
// We will use a nop in order to carry the fault.
|
// We will use a nop in order to carry the fault.
|
||||||
|
|
|
@ -1152,19 +1152,6 @@ DefaultIEW<Impl>::dispatchInsts(unsigned tid)
|
||||||
// Same as non-speculative stores.
|
// Same as non-speculative stores.
|
||||||
inst->setCanCommit();
|
inst->setCanCommit();
|
||||||
instQueue.insertBarrier(inst);
|
instQueue.insertBarrier(inst);
|
||||||
add_to_iq = false;
|
|
||||||
} else if (inst->isNonSpeculative()) {
|
|
||||||
DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
|
|
||||||
"encountered, skipping.\n", tid);
|
|
||||||
|
|
||||||
// Same as non-speculative stores.
|
|
||||||
inst->setCanCommit();
|
|
||||||
|
|
||||||
// Specifically insert it as nonspeculative.
|
|
||||||
instQueue.insertNonSpec(inst);
|
|
||||||
|
|
||||||
++iewDispNonSpecInsts;
|
|
||||||
|
|
||||||
add_to_iq = false;
|
add_to_iq = false;
|
||||||
} else if (inst->isNop()) {
|
} else if (inst->isNop()) {
|
||||||
DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "
|
DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "
|
||||||
|
@ -1193,6 +1180,20 @@ DefaultIEW<Impl>::dispatchInsts(unsigned tid)
|
||||||
} else {
|
} else {
|
||||||
add_to_iq = true;
|
add_to_iq = true;
|
||||||
}
|
}
|
||||||
|
if (inst->isNonSpeculative()) {
|
||||||
|
DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
|
||||||
|
"encountered, skipping.\n", tid);
|
||||||
|
|
||||||
|
// Same as non-speculative stores.
|
||||||
|
inst->setCanCommit();
|
||||||
|
|
||||||
|
// Specifically insert it as nonspeculative.
|
||||||
|
instQueue.insertNonSpec(inst);
|
||||||
|
|
||||||
|
++iewDispNonSpecInsts;
|
||||||
|
|
||||||
|
add_to_iq = false;
|
||||||
|
}
|
||||||
|
|
||||||
// If the instruction queue is not full, then add the
|
// If the instruction queue is not full, then add the
|
||||||
// instruction.
|
// instruction.
|
||||||
|
@ -1379,6 +1380,7 @@ DefaultIEW<Impl>::executeInsts()
|
||||||
predictedNotTakenIncorrect++;
|
predictedNotTakenIncorrect++;
|
||||||
}
|
}
|
||||||
} else if (ldstQueue.violation(tid)) {
|
} else if (ldstQueue.violation(tid)) {
|
||||||
|
assert(inst->isMemRef());
|
||||||
// If there was an ordering violation, then get the
|
// If there was an ordering violation, then get the
|
||||||
// DynInst that caused the violation. Note that this
|
// DynInst that caused the violation. Note that this
|
||||||
// clears the violation signal.
|
// clears the violation signal.
|
||||||
|
@ -1391,10 +1393,10 @@ DefaultIEW<Impl>::executeInsts()
|
||||||
|
|
||||||
// Ensure the violating instruction is older than
|
// Ensure the violating instruction is older than
|
||||||
// current squash
|
// current squash
|
||||||
if (fetchRedirect[tid] &&
|
/* if (fetchRedirect[tid] &&
|
||||||
violator->seqNum >= toCommit->squashedSeqNum[tid])
|
violator->seqNum >= toCommit->squashedSeqNum[tid] + 1)
|
||||||
continue;
|
continue;
|
||||||
|
*/
|
||||||
fetchRedirect[tid] = true;
|
fetchRedirect[tid] = true;
|
||||||
|
|
||||||
// Tell the instruction queue that a violation has occured.
|
// Tell the instruction queue that a violation has occured.
|
||||||
|
@ -1414,6 +1416,33 @@ DefaultIEW<Impl>::executeInsts()
|
||||||
|
|
||||||
squashDueToMemBlocked(inst, tid);
|
squashDueToMemBlocked(inst, tid);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Reset any state associated with redirects that will not
|
||||||
|
// be used.
|
||||||
|
if (ldstQueue.violation(tid)) {
|
||||||
|
assert(inst->isMemRef());
|
||||||
|
|
||||||
|
DynInstPtr violator = ldstQueue.getMemDepViolator(tid);
|
||||||
|
|
||||||
|
DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: "
|
||||||
|
"%#x, inst PC: %#x. Addr is: %#x.\n",
|
||||||
|
violator->readPC(), inst->readPC(), inst->physEffAddr);
|
||||||
|
DPRINTF(IEW, "Violation will not be handled because "
|
||||||
|
"already squashing\n");
|
||||||
|
|
||||||
|
++memOrderViolationEvents;
|
||||||
|
}
|
||||||
|
if (ldstQueue.loadBlocked(tid) &&
|
||||||
|
!ldstQueue.isLoadBlockedHandled(tid)) {
|
||||||
|
DPRINTF(IEW, "Load operation couldn't execute because the "
|
||||||
|
"memory system is blocked. PC: %#x [sn:%lli]\n",
|
||||||
|
inst->readPC(), inst->seqNum);
|
||||||
|
DPRINTF(IEW, "Blocked load will not be handled because "
|
||||||
|
"already squashing\n");
|
||||||
|
|
||||||
|
ldstQueue.setLoadBlockedHandled(tid);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1563,6 +1592,7 @@ DefaultIEW<Impl>::tick()
|
||||||
//DPRINTF(IEW,"NonspecInst from thread %i",tid);
|
//DPRINTF(IEW,"NonspecInst from thread %i",tid);
|
||||||
if (fromCommit->commitInfo[tid].uncached) {
|
if (fromCommit->commitInfo[tid].uncached) {
|
||||||
instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);
|
instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);
|
||||||
|
fromCommit->commitInfo[tid].uncachedLoad->setAtCommit();
|
||||||
} else {
|
} else {
|
||||||
instQueue.scheduleNonSpec(
|
instQueue.scheduleNonSpec(
|
||||||
fromCommit->commitInfo[tid].nonSpecSeqNum);
|
fromCommit->commitInfo[tid].nonSpecSeqNum);
|
||||||
|
|
|
@ -829,6 +829,8 @@ InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
|
||||||
|
|
||||||
unsigned tid = (*inst_it).second->threadNumber;
|
unsigned tid = (*inst_it).second->threadNumber;
|
||||||
|
|
||||||
|
(*inst_it).second->setAtCommit();
|
||||||
|
|
||||||
(*inst_it).second->setCanIssue();
|
(*inst_it).second->setCanIssue();
|
||||||
|
|
||||||
if (!(*inst_it).second->isMemRef()) {
|
if (!(*inst_it).second->isMemRef()) {
|
||||||
|
@ -960,6 +962,8 @@ template <class Impl>
|
||||||
void
|
void
|
||||||
InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
|
InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
|
||||||
{
|
{
|
||||||
|
DPRINTF(IQ, "Rescheduling mem inst [sn:%lli]\n", resched_inst->seqNum);
|
||||||
|
resched_inst->clearCanIssue();
|
||||||
memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
|
memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,7 +988,6 @@ InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
|
||||||
completed_inst->memOpDone = true;
|
completed_inst->memOpDone = true;
|
||||||
|
|
||||||
memDepUnit[tid].completed(completed_inst);
|
memDepUnit[tid].completed(completed_inst);
|
||||||
|
|
||||||
count[tid]--;
|
count[tid]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1084,16 +1087,21 @@ InstructionQueue<Impl>::doSquash(unsigned tid)
|
||||||
|
|
||||||
++iqSquashedOperandsExamined;
|
++iqSquashedOperandsExamined;
|
||||||
}
|
}
|
||||||
} else if (!squashed_inst->isStoreConditional() || !squashed_inst->isCompleted()) {
|
} else if (!squashed_inst->isStoreConditional() ||
|
||||||
|
!squashed_inst->isCompleted()) {
|
||||||
NonSpecMapIt ns_inst_it =
|
NonSpecMapIt ns_inst_it =
|
||||||
nonSpecInsts.find(squashed_inst->seqNum);
|
nonSpecInsts.find(squashed_inst->seqNum);
|
||||||
assert(ns_inst_it != nonSpecInsts.end());
|
assert(ns_inst_it != nonSpecInsts.end());
|
||||||
|
if (ns_inst_it == nonSpecInsts.end()) {
|
||||||
|
assert(squashed_inst->getFault() != NoFault);
|
||||||
|
} else {
|
||||||
|
|
||||||
(*ns_inst_it).second = NULL;
|
(*ns_inst_it).second = NULL;
|
||||||
|
|
||||||
nonSpecInsts.erase(ns_inst_it);
|
nonSpecInsts.erase(ns_inst_it);
|
||||||
|
|
||||||
++iqSquashedNonSpecRemoved;
|
++iqSquashedNonSpecRemoved;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Might want to also clear out the head of the dependency graph.
|
// Might want to also clear out the head of the dependency graph.
|
||||||
|
|
|
@ -497,6 +497,11 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
(load_idx != loadHead || !load_inst->isAtCommit())) {
|
(load_idx != loadHead || !load_inst->isAtCommit())) {
|
||||||
iewStage->rescheduleMemInst(load_inst);
|
iewStage->rescheduleMemInst(load_inst);
|
||||||
++lsqRescheduledLoads;
|
++lsqRescheduledLoads;
|
||||||
|
|
||||||
|
// Must delete request now that it wasn't handed off to
|
||||||
|
// memory. This is quite ugly. @todo: Figure out the proper
|
||||||
|
// place to really handle request deletes.
|
||||||
|
delete req;
|
||||||
return TheISA::genMachineCheckFault();
|
return TheISA::genMachineCheckFault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,6 +539,10 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
|
|
||||||
if (store_size == 0)
|
if (store_size == 0)
|
||||||
continue;
|
continue;
|
||||||
|
else if (storeQueue[store_idx].inst->uncacheable())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
assert(storeQueue[store_idx].inst->effAddrValid);
|
||||||
|
|
||||||
// Check if the store data is within the lower and upper bounds of
|
// Check if the store data is within the lower and upper bounds of
|
||||||
// addresses that the request needs.
|
// addresses that the request needs.
|
||||||
|
@ -550,7 +559,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
storeQueue[store_idx].inst->effAddr;
|
storeQueue[store_idx].inst->effAddr;
|
||||||
|
|
||||||
// If the store's data has all of the data needed, we can forward.
|
// If the store's data has all of the data needed, we can forward.
|
||||||
if (store_has_lower_limit && store_has_upper_limit) {
|
if ((store_has_lower_limit && store_has_upper_limit)) {
|
||||||
// Get shift amount for offset into the store's data.
|
// Get shift amount for offset into the store's data.
|
||||||
int shift_amt = req->getVaddr() & (store_size - 1);
|
int shift_amt = req->getVaddr() & (store_size - 1);
|
||||||
// @todo: Magic number, assumes byte addressing
|
// @todo: Magic number, assumes byte addressing
|
||||||
|
@ -596,6 +605,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
// If it's already been written back, then don't worry about
|
// If it's already been written back, then don't worry about
|
||||||
// stalling on it.
|
// stalling on it.
|
||||||
if (storeQueue[store_idx].completed) {
|
if (storeQueue[store_idx].completed) {
|
||||||
|
panic("Should not check one of these");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,6 +624,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
// rescheduled eventually
|
// rescheduled eventually
|
||||||
iewStage->rescheduleMemInst(load_inst);
|
iewStage->rescheduleMemInst(load_inst);
|
||||||
iewStage->decrWb(load_inst->seqNum);
|
iewStage->decrWb(load_inst->seqNum);
|
||||||
|
load_inst->clearIssued();
|
||||||
++lsqRescheduledLoads;
|
++lsqRescheduledLoads;
|
||||||
|
|
||||||
// Do not generate a writeback event as this instruction is not
|
// Do not generate a writeback event as this instruction is not
|
||||||
|
@ -622,7 +633,11 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
"Store idx %i to load addr %#x\n",
|
"Store idx %i to load addr %#x\n",
|
||||||
store_idx, req->getVaddr());
|
store_idx, req->getVaddr());
|
||||||
|
|
||||||
++lsqBlockedLoads;
|
// Must delete request now that it wasn't handed off to
|
||||||
|
// memory. This is quite ugly. @todo: Figure out the
|
||||||
|
// proper place to really handle request deletes.
|
||||||
|
delete req;
|
||||||
|
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -654,8 +669,11 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
// Delete state and data packet because a load retry
|
// Delete state and data packet because a load retry
|
||||||
// initiates a pipeline restart; it does not retry.
|
// initiates a pipeline restart; it does not retry.
|
||||||
delete state;
|
delete state;
|
||||||
|
delete data_pkt->req;
|
||||||
delete data_pkt;
|
delete data_pkt;
|
||||||
|
|
||||||
|
req = NULL;
|
||||||
|
|
||||||
if (result == Packet::BadAddress) {
|
if (result == Packet::BadAddress) {
|
||||||
return TheISA::genMachineCheckFault();
|
return TheISA::genMachineCheckFault();
|
||||||
}
|
}
|
||||||
|
@ -669,6 +687,9 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
// If the cache was blocked, or has become blocked due to the access,
|
// If the cache was blocked, or has become blocked due to the access,
|
||||||
// handle it.
|
// handle it.
|
||||||
if (lsq->cacheBlocked()) {
|
if (lsq->cacheBlocked()) {
|
||||||
|
if (req)
|
||||||
|
delete req;
|
||||||
|
|
||||||
++lsqCacheBlocked;
|
++lsqCacheBlocked;
|
||||||
|
|
||||||
iewStage->decrWb(load_inst->seqNum);
|
iewStage->decrWb(load_inst->seqNum);
|
||||||
|
|
|
@ -81,6 +81,7 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
|
||||||
if (isSwitchedOut() || inst->isSquashed()) {
|
if (isSwitchedOut() || inst->isSquashed()) {
|
||||||
iewStage->decrWb(inst->seqNum);
|
iewStage->decrWb(inst->seqNum);
|
||||||
delete state;
|
delete state;
|
||||||
|
delete pkt->req;
|
||||||
delete pkt;
|
delete pkt;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -94,6 +95,7 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete state;
|
delete state;
|
||||||
|
delete pkt->req;
|
||||||
delete pkt;
|
delete pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,12 +405,15 @@ template <class Impl>
|
||||||
Fault
|
Fault
|
||||||
LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
|
LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
|
||||||
{
|
{
|
||||||
|
using namespace TheISA;
|
||||||
// Execute a specific load.
|
// Execute a specific load.
|
||||||
Fault load_fault = NoFault;
|
Fault load_fault = NoFault;
|
||||||
|
|
||||||
DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
|
DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
|
||||||
inst->readPC(),inst->seqNum);
|
inst->readPC(),inst->seqNum);
|
||||||
|
|
||||||
|
assert(!inst->isSquashed());
|
||||||
|
|
||||||
load_fault = inst->initiateAcc();
|
load_fault = inst->initiateAcc();
|
||||||
|
|
||||||
// If the instruction faulted, then we need to send it along to commit
|
// If the instruction faulted, then we need to send it along to commit
|
||||||
|
@ -418,12 +423,44 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
|
||||||
// realizes there is activity.
|
// realizes there is activity.
|
||||||
// Mark it as executed unless it is an uncached load that
|
// Mark it as executed unless it is an uncached load that
|
||||||
// needs to hit the head of commit.
|
// needs to hit the head of commit.
|
||||||
if (!(inst->req && inst->req->isUncacheable()) ||
|
if (!(inst->hasRequest() && inst->uncacheable()) ||
|
||||||
inst->isAtCommit()) {
|
inst->isAtCommit()) {
|
||||||
inst->setExecuted();
|
inst->setExecuted();
|
||||||
}
|
}
|
||||||
iewStage->instToCommit(inst);
|
iewStage->instToCommit(inst);
|
||||||
iewStage->activityThisCycle();
|
iewStage->activityThisCycle();
|
||||||
|
} else if (!loadBlocked()) {
|
||||||
|
assert(inst->effAddrValid);
|
||||||
|
int load_idx = inst->lqIdx;
|
||||||
|
incrLdIdx(load_idx);
|
||||||
|
while (load_idx != loadTail) {
|
||||||
|
// Really only need to check loads that have actually executed
|
||||||
|
|
||||||
|
// @todo: For now this is extra conservative, detecting a
|
||||||
|
// violation if the addresses match assuming all accesses
|
||||||
|
// are quad word accesses.
|
||||||
|
|
||||||
|
// @todo: Fix this, magic number being used here
|
||||||
|
if (loadQueue[load_idx]->effAddrValid &&
|
||||||
|
(loadQueue[load_idx]->effAddr >> 8) ==
|
||||||
|
(inst->effAddr >> 8)) {
|
||||||
|
// A load incorrectly passed this load. Squash and refetch.
|
||||||
|
// For now return a fault to show that it was unsuccessful.
|
||||||
|
DynInstPtr violator = loadQueue[load_idx];
|
||||||
|
if (!memDepViolator ||
|
||||||
|
(violator->seqNum < memDepViolator->seqNum)) {
|
||||||
|
memDepViolator = violator;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++lsqMemOrderViolation;
|
||||||
|
|
||||||
|
return genMachineCheckFault();
|
||||||
|
}
|
||||||
|
|
||||||
|
incrLdIdx(load_idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return load_fault;
|
return load_fault;
|
||||||
|
@ -442,6 +479,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
|
||||||
DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
|
DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
|
||||||
store_inst->readPC(), store_inst->seqNum);
|
store_inst->readPC(), store_inst->seqNum);
|
||||||
|
|
||||||
|
assert(!store_inst->isSquashed());
|
||||||
|
|
||||||
// Check the recently completed loads to see if any match this store's
|
// Check the recently completed loads to see if any match this store's
|
||||||
// address. If so, then we have a memory ordering violation.
|
// address. If so, then we have a memory ordering violation.
|
||||||
int load_idx = store_inst->lqIdx;
|
int load_idx = store_inst->lqIdx;
|
||||||
|
@ -465,32 +504,36 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
|
||||||
++storesToWB;
|
++storesToWB;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!memDepViolator) {
|
assert(store_inst->effAddrValid);
|
||||||
while (load_idx != loadTail) {
|
while (load_idx != loadTail) {
|
||||||
// Really only need to check loads that have actually executed
|
// Really only need to check loads that have actually executed
|
||||||
// It's safe to check all loads because effAddr is set to
|
// It's safe to check all loads because effAddr is set to
|
||||||
// InvalAddr when the dyn inst is created.
|
// InvalAddr when the dyn inst is created.
|
||||||
|
|
||||||
// @todo: For now this is extra conservative, detecting a
|
// @todo: For now this is extra conservative, detecting a
|
||||||
// violation if the addresses match assuming all accesses
|
// violation if the addresses match assuming all accesses
|
||||||
// are quad word accesses.
|
// are quad word accesses.
|
||||||
|
|
||||||
// @todo: Fix this, magic number being used here
|
// @todo: Fix this, magic number being used here
|
||||||
if ((loadQueue[load_idx]->effAddr >> 8) ==
|
if (loadQueue[load_idx]->effAddrValid &&
|
||||||
(store_inst->effAddr >> 8)) {
|
(loadQueue[load_idx]->effAddr >> 8) ==
|
||||||
// A load incorrectly passed this store. Squash and refetch.
|
(store_inst->effAddr >> 8)) {
|
||||||
// For now return a fault to show that it was unsuccessful.
|
// A load incorrectly passed this store. Squash and refetch.
|
||||||
memDepViolator = loadQueue[load_idx];
|
// For now return a fault to show that it was unsuccessful.
|
||||||
++lsqMemOrderViolation;
|
DynInstPtr violator = loadQueue[load_idx];
|
||||||
|
if (!memDepViolator ||
|
||||||
return genMachineCheckFault();
|
(violator->seqNum < memDepViolator->seqNum)) {
|
||||||
|
memDepViolator = violator;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
incrLdIdx(load_idx);
|
++lsqMemOrderViolation;
|
||||||
|
|
||||||
|
return genMachineCheckFault();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've reached this point, there was no violation.
|
incrLdIdx(load_idx);
|
||||||
memDepViolator = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return store_fault;
|
return store_fault;
|
||||||
|
@ -660,7 +703,7 @@ LSQUnit<Impl>::writebackStores()
|
||||||
panic("LSQ sent out a bad address for a completed store!");
|
panic("LSQ sent out a bad address for a completed store!");
|
||||||
}
|
}
|
||||||
// Need to handle becoming blocked on a store.
|
// Need to handle becoming blocked on a store.
|
||||||
DPRINTF(IEW, "D-Cache became blcoked when writing [sn:%lli], will"
|
DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will"
|
||||||
"retry later\n",
|
"retry later\n",
|
||||||
inst->seqNum);
|
inst->seqNum);
|
||||||
isStoreBlocked = true;
|
isStoreBlocked = true;
|
||||||
|
@ -735,6 +778,10 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (memDepViolator && squashed_num < memDepViolator->seqNum) {
|
||||||
|
memDepViolator = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int store_idx = storeTail;
|
int store_idx = storeTail;
|
||||||
decrStIdx(store_idx);
|
decrStIdx(store_idx);
|
||||||
|
|
||||||
|
@ -764,6 +811,11 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
|
||||||
storeQueue[store_idx].inst = NULL;
|
storeQueue[store_idx].inst = NULL;
|
||||||
storeQueue[store_idx].canWB = 0;
|
storeQueue[store_idx].canWB = 0;
|
||||||
|
|
||||||
|
// Must delete request now that it wasn't handed off to
|
||||||
|
// memory. This is quite ugly. @todo: Figure out the proper
|
||||||
|
// place to really handle request deletes.
|
||||||
|
delete storeQueue[store_idx].req;
|
||||||
|
|
||||||
storeQueue[store_idx].req = NULL;
|
storeQueue[store_idx].req = NULL;
|
||||||
--stores;
|
--stores;
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,9 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
|
||||||
inst_entry->regsReady = true;
|
inst_entry->regsReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the bit saying this instruction can issue.
|
||||||
|
inst->clearCanIssue();
|
||||||
|
|
||||||
// Add this instruction to the list of dependents.
|
// Add this instruction to the list of dependents.
|
||||||
store_entry->dependInsts.push_back(inst_entry);
|
store_entry->dependInsts.push_back(inst_entry);
|
||||||
|
|
||||||
|
@ -357,7 +360,6 @@ void
|
||||||
MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst)
|
MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst)
|
||||||
{
|
{
|
||||||
DynInstPtr temp_inst;
|
DynInstPtr temp_inst;
|
||||||
bool found_inst = false;
|
|
||||||
|
|
||||||
// For now this replay function replays all waiting memory ops.
|
// For now this replay function replays all waiting memory ops.
|
||||||
while (!instsToReplay.empty()) {
|
while (!instsToReplay.empty()) {
|
||||||
|
@ -371,14 +373,8 @@ MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst)
|
||||||
|
|
||||||
moveToReady(inst_entry);
|
moveToReady(inst_entry);
|
||||||
|
|
||||||
if (temp_inst == inst) {
|
|
||||||
found_inst = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
instsToReplay.pop_front();
|
instsToReplay.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(found_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MemDepPred, class Impl>
|
template <class MemDepPred, class Impl>
|
||||||
|
|
|
@ -192,8 +192,6 @@ SimpleRenameMap::rename(RegIndex arch_reg)
|
||||||
// known that the prev reg was outside the range of normal registers
|
// known that the prev reg was outside the range of normal registers
|
||||||
// so the free list can avoid adding it.
|
// so the free list can avoid adding it.
|
||||||
prev_reg = renamed_reg;
|
prev_reg = renamed_reg;
|
||||||
|
|
||||||
assert(renamed_reg < numPhysicalRegs + numMiscRegs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(Rename, "Renamed reg %d to physical reg %d old mapping was %d\n",
|
DPRINTF(Rename, "Renamed reg %d to physical reg %d old mapping was %d\n",
|
||||||
|
|
|
@ -171,8 +171,12 @@ Bus::recvTiming(PacketPtr pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
short dest = pkt->getDest();
|
short dest = pkt->getDest();
|
||||||
|
|
||||||
|
// Make sure to clear the snoop commit flag so it doesn't think an
|
||||||
|
// access has been handled twice.
|
||||||
if (dest == Packet::Broadcast) {
|
if (dest == Packet::Broadcast) {
|
||||||
port = findPort(pkt->getAddr(), pkt->getSrc());
|
port = findPort(pkt->getAddr(), pkt->getSrc());
|
||||||
|
pkt->flags &= ~SNOOP_COMMIT;
|
||||||
if (timingSnoop(pkt, port ? port : interfaces[pkt->getSrc()])) {
|
if (timingSnoop(pkt, port ? port : interfaces[pkt->getSrc()])) {
|
||||||
bool success;
|
bool success;
|
||||||
|
|
||||||
|
|
7
src/mem/cache/cache_impl.hh
vendored
7
src/mem/cache/cache_impl.hh
vendored
|
@ -545,8 +545,13 @@ Cache<TagStore,Coherence>::access(PacketPtr &pkt)
|
||||||
//We are determining prefetches on access stream, call prefetcher
|
//We are determining prefetches on access stream, call prefetcher
|
||||||
prefetcher->handleMiss(pkt, curTick);
|
prefetcher->handleMiss(pkt, curTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1));
|
||||||
|
|
||||||
if (!pkt->req->isUncacheable()) {
|
if (!pkt->req->isUncacheable()) {
|
||||||
blk = handleAccess(pkt, lat, writebacks);
|
if (!missQueue->findMSHR(blk_addr)) {
|
||||||
|
blk = handleAccess(pkt, lat, writebacks);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
size = pkt->getSize();
|
size = pkt->getSize();
|
||||||
}
|
}
|
||||||
|
|
1
src/mem/cache/miss/miss_queue.cc
vendored
1
src/mem/cache/miss/miss_queue.cc
vendored
|
@ -599,6 +599,7 @@ MissQueue::handleResponse(PacketPtr &pkt, Tick time)
|
||||||
MemCmd cmd = mshr->getTarget()->cmd;
|
MemCmd cmd = mshr->getTarget()->cmd;
|
||||||
mshr->pkt->setDest(Packet::Broadcast);
|
mshr->pkt->setDest(Packet::Broadcast);
|
||||||
mshr->pkt->result = Packet::Unknown;
|
mshr->pkt->result = Packet::Unknown;
|
||||||
|
mshr->pkt->req = mshr->getTarget()->req;
|
||||||
mq.markPending(mshr, cmd);
|
mq.markPending(mshr, cmd);
|
||||||
mshr->order = order++;
|
mshr->order = order++;
|
||||||
cache->setMasterRequest(Request_MSHR, time);
|
cache->setMasterRequest(Request_MSHR, time);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2006 The Regents of The University of Michigan
|
# Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -37,7 +37,7 @@ class MyCache(BaseCache):
|
||||||
mshrs = 10
|
mshrs = 10
|
||||||
tgts_per_mshr = 5
|
tgts_per_mshr = 5
|
||||||
|
|
||||||
cpu = DerivO3CPU()
|
cpu = DerivO3CPU(cpu_id=0)
|
||||||
cpu.addTwoLevelCacheHierarchy(MyCache(size = '128kB'), MyCache(size = '256kB'),
|
cpu.addTwoLevelCacheHierarchy(MyCache(size = '128kB'), MyCache(size = '256kB'),
|
||||||
MyCache(size = '2MB'))
|
MyCache(size = '2MB'))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue