inorder: add updatePC event to resPool
this will be used for when a thread comes back from a cache miss, it needs to update the PCs because the inst might of been a branch or delayslot in which the next PC isnt always a straight addition
This commit is contained in:
parent
90d3b45a56
commit
aacc5cb205
7 changed files with 67 additions and 4 deletions
|
@ -571,10 +571,15 @@ PipelineStage::activateThread(ThreadID tid)
|
||||||
DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into stage skidBuffer %i\n",
|
DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into stage skidBuffer %i\n",
|
||||||
tid, inst->seqNum, inst->readPC(), inst->threadNumber);
|
tid, inst->seqNum, inst->readPC(), inst->threadNumber);
|
||||||
|
|
||||||
|
// Make instruction available for pipeline processing
|
||||||
skidBuffer[tid].push(inst);
|
skidBuffer[tid].push(inst);
|
||||||
|
|
||||||
switchedOutBuffer[tid] = NULL;
|
// Update PC so that we start fetching after this instruction to prevent
|
||||||
|
// "double"-execution of instructions
|
||||||
|
cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::UpdateAfterContextSwitch, inst, 0, 0, tid);
|
||||||
|
|
||||||
|
// Clear switchout buffer
|
||||||
|
switchedOutBuffer[tid] = NULL;
|
||||||
switchedOutValid[tid] = false;
|
switchedOutValid[tid] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,10 @@ class Resource {
|
||||||
/** Resources that care about thread activation override this. */
|
/** Resources that care about thread activation override this. */
|
||||||
virtual void suspendThread(ThreadID tid) { }
|
virtual void suspendThread(ThreadID tid) { }
|
||||||
|
|
||||||
|
/** Will be called the cycle before a context switch. Any bookkeeping
|
||||||
|
* that needs to be kept for that, can be done here
|
||||||
|
*/
|
||||||
|
virtual void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid) { }
|
||||||
|
|
||||||
/** Resources that care when an instruction has been graduated
|
/** Resources that care when an instruction has been graduated
|
||||||
* can override this
|
* can override this
|
||||||
|
|
|
@ -201,6 +201,9 @@ ResourcePool::slotsInUse(int res_idx)
|
||||||
return resources[res_idx]->slotsInUse();
|
return resources[res_idx]->slotsInUse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@todo: split this function and call this version schedulePoolEvent
|
||||||
|
// and use this scheduleEvent for scheduling a specific event on
|
||||||
|
// a resource
|
||||||
void
|
void
|
||||||
ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
|
ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
|
||||||
int delay, int res_idx, ThreadID tid)
|
int delay, int res_idx, ThreadID tid)
|
||||||
|
@ -310,6 +313,20 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ResourcePool::UpdateAfterContextSwitch:
|
||||||
|
{
|
||||||
|
DPRINTF(Resource, "Scheduling UpdatePC Resource Pool Event for tick %i.\n",
|
||||||
|
curTick + delay);
|
||||||
|
ResPoolEvent *res_pool_event = new ResPoolEvent(this,e_type,
|
||||||
|
inst,
|
||||||
|
inst->squashingStage,
|
||||||
|
inst->seqNum,
|
||||||
|
inst->readTid());
|
||||||
|
mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay));
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n",
|
DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n",
|
||||||
InOrderCPU::eventNames[e_type]);
|
InOrderCPU::eventNames[e_type]);
|
||||||
|
@ -415,6 +432,19 @@ ResourcePool::instGraduated(InstSeqNum seq_num, ThreadID tid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ResourcePool::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
|
||||||
|
{
|
||||||
|
DPRINTF(Resource, "[tid:%i] Broadcasting Update PC to all resources.\n",
|
||||||
|
tid);
|
||||||
|
|
||||||
|
int num_resources = resources.size();
|
||||||
|
|
||||||
|
for (int idx = 0; idx < num_resources; idx++) {
|
||||||
|
resources[idx]->updateAfterContextSwitch(inst, tid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool)
|
ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool)
|
||||||
: Event((Event::Priority)((unsigned)CPU_Tick_Pri+5)), resPool(_resPool),
|
: Event((Event::Priority)((unsigned)CPU_Tick_Pri+5)), resPool(_resPool),
|
||||||
eventType((InOrderCPU::CPUEventType) Default)
|
eventType((InOrderCPU::CPUEventType) Default)
|
||||||
|
@ -462,6 +492,10 @@ ResourcePool::ResPoolEvent::process()
|
||||||
resPool->squashDueToMemStall(inst, stageNum, seqNum, tid);
|
resPool->squashDueToMemStall(inst, stageNum, seqNum, tid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ResourcePool::UpdateAfterContextSwitch:
|
||||||
|
resPool->updateAfterContextSwitch(inst, tid);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatal("Unrecognized Event Type");
|
fatal("Unrecognized Event Type");
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ class ResourcePool {
|
||||||
enum ResPoolEventType {
|
enum ResPoolEventType {
|
||||||
InstGraduated = InOrderCPU::NumCPUEvents,
|
InstGraduated = InOrderCPU::NumCPUEvents,
|
||||||
SquashAll,
|
SquashAll,
|
||||||
|
UpdateAfterContextSwitch,
|
||||||
Default
|
Default
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -175,6 +176,9 @@ class ResourcePool {
|
||||||
/** De-Activate Thread in all resources */
|
/** De-Activate Thread in all resources */
|
||||||
void suspendAll(ThreadID tid);
|
void suspendAll(ThreadID tid);
|
||||||
|
|
||||||
|
/** Broadcast Context Switch Update to all resources */
|
||||||
|
void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid);
|
||||||
|
|
||||||
/** Broadcast graduation to all resources */
|
/** Broadcast graduation to all resources */
|
||||||
void instGraduated(InstSeqNum seq_num, ThreadID tid);
|
void instGraduated(InstSeqNum seq_num, ThreadID tid);
|
||||||
|
|
||||||
|
|
|
@ -49,14 +49,14 @@ using namespace ThePipeline;
|
||||||
Tick
|
Tick
|
||||||
CacheUnit::CachePort::recvAtomic(PacketPtr pkt)
|
CacheUnit::CachePort::recvAtomic(PacketPtr pkt)
|
||||||
{
|
{
|
||||||
panic("DefaultFetch doesn't expect recvAtomic callback!");
|
panic("CacheUnit::CachePort doesn't expect recvAtomic callback!");
|
||||||
return curTick;
|
return curTick;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CacheUnit::CachePort::recvFunctional(PacketPtr pkt)
|
CacheUnit::CachePort::recvFunctional(PacketPtr pkt)
|
||||||
{
|
{
|
||||||
panic("DefaultFetch doesn't expect recvFunctional callback!");
|
panic("CacheUnit::CachePort doesn't expect recvFunctional callback!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -65,7 +65,7 @@ CacheUnit::CachePort::recvStatusChange(Status status)
|
||||||
if (status == RangeChange)
|
if (status == RangeChange)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
panic("DefaultFetch doesn't expect recvStatusChange callback!");
|
panic("CacheUnit::CachePort doesn't expect recvStatusChange callback!");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -342,3 +342,17 @@ FetchSeqUnit::suspendThread(ThreadID tid)
|
||||||
{
|
{
|
||||||
deactivateThread(tid);
|
deactivateThread(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
|
||||||
|
{
|
||||||
|
pcValid[tid] = true;
|
||||||
|
|
||||||
|
PC[tid] = inst->readNextPC();
|
||||||
|
nextPC[tid] = inst->readNextNPC();
|
||||||
|
nextNPC[tid] = inst->readNextNPC() + instSize;
|
||||||
|
|
||||||
|
|
||||||
|
DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PC:%08p NPC:%08p NNPC:%08p.\n",
|
||||||
|
tid, PC[tid], nextPC[tid], nextNPC[tid]);
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ class FetchSeqUnit : public Resource {
|
||||||
virtual void deactivateThread(ThreadID tid);
|
virtual void deactivateThread(ThreadID tid);
|
||||||
virtual void suspendThread(ThreadID tid);
|
virtual void suspendThread(ThreadID tid);
|
||||||
virtual void execute(int slot_num);
|
virtual void execute(int slot_num);
|
||||||
|
void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid);
|
||||||
|
|
||||||
|
|
||||||
/** Override default Resource squash sequence. This actually,
|
/** Override default Resource squash sequence. This actually,
|
||||||
* looks in the global communication buffer to get squash
|
* looks in the global communication buffer to get squash
|
||||||
|
|
Loading…
Reference in a new issue