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:
parent
c0e53b6d4c
commit
d48ea81ba2
8 changed files with 96 additions and 36 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue