Updates to O3 CPU. It should now work in FS mode, although sampling still has a bug.

src/cpu/o3/commit_impl.hh:
    Fixes for compile and sampling.
src/cpu/o3/cpu.cc:
    Deallocate and activate threads properly.  Also hopefully fix being able to use caches while switching over.
src/cpu/o3/cpu.hh:
    Fixes for deallocating and activating threads.
src/cpu/o3/fetch_impl.hh:
src/cpu/o3/lsq_unit.hh:
    Handle getting back a BadAddress result from the access.
src/cpu/o3/iew_impl.hh:
    More debug output.
src/cpu/o3/lsq_unit_impl.hh:
    Fixup store conditional handling (still a bit of a hack, but works now).

    Also handle getting back a BadAddress result from the access.
src/cpu/o3/thread_context_impl.hh:
    Deallocate context now records if the context should be fully removed.

--HG--
extra : convert_revision : 55f81660602d0e25367ce1f5b0b9cfc62abe7bf9
This commit is contained in:
Kevin Lim 2006-10-08 00:53:41 -04:00
parent c0e53b6d4c
commit d48ea81ba2
8 changed files with 96 additions and 36 deletions

View file

@ -342,12 +342,6 @@ DefaultCommit<Impl>::drain()
{ {
drainPending = true; drainPending = true;
// If it's already drained, return true.
if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
cpu->signalDrained();
return true;
}
return false; return false;
} }
@ -1218,16 +1212,16 @@ DefaultCommit<Impl>::skidInsert()
for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) { for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) {
DynInstPtr inst = fromRename->insts[inst_num]; DynInstPtr inst = fromRename->insts[inst_num];
int tid = inst->threadNumber;
if (!inst->isSquashed()) { if (!inst->isSquashed()) {
DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ", DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ",
"skidBuffer.\n", inst->readPC(), inst->seqNum, tid); "skidBuffer.\n", inst->readPC(), inst->seqNum,
inst->threadNumber);
skidBuffer.push(inst); skidBuffer.push(inst);
} else { } else {
DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was " DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
"squashed, skipping.\n", "squashed, skipping.\n",
inst->readPC(), inst->seqNum, tid); inst->readPC(), inst->seqNum, inst->threadNumber);
} }
} }
} }

View file

@ -88,7 +88,7 @@ FullO3CPU<Impl>::TickEvent::description()
template <class Impl> template <class Impl>
FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent()
: Event(&mainEventQueue, CPU_Tick_Pri) : Event(&mainEventQueue, CPU_Switch_Pri)
{ {
} }
@ -135,7 +135,8 @@ void
FullO3CPU<Impl>::DeallocateContextEvent::process() FullO3CPU<Impl>::DeallocateContextEvent::process()
{ {
cpu->deactivateThread(tid); cpu->deactivateThread(tid);
cpu->removeThread(tid); if (remove)
cpu->removeThread(tid);
} }
template <class Impl> template <class Impl>
@ -191,7 +192,11 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
deferRegistration(params->deferRegistration), deferRegistration(params->deferRegistration),
numThreads(number_of_threads) numThreads(number_of_threads)
{ {
_status = Idle; if (!deferRegistration) {
_status = Running;
} else {
_status = Idle;
}
checker = NULL; checker = NULL;
@ -304,6 +309,9 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
tid, tid,
bindRegs); bindRegs);
activateThreadEvent[tid].init(tid, this);
deallocateContextEvent[tid].init(tid, this);
} }
rename.setRenameMap(renameMap); rename.setRenameMap(renameMap);
@ -449,7 +457,7 @@ FullO3CPU<Impl>::tick()
getState() == SimObject::Drained) { getState() == SimObject::Drained) {
// increment stat // increment stat
lastRunningCycle = curTick; lastRunningCycle = curTick;
} else if (!activityRec.active()) { } else if (!activityRec.active() || _status == Idle) {
lastRunningCycle = curTick; lastRunningCycle = curTick;
timesIdled++; timesIdled++;
} else { } else {
@ -548,7 +556,7 @@ FullO3CPU<Impl>::activateContext(int tid, int delay)
activateThread(tid); activateThread(tid);
} }
if(lastActivatedCycle < curTick) { if (lastActivatedCycle < curTick) {
scheduleTickEvent(delay); scheduleTickEvent(delay);
// Be sure to signal that there's some activity so the CPU doesn't // Be sure to signal that there's some activity so the CPU doesn't
@ -563,17 +571,20 @@ FullO3CPU<Impl>::activateContext(int tid, int delay)
} }
template <class Impl> template <class Impl>
void bool
FullO3CPU<Impl>::deallocateContext(int tid, int delay) FullO3CPU<Impl>::deallocateContext(int tid, bool remove, int delay)
{ {
// Schedule removal of thread data from CPU // Schedule removal of thread data from CPU
if (delay){ if (delay){
DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate " DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
"on cycle %d\n", tid, curTick + cycles(delay)); "on cycle %d\n", tid, curTick + cycles(delay));
scheduleDeallocateContextEvent(tid, delay); scheduleDeallocateContextEvent(tid, remove, delay);
return false;
} else { } else {
deactivateThread(tid); deactivateThread(tid);
removeThread(tid); if (remove)
removeThread(tid);
return true;
} }
} }
@ -582,8 +593,9 @@ void
FullO3CPU<Impl>::suspendContext(int tid) FullO3CPU<Impl>::suspendContext(int tid)
{ {
DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
deactivateThread(tid); bool deallocated = deallocateContext(tid, false, 1);
if (activeThreads.size() == 0) // If this was the last thread then unschedule the tick event.
if ((activeThreads.size() == 1 && !deallocated) || activeThreads.size() == 0)
unscheduleTickEvent(); unscheduleTickEvent();
_status = Idle; _status = Idle;
} }
@ -594,7 +606,7 @@ FullO3CPU<Impl>::haltContext(int tid)
{ {
//For now, this is the same as deallocate //For now, this is the same as deallocate
DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid); DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
deallocateContext(tid, 1); deallocateContext(tid, true, 1);
} }
template <class Impl> template <class Impl>
@ -935,6 +947,25 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
} }
if (!tickEvent.scheduled()) if (!tickEvent.scheduled())
tickEvent.schedule(curTick); tickEvent.schedule(curTick);
Port *peer;
Port *icachePort = fetch.getIcachePort();
if (icachePort->getPeer() == NULL) {
peer = oldCPU->getPort("icachePort")->getPeer();
icachePort->setPeer(peer);
} else {
peer = icachePort->getPeer();
}
peer->setPeer(icachePort);
Port *dcachePort = iew.getDcachePort();
if (dcachePort->getPeer() == NULL) {
Port *peer = oldCPU->getPort("dcachePort")->getPeer();
dcachePort->setPeer(peer);
} else {
peer = dcachePort->getPeer();
}
peer->setPeer(dcachePort);
} }
template <class Impl> template <class Impl>

View file

@ -202,9 +202,12 @@ class FullO3CPU : public BaseO3CPU
class DeallocateContextEvent : public Event class DeallocateContextEvent : public Event
{ {
private: private:
/** Number of Thread to Activate */ /** Number of Thread to deactivate */
int tid; int tid;
/** Should the thread be removed from the CPU? */
bool remove;
/** Pointer to the CPU. */ /** Pointer to the CPU. */
FullO3CPU<Impl> *cpu; FullO3CPU<Impl> *cpu;
@ -218,12 +221,15 @@ class FullO3CPU : public BaseO3CPU
/** Processes the event, calling activateThread() on the CPU. */ /** Processes the event, calling activateThread() on the CPU. */
void process(); void process();
/** Sets whether the thread should also be removed from the CPU. */
void setRemove(bool _remove) { remove = _remove; }
/** Returns the description of the event. */ /** Returns the description of the event. */
const char *description(); const char *description();
}; };
/** Schedule cpu to deallocate thread context.*/ /** Schedule cpu to deallocate thread context.*/
void scheduleDeallocateContextEvent(int tid, int delay) void scheduleDeallocateContextEvent(int tid, bool remove, int delay)
{ {
// 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())
@ -296,9 +302,9 @@ class FullO3CPU : public BaseO3CPU
void suspendContext(int tid); void suspendContext(int tid);
/** Remove Thread from Active Threads List && /** Remove Thread from Active Threads List &&
* Remove Thread Context from CPU. * Possibly Remove Thread Context from CPU.
*/ */
void deallocateContext(int tid, int delay = 1); bool deallocateContext(int tid, bool remove, int delay = 1);
/** Remove Thread from Active Threads List && /** Remove Thread from Active Threads List &&
* Remove Thread Context from CPU. * Remove Thread Context from CPU.
@ -626,11 +632,6 @@ class FullO3CPU : public BaseO3CPU
/** Pointers to all of the threads in the CPU. */ /** Pointers to all of the threads in the CPU. */
std::vector<Thread *> thread; std::vector<Thread *> thread;
/** Pointer to the icache interface. */
MemInterface *icacheInterface;
/** Pointer to the dcache interface. */
MemInterface *dcacheInterface;
/** Whether or not the CPU should defer its registration. */ /** Whether or not the CPU should defer its registration. */
bool deferRegistration; bool deferRegistration;

View file

@ -623,6 +623,11 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
// Now do the timing access to see whether or not the instruction // Now do the timing access to see whether or not the instruction
// exists within the cache. // exists within the cache.
if (!icachePort->sendTiming(data_pkt)) { if (!icachePort->sendTiming(data_pkt)) {
if (data_pkt->result == Packet::BadAddress) {
fault = TheISA::genMachineCheckFault();
delete mem_req;
memReq[tid] = NULL;
}
assert(retryPkt == NULL); assert(retryPkt == NULL);
assert(retryTid == -1); assert(retryTid == -1);
DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);

View file

@ -600,6 +600,11 @@ template<class Impl>
void void
DefaultIEW<Impl>::instToCommit(DynInstPtr &inst) DefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
{ {
// This function should not be called after writebackInsts in a
// single cycle. That will cause problems with an instruction
// being added to the queue to commit without being processed by
// writebackInsts prior to being sent to commit.
// First check the time slot that this instruction will write // First check the time slot that this instruction will write
// to. If there are free write ports at the time, then go ahead // to. If there are free write ports at the time, then go ahead
// and write the instruction to that time. If there are not, // and write the instruction to that time. If there are not,
@ -1286,6 +1291,7 @@ DefaultIEW<Impl>::executeInsts()
} else if (fault != NoFault) { } else if (fault != NoFault) {
// 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
// without the instruction completing. // without the instruction completing.
DPRINTF(IEW, "Store has fault! [sn:%lli]\n", inst->seqNum);
// Send this instruction to commit, also make sure iew stage // Send this instruction to commit, also make sure iew stage
// realizes there is activity. // realizes there is activity.

View file

@ -638,6 +638,11 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
// if we the cache is not blocked, do cache access // if we the cache is not blocked, do cache access
if (!lsq->cacheBlocked()) { if (!lsq->cacheBlocked()) {
if (!dcachePort->sendTiming(data_pkt)) { if (!dcachePort->sendTiming(data_pkt)) {
if (data_pkt->result == Packet::BadAddress) {
delete data_pkt;
return TheISA::genMachineCheckFault();
}
// If the access didn't succeed, tell the LSQ by setting // If the access didn't succeed, tell the LSQ by setting
// the retry thread id. // the retry thread id.
lsq->setRetryTid(lsqID); lsq->setRetryTid(lsqID);

View file

@ -608,9 +608,9 @@ LSQUnit<Impl>::writebackStores()
DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
"to Addr:%#x, data:%#x [sn:%lli]\n", "to Addr:%#x, data:%#x [sn:%lli]\n",
storeWBIdx, storeQueue[storeWBIdx].inst->readPC(), storeWBIdx, inst->readPC(),
req->getPaddr(), *(inst->memData), req->getPaddr(), *(inst->memData),
storeQueue[storeWBIdx].inst->seqNum); inst->seqNum);
// @todo: Remove this SC hack once the memory system handles it. // @todo: Remove this SC hack once the memory system handles it.
if (req->getFlags() & LOCKED) { if (req->getFlags() & LOCKED) {
@ -619,10 +619,19 @@ LSQUnit<Impl>::writebackStores()
} else { } else {
if (cpu->lockFlag) { if (cpu->lockFlag) {
req->setScResult(1); req->setScResult(1);
DPRINTF(LSQUnit, "Store conditional [sn:%lli] succeeded.",
inst->seqNum);
} else { } else {
req->setScResult(0); req->setScResult(0);
// Hack: Instantly complete this store. // Hack: Instantly complete this store.
completeDataAccess(data_pkt); // completeDataAccess(data_pkt);
DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. "
"Instantly completing it.\n",
inst->seqNum);
WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
wb->schedule(curTick + 1);
delete state;
completeStore(storeWBIdx);
incrStIdx(storeWBIdx); incrStIdx(storeWBIdx);
continue; continue;
} }
@ -633,7 +642,13 @@ LSQUnit<Impl>::writebackStores()
} }
if (!dcachePort->sendTiming(data_pkt)) { if (!dcachePort->sendTiming(data_pkt)) {
if (data_pkt->result == Packet::BadAddress) {
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"
"retry later\n",
inst->seqNum);
isStoreBlocked = true; isStoreBlocked = true;
++lsqCacheBlocked; ++lsqCacheBlocked;
assert(retryPkt == NULL); assert(retryPkt == NULL);
@ -880,6 +895,9 @@ LSQUnit<Impl>::recvRetry()
assert(retryPkt != NULL); assert(retryPkt != NULL);
if (dcachePort->sendTiming(retryPkt)) { if (dcachePort->sendTiming(retryPkt)) {
if (retryPkt->result == Packet::BadAddress) {
panic("LSQ sent out a bad address for a completed store!");
}
storePostSend(retryPkt); storePostSend(retryPkt);
retryPkt = NULL; retryPkt = NULL;
isStoreBlocked = false; isStoreBlocked = false;

View file

@ -165,14 +165,14 @@ template <class Impl>
void void
O3ThreadContext<Impl>::deallocate(int delay) O3ThreadContext<Impl>::deallocate(int delay)
{ {
DPRINTF(O3CPU, "Calling deallocate on Thread Context %d\n", DPRINTF(O3CPU, "Calling deallocate on Thread Context %d delay %d\n",
getThreadNum()); getThreadNum(), delay);
if (thread->status() == ThreadContext::Unallocated) if (thread->status() == ThreadContext::Unallocated)
return; return;
thread->setStatus(ThreadContext::Unallocated); thread->setStatus(ThreadContext::Unallocated);
cpu->deallocateContext(thread->readTid(), delay); cpu->deallocateContext(thread->readTid(), true, delay);
} }
template <class Impl> template <class Impl>