summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2006-11-12 21:57:58 -0500
committerKevin Lim <ktlim@umich.edu>2006-11-12 21:57:58 -0500
commit3052632b68f842750c767caaf310fcbf116c559f (patch)
tree9b4b05c13e5e9c964659122e85fff46a14b5e88f /src/cpu
parentd2d44317528ffadf81fbb95c92291d8d2d4a2190 (diff)
parent437436a2f706477439cfb81d254e8f7b454450a5 (diff)
downloadgem5-3052632b68f842750c767caaf310fcbf116c559f.tar.xz
Merge ktlim@zamp:./local/clean/tmp/test-regress
into zamp.eecs.umich.edu:/z/ktlim2/clean/newmem-busfix --HG-- extra : convert_revision : b98236507bb8996ce605b48b5a5a6a7aac297dc5
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/o3/alpha/cpu.hh7
-rw-r--r--src/cpu/o3/alpha/cpu_impl.hh22
-rw-r--r--src/cpu/o3/commit_impl.hh33
-rw-r--r--src/cpu/o3/cpu.cc6
-rw-r--r--src/cpu/o3/fetch_impl.hh25
-rw-r--r--src/cpu/ozone/cpu_impl.hh50
-rw-r--r--src/cpu/ozone/front_end_impl.hh4
-rw-r--r--src/cpu/simple/atomic.cc3
-rw-r--r--src/cpu/simple/base.cc1
9 files changed, 77 insertions, 74 deletions
diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh
index b62550062..0078db69f 100644
--- a/src/cpu/o3/alpha/cpu.hh
+++ b/src/cpu/o3/alpha/cpu.hh
@@ -156,8 +156,11 @@ class AlphaO3CPU : public FullO3CPU<Impl>
bool simPalCheck(int palFunc, unsigned tid);
- /** Processes any interrupts. */
- void processInterrupts();
+ /** Returns the Fault for any valid interrupt. */
+ Fault getInterrupts();
+
+ /** Processes any an interrupt fault. */
+ void processInterrupts(Fault interrupt);
/** Halts the CPU. */
void halt() { panic("Halt not implemented!\n"); }
diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh
index 15b50cb15..b2ef78360 100644
--- a/src/cpu/o3/alpha/cpu_impl.hh
+++ b/src/cpu/o3/alpha/cpu_impl.hh
@@ -267,8 +267,16 @@ AlphaO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
}
template <class Impl>
+Fault
+AlphaO3CPU<Impl>::getInterrupts()
+{
+ // Check if there are any outstanding interrupts
+ return this->interrupts.getInterrupt(this->threadContexts[0]);
+}
+
+template <class Impl>
void
-AlphaO3CPU<Impl>::processInterrupts()
+AlphaO3CPU<Impl>::processInterrupts(Fault interrupt)
{
// Check for interrupts here. For now can copy the code that
// exists within isa_fullsys_traits.hh. Also assume that thread 0
@@ -276,14 +284,12 @@ AlphaO3CPU<Impl>::processInterrupts()
// @todo: Possibly consolidate the interrupt checking code.
// @todo: Allow other threads to handle interrupts.
- // Check if there are any outstanding interrupts
- //Handle the interrupts
- Fault interrupt = this->interrupts.getInterrupt(this->tcBase(0));
+ assert(interrupt != NoFault);
+ this->interrupts.updateIntrInfo(this->threadContexts[0]);
- if (interrupt != NoFault) {
- this->checkInterrupts = false;
- this->trap(interrupt, 0);
- }
+ DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
+ this->checkInterrupts = false;
+ this->trap(interrupt, 0);
}
#endif // FULL_SYSTEM
diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index 30052a148..b394759b9 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -640,8 +640,18 @@ DefaultCommit<Impl>::commit()
// @todo: Allow other threads to handle interrupts.
if (cpu->checkInterrupts &&
cpu->check_interrupts(cpu->tcBase(0)) &&
+ commitStatus[0] != TrapPending &&
!trapSquash[0] &&
!tcSquash[0]) {
+
+ // Get any interrupt that happened
+ Fault intr = cpu->getInterrupts();
+
+ // Exit this if block if there's no fault.
+ if (intr == NoFault) {
+ goto commit_insts;
+ }
+
// Tell fetch that there is an interrupt pending. This will
// make fetch wait until it sees a non PAL-mode PC, at which
// point it stops fetching instructions.
@@ -650,36 +660,37 @@ DefaultCommit<Impl>::commit()
// Wait until the ROB is empty and all stores have drained in
// order to enter the interrupt.
if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
- // Not sure which thread should be the one to interrupt. For now
- // always do thread 0.
+ // Squash or record that I need to squash this cycle if
+ // an interrupt needed to be handled.
+ DPRINTF(Commit, "Interrupt detected.\n");
+
assert(!thread[0]->inSyscall);
thread[0]->inSyscall = true;
- // CPU will handle implementation of the interrupt.
- cpu->processInterrupts();
-
- // Now squash or record that I need to squash this cycle.
- commitStatus[0] = TrapPending;
+ // CPU will handle interrupt.
+ cpu->processInterrupts(intr);
- // Exit state update mode to avoid accidental updating.
thread[0]->inSyscall = false;
+ commitStatus[0] = TrapPending;
+
// Generate trap squash event.
generateTrapEvent(0);
toIEW->commitInfo[0].clearInterrupt = true;
-
- DPRINTF(Commit, "Interrupt detected.\n");
} else {
DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
}
}
+
+ // Label for goto. Not pretty but more readable than really big
+ // if statement above.
+ commit_insts:
#endif // FULL_SYSTEM
////////////////////////////////////
// Check for any possible squashes, handle them first
////////////////////////////////////
-
std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index dfe42d882..580816372 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -819,6 +819,12 @@ unsigned int
FullO3CPU<Impl>::drain(Event *drain_event)
{
DPRINTF(O3CPU, "Switching out\n");
+
+ // If the CPU isn't doing anything, then return immediately.
+ if (_status == Idle || _status == SwitchedOut) {
+ return 0;
+ }
+
drainCount = 0;
fetch.drain();
decode.drain();
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 350ecd52d..a5478d4f8 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -561,27 +561,36 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
Fault fault = NoFault;
//AlphaDep
- if (cacheBlocked || isSwitchedOut() ||
- (interruptPending && (fetch_PC & 0x3))) {
+ if (cacheBlocked) {
+ DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, cache blocked\n",
+ tid);
+ return false;
+ } else if (isSwitchedOut()) {
+ DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, switched out\n",
+ tid);
+ return false;
+ } else if (interruptPending && !(fetch_PC & 0x3)) {
// 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
// fetch is switched out.
+ DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, interrupt pending\n",
+ tid);
return false;
}
// Align the fetch PC so it's at the start of a cache block.
- fetch_PC = icacheBlockAlignPC(fetch_PC);
+ Addr block_PC = icacheBlockAlignPC(fetch_PC);
// If we've already got the block, no need to try to fetch it again.
- if (cacheDataValid[tid] && fetch_PC == cacheDataPC[tid]) {
+ if (cacheDataValid[tid] && block_PC == cacheDataPC[tid]) {
return true;
}
// Setup the memReq to do a read of the first instruction's address.
// Set the appropriate read size and flags as well.
// Build request here.
- RequestPtr mem_req = new Request(tid, fetch_PC, cacheBlkSize, 0,
+ RequestPtr mem_req = new Request(tid, block_PC, cacheBlkSize, 0,
fetch_PC, cpu->readCpuId(), tid);
memReq[tid] = mem_req;
@@ -611,7 +620,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
Packet::ReadReq, Packet::Broadcast);
data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]);
- cacheDataPC[tid] = fetch_PC;
+ cacheDataPC[tid] = block_PC;
cacheDataValid[tid] = false;
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
@@ -1052,12 +1061,16 @@ DefaultFetch<Impl>::fetch(bool &status_change)
} else {
if (fetchStatus[tid] == Idle) {
++fetchIdleCycles;
+ DPRINTF(Fetch, "[tid:%i]: Fetch is idle!\n", tid);
} else if (fetchStatus[tid] == Blocked) {
++fetchBlockedCycles;
+ DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid);
} else if (fetchStatus[tid] == Squashing) {
++fetchSquashCycles;
+ DPRINTF(Fetch, "[tid:%i]: Fetch is squashing!\n", tid);
} else if (fetchStatus[tid] == IcacheWaitResponse) {
++icacheStallCycles;
+ DPRINTF(Fetch, "[tid:%i]: Fetch is waiting cache response!\n", tid);
}
// Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so
diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh
index 86c973a0f..accc8d294 100644
--- a/src/cpu/ozone/cpu_impl.hh
+++ b/src/cpu/ozone/cpu_impl.hh
@@ -700,52 +700,12 @@ OzoneCPU<Impl>::processInterrupts()
// Check if there are any outstanding interrupts
//Handle the interrupts
- int ipl = 0;
- int summary = 0;
+ Fault interrupt = this->interrupts.getInterrupt(thread.getTC());
- checkInterrupts = false;
-
- if (thread.readMiscReg(IPR_ASTRR))
- panic("asynchronous traps not implemented\n");
-
- if (thread.readMiscReg(IPR_SIRR)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (thread.readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = intr_status();
-
- if (interrupts) {
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- if (ipl && ipl > thread.readMiscReg(IPR_IPLR)) {
- thread.setMiscReg(IPR_ISR, summary);
- thread.setMiscReg(IPR_INTID, ipl);
-#if USE_CHECKER
- // @todo: Make this more transparent
- if (checker) {
- checker->threadBase()->setMiscReg(IPR_ISR, summary);
- checker->threadBase()->setMiscReg(IPR_INTID, ipl);
- }
-#endif
- Fault fault = new InterruptFault;
- fault->invoke(thread.getTC());
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- thread.readMiscReg(IPR_IPLR), ipl, summary);
+ if (interrupt != NoFault) {
+ this->interrupts.updateIntrInfo(thread.getTC());
+ this->checkInterrupts = false;
+ interrupt->invoke(thread.getTC());
}
}
diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh
index 73ca6afbe..198ce0308 100644
--- a/src/cpu/ozone/front_end_impl.hh
+++ b/src/cpu/ozone/front_end_impl.hh
@@ -476,8 +476,8 @@ FrontEnd<Impl>::fetchCacheLine()
// Setup the memReq to do a read of the first isntruction's address.
// Set the appropriate read size and flags as well.
- memReq = new Request(0, fetch_PC, cacheBlkSize, flags,
- fetch_PC, cpu->readCpuId(), 0);
+ memReq = new Request(0, fetch_PC, cacheBlkSize, 0,
+ PC, cpu->readCpuId(), 0);
// Translate the instruction request.
fault = cpu->translateInstReq(memReq, thread);
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index e9679cc7c..58dc1fe5f 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -213,6 +213,9 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
break;
}
}
+ if (_status != Running) {
+ _status = Idle;
+ }
}
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index ab438aa77..4e5754bbb 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -315,6 +315,7 @@ BaseSimpleCPU::checkForInterrupts()
Fault interrupt = interrupts.getInterrupt(tc);
if (interrupt != NoFault) {
+ interrupts.updateIntrInfo(tc);
checkInterrupts = false;
interrupt->invoke(tc);
}