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
21 changed files with 353 additions and 148 deletions

View File

@@ -118,6 +118,9 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
for (int i=0; i < numThreads; i++) {
commitStatus[i] = Idle;
changedROBNumEntries[i] = false;
checkEmptyROB[i] = false;
trapInFlight[i] = false;
committedStores[i] = false;
trapSquash[i] = false;
tcSquash[i] = false;
PC[i] = nextPC[i] = nextNPC[i] = 0;
@@ -335,6 +338,7 @@ DefaultCommit<Impl>::initStage()
for (int i=0; i < numThreads; i++) {
toIEW->commitInfo[i].usedROB = true;
toIEW->commitInfo[i].freeROBEntries = rob->numFreeEntries(i);
toIEW->commitInfo[i].emptyROB = true;
}
cpu->activityThisCycle();
@@ -473,14 +477,14 @@ DefaultCommit<Impl>::generateTrapEvent(unsigned tid)
TrapEvent *trap = new TrapEvent(this, tid);
trap->schedule(curTick + trapLatency);
thread[tid]->trapPending = true;
trapInFlight[tid] = true;
}
template <class Impl>
void
DefaultCommit<Impl>::generateTCEvent(unsigned tid)
{
assert(!trapInFlight[tid]);
DPRINTF(Commit, "Generating TC squash event for [tid:%i]\n", tid);
tcSquash[tid] = true;
@@ -495,7 +499,7 @@ DefaultCommit<Impl>::squashAll(unsigned tid)
// Hopefully this doesn't mess things up. Basically I want to squash
// all instructions of this thread.
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
// 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]->inSyscall = false;
trapInFlight[tid] = false;
trapSquash[tid] = false;
@@ -580,6 +585,10 @@ DefaultCommit<Impl>::tick()
while (threads != end) {
unsigned tid = *threads++;
// Clear the bit saying if the thread has committed stores
// this cycle.
committedStores[tid] = false;
if (commitStatus[tid] == ROBSquashing) {
if (rob->isDoneSquashing(tid)) {
@@ -635,16 +644,11 @@ DefaultCommit<Impl>::tick()
updateStatus();
}
#if FULL_SYSTEM
template <class Impl>
void
DefaultCommit<Impl>::commit()
DefaultCommit<Impl>::handleInterrupt()
{
//////////////////////////////////////
// Check for interrupts
//////////////////////////////////////
#if FULL_SYSTEM
if (interrupt != NoFault) {
// Wait until the ROB is empty and all stores have drained in
// order to enter the interrupt.
@@ -653,6 +657,12 @@ DefaultCommit<Impl>::commit()
// an interrupt needed to be handled.
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);
thread[0]->inSyscall = true;
@@ -666,16 +676,14 @@ DefaultCommit<Impl>::commit()
// Generate trap squash event.
generateTrapEvent(0);
// Clear the interrupt now that it's been handled
toIEW->commitInfo[0].clearInterrupt = true;
interrupt = NoFault;
} else {
DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
}
} else if (cpu->check_interrupts(cpu->tcBase(0)) &&
commitStatus[0] != TrapPending &&
!trapSquash[0] &&
!tcSquash[0]) {
} else if (commitStatus[0] != TrapPending &&
cpu->check_interrupts(cpu->tcBase(0)) &&
!trapSquash[0] &&
!tcSquash[0]) {
// Process interrupts if interrupts are enabled, not in PAL
// mode, and no other traps or external squashes are currently
// pending.
@@ -691,7 +699,21 @@ DefaultCommit<Impl>::commit()
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
////////////////////////////////////
@@ -709,6 +731,7 @@ DefaultCommit<Impl>::commit()
assert(!tcSquash[tid]);
squashFromTrap(tid);
} else if (tcSquash[tid] == true) {
assert(commitStatus[tid] != TrapPending);
squashFromTC(tid);
}
@@ -753,6 +776,7 @@ DefaultCommit<Impl>::commit()
bdelay_done_seq_num--;
#endif
}
// All younger instructions will be squashed. Set the sequence
// number as the youngest instruction in the ROB.
youngestSeqNum[tid] = squashed_inst;
@@ -817,13 +841,29 @@ DefaultCommit<Impl>::commit()
toIEW->commitInfo[tid].usedROB = true;
toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
if (rob->isEmpty(tid)) {
toIEW->commitInfo[tid].emptyROB = true;
}
wroteToTimeBuffer = true;
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.
thread[tid]->funcExeInst--;
head_inst->setAtCommit();
if (head_inst->isNonSpeculative() ||
head_inst->isStoreConditional() ||
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",
head_inst->seqNum, head_inst->readPC());
// Hack to make sure syscalls/memory barriers/quiesces
// 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())
{
if (inst_num > 0 || iewStage->hasStoresToWB()) {
DPRINTF(Commit, "Waiting for all stores to writeback.\n");
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;
@@ -1002,6 +1030,12 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
return false;
} 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",
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");
}
// Check if the instruction caused a fault. If so, trap.
Fault inst_fault = head_inst->getFault();
// Stores mark themselves as completed.
if (!head_inst->isStore()) {
if (!head_inst->isStore() && inst_fault == NoFault) {
head_inst->setCompleted();
}
@@ -1038,9 +1075,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
}
#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
// faults happen. So we will set it here, prior to the DTB
// 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));
if (inst_fault != NoFault) {
head_inst->setCompleted();
DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
head_inst->seqNum, head_inst->readPC());
@@ -1057,6 +1090,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
return false;
}
head_inst->setCompleted();
#if USE_CHECKER
if (cpu->checker && head_inst->isStore()) {
cpu->checker->verify(head_inst);
@@ -1082,6 +1117,13 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
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.
generateTrapEvent(tid);
// 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.
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;
}
@@ -1167,7 +1213,8 @@ DefaultCommit<Impl>::getInsts()
int tid = inst->threadNumber;
if (!inst->isSquashed() &&
commitStatus[tid] != ROBSquashing) {
commitStatus[tid] != ROBSquashing &&
commitStatus[tid] != TrapPending) {
changedROBNumEntries[tid] = true;
DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n",