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:
Kevin Lim 2007-03-23 13:20:19 -04:00
commit 047f77102b
21 changed files with 353 additions and 148 deletions

View file

@ -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();

View file

@ -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);
} }
} }

View file

@ -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;

View file

@ -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();
} }
} }

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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",

View file

@ -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>

View file

@ -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 */

View file

@ -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.

View file

@ -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);

View file

@ -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.

View file

@ -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);

View file

@ -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;

View file

@ -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>

View file

@ -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",

View file

@ -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;

View file

@ -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();
} }

View file

@ -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);

View file

@ -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'))