Support for draining, and the new method of switching out. Now switching out happens after the pipeline has been drained, deferring the three way handshake to the normal drain mechanism. The calls of switchOut() and takeOverFrom() both take action immediately.
src/cpu/o3/commit.hh: src/cpu/o3/commit_impl.hh: src/cpu/o3/cpu.cc: src/cpu/o3/cpu.hh: src/cpu/o3/decode.hh: src/cpu/o3/decode_impl.hh: src/cpu/o3/fetch.hh: src/cpu/o3/fetch_impl.hh: src/cpu/o3/iew.hh: src/cpu/o3/iew_impl.hh: src/cpu/o3/rename.hh: src/cpu/o3/rename_impl.hh: Support for draining, new method of switching out. --HG-- extra : convert_revision : 05bf8b271ec85b3e2c675c3bed6c42aeba21f465
This commit is contained in:
parent
8c547d80b1
commit
30c516d51c
|
@ -187,11 +187,14 @@ class DefaultCommit
|
|||
/** Initializes stage by sending back the number of free entries. */
|
||||
void initStage();
|
||||
|
||||
/** Initializes the switching out of commit. */
|
||||
void switchOut();
|
||||
/** Initializes the draining of commit. */
|
||||
void drain();
|
||||
|
||||
/** Resumes execution after draining. */
|
||||
void resume();
|
||||
|
||||
/** Completes the switch out of commit. */
|
||||
void doSwitchOut();
|
||||
void switchOut();
|
||||
|
||||
/** Takes over from another CPU's thread. */
|
||||
void takeOverFrom();
|
||||
|
@ -383,8 +386,8 @@ class DefaultCommit
|
|||
/** Number of Active Threads */
|
||||
unsigned numThreads;
|
||||
|
||||
/** Is a switch out pending. */
|
||||
bool switchPending;
|
||||
/** Is a drain pending. */
|
||||
bool drainPending;
|
||||
|
||||
/** Is commit switched out. */
|
||||
bool switchedOut;
|
||||
|
|
|
@ -80,7 +80,7 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
|
|||
renameWidth(params->renameWidth),
|
||||
commitWidth(params->commitWidth),
|
||||
numThreads(params->numberOfThreads),
|
||||
switchPending(false),
|
||||
drainPending(false),
|
||||
switchedOut(false),
|
||||
trapLatency(params->trapLatency),
|
||||
fetchTrapLatency(params->fetchTrapLatency)
|
||||
|
@ -351,20 +351,26 @@ DefaultCommit<Impl>::initStage()
|
|||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultCommit<Impl>::switchOut()
|
||||
DefaultCommit<Impl>::drain()
|
||||
{
|
||||
switchPending = true;
|
||||
drainPending = true;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultCommit<Impl>::doSwitchOut()
|
||||
DefaultCommit<Impl>::switchOut()
|
||||
{
|
||||
switchedOut = true;
|
||||
switchPending = false;
|
||||
drainPending = false;
|
||||
rob->switchOut();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultCommit<Impl>::resume()
|
||||
{
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultCommit<Impl>::takeOverFrom()
|
||||
|
@ -557,8 +563,9 @@ DefaultCommit<Impl>::tick()
|
|||
wroteToTimeBuffer = false;
|
||||
_nextStatus = Inactive;
|
||||
|
||||
if (switchPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
|
||||
cpu->signalSwitched();
|
||||
if (drainPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
|
||||
cpu->signalDrained();
|
||||
drainPending = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
|
|||
physmem(system->physmem),
|
||||
#endif // FULL_SYSTEM
|
||||
mem(params->mem),
|
||||
switchCount(0),
|
||||
drainCount(0),
|
||||
deferRegistration(params->deferRegistration),
|
||||
numThreads(number_of_threads)
|
||||
{
|
||||
|
@ -713,45 +713,72 @@ FullO3CPU<Impl>::haltContext(int tid)
|
|||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::switchOut()
|
||||
bool
|
||||
FullO3CPU<Impl>::drain(Event *drain_event)
|
||||
{
|
||||
switchCount = 0;
|
||||
fetch.switchOut();
|
||||
decode.switchOut();
|
||||
rename.switchOut();
|
||||
iew.switchOut();
|
||||
commit.switchOut();
|
||||
drainCount = 0;
|
||||
drainEvent = drain_event;
|
||||
fetch.drain();
|
||||
decode.drain();
|
||||
rename.drain();
|
||||
iew.drain();
|
||||
commit.drain();
|
||||
|
||||
// Wake the CPU and record activity so everything can drain out if
|
||||
// the CPU is currently idle.
|
||||
wakeCPU();
|
||||
activityRec.activity();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::signalSwitched()
|
||||
FullO3CPU<Impl>::resume()
|
||||
{
|
||||
if (++switchCount == NumStages) {
|
||||
fetch.doSwitchOut();
|
||||
rename.doSwitchOut();
|
||||
commit.doSwitchOut();
|
||||
instList.clear();
|
||||
while (!removeList.empty()) {
|
||||
removeList.pop();
|
||||
}
|
||||
if (_status == SwitchedOut)
|
||||
return;
|
||||
fetch.resume();
|
||||
decode.resume();
|
||||
rename.resume();
|
||||
iew.resume();
|
||||
commit.resume();
|
||||
|
||||
#if USE_CHECKER
|
||||
if (checker)
|
||||
checker->switchOut();
|
||||
#endif
|
||||
if (!tickEvent.scheduled())
|
||||
tickEvent.schedule(curTick);
|
||||
_status = Running;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::signalDrained()
|
||||
{
|
||||
if (++drainCount == NumStages) {
|
||||
if (tickEvent.scheduled())
|
||||
tickEvent.squash();
|
||||
_status = SwitchedOut;
|
||||
_status = Drained;
|
||||
drainEvent->process();
|
||||
}
|
||||
assert(switchCount <= 5);
|
||||
assert(drainCount <= 5);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::switchOut()
|
||||
{
|
||||
fetch.switchOut();
|
||||
rename.switchOut();
|
||||
commit.switchOut();
|
||||
instList.clear();
|
||||
while (!removeList.empty()) {
|
||||
removeList.pop();
|
||||
}
|
||||
|
||||
_status = SwitchedOut;
|
||||
#if USE_CHECKER
|
||||
if (checker)
|
||||
checker->switchOut();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
|
|
|
@ -57,6 +57,8 @@ class Checker;
|
|||
class ThreadContext;
|
||||
template <class>
|
||||
class O3ThreadContext;
|
||||
|
||||
class Checkpoint;
|
||||
class MemObject;
|
||||
class Process;
|
||||
|
||||
|
@ -109,6 +111,7 @@ class FullO3CPU : public BaseO3CPU
|
|||
Idle,
|
||||
Halted,
|
||||
Blocked,
|
||||
Drained,
|
||||
SwitchedOut
|
||||
};
|
||||
|
||||
|
@ -270,14 +273,21 @@ class FullO3CPU : public BaseO3CPU
|
|||
*/
|
||||
virtual void syscall(int tid) { panic("Unimplemented!"); }
|
||||
|
||||
/** Switches out this CPU. */
|
||||
void switchOut();
|
||||
/** Starts draining the CPU's pipeline of all instructions in
|
||||
* order to stop all memory accesses. */
|
||||
virtual bool drain(Event *drain_event);
|
||||
|
||||
/** Resumes execution after a drain. */
|
||||
virtual void resume();
|
||||
|
||||
/** Signals to this CPU that a stage has completed switching out. */
|
||||
void signalSwitched();
|
||||
void signalDrained();
|
||||
|
||||
/** Switches out this CPU. */
|
||||
virtual void switchOut();
|
||||
|
||||
/** Takes over from another CPU. */
|
||||
void takeOverFrom(BaseCPU *oldCPU);
|
||||
virtual void takeOverFrom(BaseCPU *oldCPU);
|
||||
|
||||
/** Get the current instruction sequence number, and increment it. */
|
||||
InstSeqNum getAndIncrementInstSeq()
|
||||
|
@ -550,8 +560,11 @@ class FullO3CPU : public BaseO3CPU
|
|||
/** Pointer to memory. */
|
||||
MemObject *mem;
|
||||
|
||||
/** Counter of how many stages have completed switching out. */
|
||||
int switchCount;
|
||||
/** Event to call process() on once draining has completed. */
|
||||
Event *drainEvent;
|
||||
|
||||
/** Counter of how many stages have completed draining. */
|
||||
int drainCount;
|
||||
|
||||
/** Pointers to all of the threads in the CPU. */
|
||||
std::vector<Thread *> thread;
|
||||
|
|
|
@ -109,8 +109,14 @@ class DefaultDecode
|
|||
/** Sets pointer to list of active threads. */
|
||||
void setActiveThreads(std::list<unsigned> *at_ptr);
|
||||
|
||||
/** Drains the decode stage. */
|
||||
void drain();
|
||||
|
||||
/** Resumes execution after a drain. */
|
||||
void resume() { }
|
||||
|
||||
/** Switches out the decode stage. */
|
||||
void switchOut();
|
||||
void switchOut() { }
|
||||
|
||||
/** Takes over from another CPU's thread. */
|
||||
void takeOverFrom();
|
||||
|
|
|
@ -166,10 +166,10 @@ DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
|
|||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultDecode<Impl>::switchOut()
|
||||
DefaultDecode<Impl>::drain()
|
||||
{
|
||||
// Decode can immediately switch out.
|
||||
cpu->signalSwitched();
|
||||
// Decode is done draining at any time.
|
||||
cpu->signalDrained();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
|
|
|
@ -180,11 +180,14 @@ class DefaultFetch
|
|||
/** Processes cache completion event. */
|
||||
void processCacheCompletion(PacketPtr pkt);
|
||||
|
||||
/** Begins the switch out of the fetch stage. */
|
||||
void switchOut();
|
||||
/** Begins the drain of the fetch stage. */
|
||||
void drain();
|
||||
|
||||
/** Completes the switch out of the fetch stage. */
|
||||
void doSwitchOut();
|
||||
/** Resumes execution after a drain. */
|
||||
void resume();
|
||||
|
||||
/** Tells fetch stage to prepare to be switched out. */
|
||||
void switchOut();
|
||||
|
||||
/** Takes over from another CPU's thread. */
|
||||
void takeOverFrom();
|
||||
|
@ -421,6 +424,9 @@ class DefaultFetch
|
|||
*/
|
||||
bool interruptPending;
|
||||
|
||||
/** Is there a drain pending. */
|
||||
bool drainPending;
|
||||
|
||||
/** Records if fetch is switched out. */
|
||||
bool switchedOut;
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
|
|||
numThreads(params->numberOfThreads),
|
||||
numFetchingThreads(params->smtNumFetchingThreads),
|
||||
interruptPending(false),
|
||||
drainPending(false),
|
||||
switchedOut(false)
|
||||
{
|
||||
if (numThreads > Impl::MaxThreads)
|
||||
|
@ -353,7 +354,8 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
|
|||
// to return.
|
||||
if (fetchStatus[tid] != IcacheWaitResponse ||
|
||||
pkt->req != memReq[tid] ||
|
||||
isSwitchedOut()) {
|
||||
isSwitchedOut() ||
|
||||
drainPending) {
|
||||
++fetchIcacheSquashes;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
@ -384,17 +386,25 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
|
|||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultFetch<Impl>::switchOut()
|
||||
DefaultFetch<Impl>::drain()
|
||||
{
|
||||
// Fetch is ready to switch out at any time.
|
||||
switchedOut = true;
|
||||
cpu->signalSwitched();
|
||||
// Fetch is ready to drain at any time.
|
||||
cpu->signalDrained();
|
||||
drainPending = true;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultFetch<Impl>::doSwitchOut()
|
||||
DefaultFetch<Impl>::resume()
|
||||
{
|
||||
drainPending = false;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultFetch<Impl>::switchOut()
|
||||
{
|
||||
switchedOut = true;
|
||||
// Branch predictor needs to have its state cleared.
|
||||
branchPred.switchOut();
|
||||
}
|
||||
|
@ -498,7 +508,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
|
|||
unsigned flags = 0;
|
||||
#endif // FULL_SYSTEM
|
||||
|
||||
if (cacheBlocked || (interruptPending && flags == 0) || switchedOut) {
|
||||
if (cacheBlocked || (interruptPending && flags == 0) || drainPending) {
|
||||
// Hold off fetch from getting new instructions when:
|
||||
// Cache is blocked, or
|
||||
// while an interrupt is pending and we're not in PAL mode, or
|
||||
|
|
|
@ -143,11 +143,14 @@ class DefaultIEW
|
|||
/** Sets pointer to the scoreboard. */
|
||||
void setScoreboard(Scoreboard *sb_ptr);
|
||||
|
||||
/** Starts switch out of IEW stage. */
|
||||
void switchOut();
|
||||
/** Drains IEW stage. */
|
||||
void drain();
|
||||
|
||||
/** Resumes execution after a drain. */
|
||||
void resume();
|
||||
|
||||
/** Completes switch out of IEW stage. */
|
||||
void doSwitchOut();
|
||||
void switchOut();
|
||||
|
||||
/** Takes over from another CPU's thread. */
|
||||
void takeOverFrom();
|
||||
|
|
|
@ -355,15 +355,21 @@ DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
|
|||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultIEW<Impl>::switchOut()
|
||||
DefaultIEW<Impl>::drain()
|
||||
{
|
||||
// IEW is ready to switch out at any time.
|
||||
cpu->signalSwitched();
|
||||
// IEW is ready to drain at any time.
|
||||
cpu->signalDrained();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultIEW<Impl>::doSwitchOut()
|
||||
DefaultIEW<Impl>::resume()
|
||||
{
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultIEW<Impl>::switchOut()
|
||||
{
|
||||
// Clear any state.
|
||||
switchedOut = true;
|
||||
|
|
|
@ -157,12 +157,15 @@ class DefaultRename
|
|||
/** Sets pointer to the scoreboard. */
|
||||
void setScoreboard(Scoreboard *_scoreboard);
|
||||
|
||||
/** Drains the rename stage. */
|
||||
void drain();
|
||||
|
||||
/** Resumes execution after a drain. */
|
||||
void resume() { }
|
||||
|
||||
/** Switches out the rename stage. */
|
||||
void switchOut();
|
||||
|
||||
/** Completes the switch out. */
|
||||
void doSwitchOut();
|
||||
|
||||
/** Takes over from another CPU's thread. */
|
||||
void takeOverFrom();
|
||||
|
||||
|
|
|
@ -258,15 +258,15 @@ DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
|
|||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultRename<Impl>::switchOut()
|
||||
DefaultRename<Impl>::drain()
|
||||
{
|
||||
// Rename is ready to switch out at any time.
|
||||
cpu->signalSwitched();
|
||||
cpu->signalDrained();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
DefaultRename<Impl>::doSwitchOut()
|
||||
DefaultRename<Impl>::switchOut()
|
||||
{
|
||||
// Clear any state, fix up the rename map.
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
|
|
Loading…
Reference in a new issue