Updates to support new interrupt processing and removal of PcPAL.
src/arch/alpha/interrupts.hh: No need for this now that the ThreadContext is being used to set these IPRs in interrupts. Also split up the interrupt checking from the updating of the IPL and interrupt summary. src/arch/alpha/tlb.cc: Check the PC for whether or not it's in PAL mode, not the addr. src/cpu/o3/alpha/cpu.hh: Split up getting the interrupt from actually processing the interrupt. src/cpu/o3/alpha/cpu_impl.hh: Splut up the processing of interrupts. src/cpu/o3/commit_impl.hh: Update for ISA-oriented interrupt changes. src/cpu/o3/fetch_impl.hh: Fix broken if statement from PcPAL updates, and properly populate the request fields. Also more debugging output. src/cpu/ozone/cpu_impl.hh: Updates for ISA-oriented interrupt stuff. src/cpu/ozone/front_end_impl.hh: Populate request fields properly. src/cpu/simple/base.cc: Update for interrupt stuff. --HG-- extra : convert_revision : 9bac3f9ffed4948ee788699b2fa8419bc1ca647c
This commit is contained in:
parent
73581bf801
commit
12e26c68c3
9 changed files with 82 additions and 87 deletions
|
@ -49,6 +49,7 @@ namespace AlphaISA
|
||||||
{
|
{
|
||||||
memset(interrupts, 0, sizeof(interrupts));
|
memset(interrupts, 0, sizeof(interrupts));
|
||||||
intstatus = 0;
|
intstatus = 0;
|
||||||
|
newInfoSet = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void post(int int_num, int index)
|
void post(int int_num, int index)
|
||||||
|
@ -137,18 +138,10 @@ namespace AlphaISA
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ipl && ipl > tc->readMiscReg(IPR_IPLR)) {
|
if (ipl && ipl > tc->readMiscReg(IPR_IPLR)) {
|
||||||
tc->setMiscReg(IPR_ISR, summary);
|
// assert(!newInfoSet);
|
||||||
tc->setMiscReg(IPR_INTID, ipl);
|
newIpl = ipl;
|
||||||
|
newSummary = newSummary;
|
||||||
/* The following needs to be added back in somehow */
|
newInfoSet = true;
|
||||||
// Checker needs to know these two registers were updated.
|
|
||||||
/*#if USE_CHECKER
|
|
||||||
if (this->checker) {
|
|
||||||
this->checker->threadBase()->setMiscReg(IPR_ISR, summary);
|
|
||||||
this->checker->threadBase()->setMiscReg(IPR_INTID, ipl);
|
|
||||||
}
|
|
||||||
#endif*/
|
|
||||||
|
|
||||||
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
|
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
|
||||||
tc->readMiscReg(IPR_IPLR), ipl, summary);
|
tc->readMiscReg(IPR_IPLR), ipl, summary);
|
||||||
|
|
||||||
|
@ -158,7 +151,18 @@ namespace AlphaISA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateIntrInfo(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
assert(newInfoSet);
|
||||||
|
tc->setMiscReg(IPR_ISR, newSummary);
|
||||||
|
tc->setMiscReg(IPR_INTID, newIpl);
|
||||||
|
newInfoSet = false;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool newInfoSet;
|
||||||
|
int newIpl;
|
||||||
|
int newSummary;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -292,7 +292,7 @@ namespace AlphaISA
|
||||||
Fault
|
Fault
|
||||||
ITB::translate(RequestPtr &req, ThreadContext *tc) const
|
ITB::translate(RequestPtr &req, ThreadContext *tc) const
|
||||||
{
|
{
|
||||||
if (PcPAL(req->getVaddr())) {
|
if (PcPAL(req->getPC())) {
|
||||||
// strip off PAL PC marker (lsb is 1)
|
// strip off PAL PC marker (lsb is 1)
|
||||||
req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask);
|
req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask);
|
||||||
hits++;
|
hits++;
|
||||||
|
|
|
@ -156,8 +156,11 @@ class AlphaO3CPU : public FullO3CPU<Impl>
|
||||||
|
|
||||||
bool simPalCheck(int palFunc, unsigned tid);
|
bool simPalCheck(int palFunc, unsigned tid);
|
||||||
|
|
||||||
/** Processes any interrupts. */
|
/** Returns the Fault for any valid interrupt. */
|
||||||
void processInterrupts();
|
Fault getInterrupts();
|
||||||
|
|
||||||
|
/** Processes any an interrupt fault. */
|
||||||
|
void processInterrupts(Fault interrupt);
|
||||||
|
|
||||||
/** Halts the CPU. */
|
/** Halts the CPU. */
|
||||||
void halt() { panic("Halt not implemented!\n"); }
|
void halt() { panic("Halt not implemented!\n"); }
|
||||||
|
|
|
@ -266,9 +266,17 @@ AlphaO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
Fault
|
||||||
|
AlphaO3CPU<Impl>::getInterrupts()
|
||||||
|
{
|
||||||
|
// Check if there are any outstanding interrupts
|
||||||
|
return this->interrupts.getInterrupt(this->threadContexts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
AlphaO3CPU<Impl>::processInterrupts()
|
AlphaO3CPU<Impl>::processInterrupts(Fault interrupt)
|
||||||
{
|
{
|
||||||
// Check for interrupts here. For now can copy the code that
|
// Check for interrupts here. For now can copy the code that
|
||||||
// exists within isa_fullsys_traits.hh. Also assume that thread 0
|
// 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: Possibly consolidate the interrupt checking code.
|
||||||
// @todo: Allow other threads to handle interrupts.
|
// @todo: Allow other threads to handle interrupts.
|
||||||
|
|
||||||
// Check if there are any outstanding interrupts
|
assert(interrupt != NoFault);
|
||||||
//Handle the interrupts
|
this->interrupts.updateIntrInfo(this->threadContexts[0]);
|
||||||
Fault interrupt = this->interrupts.getInterrupt(this->tcBase(0));
|
|
||||||
|
|
||||||
if (interrupt != NoFault) {
|
DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
|
||||||
this->checkInterrupts = false;
|
this->checkInterrupts = false;
|
||||||
this->trap(interrupt, 0);
|
this->trap(interrupt, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FULL_SYSTEM
|
#endif // FULL_SYSTEM
|
||||||
|
|
|
@ -640,8 +640,18 @@ DefaultCommit<Impl>::commit()
|
||||||
// @todo: Allow other threads to handle interrupts.
|
// @todo: Allow other threads to handle interrupts.
|
||||||
if (cpu->checkInterrupts &&
|
if (cpu->checkInterrupts &&
|
||||||
cpu->check_interrupts(cpu->tcBase(0)) &&
|
cpu->check_interrupts(cpu->tcBase(0)) &&
|
||||||
|
commitStatus[0] != TrapPending &&
|
||||||
!trapSquash[0] &&
|
!trapSquash[0] &&
|
||||||
!tcSquash[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
|
// Tell fetch that there is an interrupt pending. This will
|
||||||
// make fetch wait until it sees a non PAL-mode PC, at which
|
// make fetch wait until it sees a non PAL-mode PC, at which
|
||||||
// point it stops fetching instructions.
|
// point it stops fetching instructions.
|
||||||
|
@ -650,26 +660,24 @@ DefaultCommit<Impl>::commit()
|
||||||
// Wait until the ROB is empty and all stores have drained in
|
// Wait until the ROB is empty and all stores have drained in
|
||||||
// order to enter the interrupt.
|
// order to enter the interrupt.
|
||||||
if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
|
if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
|
||||||
// Not sure which thread should be the one to interrupt. For now
|
// Squash or record that I need to squash this cycle if
|
||||||
// always do thread 0.
|
// an interrupt needed to be handled.
|
||||||
|
DPRINTF(Commit, "Interrupt detected.\n");
|
||||||
|
|
||||||
assert(!thread[0]->inSyscall);
|
assert(!thread[0]->inSyscall);
|
||||||
thread[0]->inSyscall = true;
|
thread[0]->inSyscall = true;
|
||||||
|
|
||||||
// CPU will handle implementation of the interrupt.
|
// CPU will handle interrupt.
|
||||||
cpu->processInterrupts();
|
cpu->processInterrupts(intr);
|
||||||
|
|
||||||
// Now squash or record that I need to squash this cycle.
|
|
||||||
commitStatus[0] = TrapPending;
|
|
||||||
|
|
||||||
// Exit state update mode to avoid accidental updating.
|
|
||||||
thread[0]->inSyscall = false;
|
thread[0]->inSyscall = false;
|
||||||
|
|
||||||
|
commitStatus[0] = TrapPending;
|
||||||
|
|
||||||
// Generate trap squash event.
|
// Generate trap squash event.
|
||||||
generateTrapEvent(0);
|
generateTrapEvent(0);
|
||||||
|
|
||||||
toIEW->commitInfo[0].clearInterrupt = true;
|
toIEW->commitInfo[0].clearInterrupt = true;
|
||||||
|
|
||||||
DPRINTF(Commit, "Interrupt detected.\n");
|
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
|
DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
|
||||||
}
|
}
|
||||||
|
@ -679,7 +687,7 @@ DefaultCommit<Impl>::commit()
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
// Check for any possible squashes, handle them first
|
// Check for any possible squashes, handle them first
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
commit_insts:
|
||||||
std::list<unsigned>::iterator threads = (*activeThreads).begin();
|
std::list<unsigned>::iterator threads = (*activeThreads).begin();
|
||||||
|
|
||||||
while (threads != (*activeThreads).end()) {
|
while (threads != (*activeThreads).end()) {
|
||||||
|
|
|
@ -559,27 +559,36 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
|
||||||
Fault fault = NoFault;
|
Fault fault = NoFault;
|
||||||
|
|
||||||
//AlphaDep
|
//AlphaDep
|
||||||
if (cacheBlocked || isSwitchedOut() ||
|
if (cacheBlocked) {
|
||||||
(interruptPending && (fetch_PC & 0x3))) {
|
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:
|
// Hold off fetch from getting new instructions when:
|
||||||
// Cache is blocked, or
|
// Cache is blocked, or
|
||||||
// while an interrupt is pending and we're not in PAL mode, or
|
// while an interrupt is pending and we're not in PAL mode, or
|
||||||
// fetch is switched out.
|
// fetch is switched out.
|
||||||
|
DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, interrupt pending\n",
|
||||||
|
tid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align the fetch PC so it's at the start of a cache block.
|
// 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 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the memReq to do a read of the first instruction's address.
|
// Setup the memReq to do a read of the first instruction's address.
|
||||||
// Set the appropriate read size and flags as well.
|
// Set the appropriate read size and flags as well.
|
||||||
// Build request here.
|
// 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);
|
fetch_PC, cpu->readCpuId(), tid);
|
||||||
|
|
||||||
memReq[tid] = mem_req;
|
memReq[tid] = mem_req;
|
||||||
|
@ -609,7 +618,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
|
||||||
Packet::ReadReq, Packet::Broadcast);
|
Packet::ReadReq, Packet::Broadcast);
|
||||||
data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]);
|
data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]);
|
||||||
|
|
||||||
cacheDataPC[tid] = fetch_PC;
|
cacheDataPC[tid] = block_PC;
|
||||||
cacheDataValid[tid] = false;
|
cacheDataValid[tid] = false;
|
||||||
|
|
||||||
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
|
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
|
||||||
|
@ -1050,12 +1059,16 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
} else {
|
} else {
|
||||||
if (fetchStatus[tid] == Idle) {
|
if (fetchStatus[tid] == Idle) {
|
||||||
++fetchIdleCycles;
|
++fetchIdleCycles;
|
||||||
|
DPRINTF(Fetch, "[tid:%i]: Fetch is idle!\n", tid);
|
||||||
} else if (fetchStatus[tid] == Blocked) {
|
} else if (fetchStatus[tid] == Blocked) {
|
||||||
++fetchBlockedCycles;
|
++fetchBlockedCycles;
|
||||||
|
DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid);
|
||||||
} else if (fetchStatus[tid] == Squashing) {
|
} else if (fetchStatus[tid] == Squashing) {
|
||||||
++fetchSquashCycles;
|
++fetchSquashCycles;
|
||||||
|
DPRINTF(Fetch, "[tid:%i]: Fetch is squashing!\n", tid);
|
||||||
} else if (fetchStatus[tid] == IcacheWaitResponse) {
|
} else if (fetchStatus[tid] == IcacheWaitResponse) {
|
||||||
++icacheStallCycles;
|
++icacheStallCycles;
|
||||||
|
DPRINTF(Fetch, "[tid:%i]: Fetch is waiting cache response!\n", tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so
|
// Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so
|
||||||
|
|
|
@ -700,52 +700,12 @@ OzoneCPU<Impl>::processInterrupts()
|
||||||
|
|
||||||
// Check if there are any outstanding interrupts
|
// Check if there are any outstanding interrupts
|
||||||
//Handle the interrupts
|
//Handle the interrupts
|
||||||
int ipl = 0;
|
Fault interrupt = this->interrupts.getInterrupt(thread.getTC());
|
||||||
int summary = 0;
|
|
||||||
|
|
||||||
checkInterrupts = false;
|
if (interrupt != NoFault) {
|
||||||
|
this->interrupts.updateIntrInfo(thread.getTC());
|
||||||
if (thread.readMiscReg(IPR_ASTRR))
|
this->checkInterrupts = false;
|
||||||
panic("asynchronous traps not implemented\n");
|
interrupt->invoke(thread.getTC());
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -476,8 +476,8 @@ FrontEnd<Impl>::fetchCacheLine()
|
||||||
|
|
||||||
// Setup the memReq to do a read of the first isntruction's address.
|
// Setup the memReq to do a read of the first isntruction's address.
|
||||||
// Set the appropriate read size and flags as well.
|
// Set the appropriate read size and flags as well.
|
||||||
memReq = new Request(0, fetch_PC, cacheBlkSize, flags,
|
memReq = new Request(0, fetch_PC, cacheBlkSize, 0,
|
||||||
fetch_PC, cpu->readCpuId(), 0);
|
PC, cpu->readCpuId(), 0);
|
||||||
|
|
||||||
// Translate the instruction request.
|
// Translate the instruction request.
|
||||||
fault = cpu->translateInstReq(memReq, thread);
|
fault = cpu->translateInstReq(memReq, thread);
|
||||||
|
|
|
@ -315,6 +315,7 @@ BaseSimpleCPU::checkForInterrupts()
|
||||||
Fault interrupt = interrupts.getInterrupt(tc);
|
Fault interrupt = interrupts.getInterrupt(tc);
|
||||||
|
|
||||||
if (interrupt != NoFault) {
|
if (interrupt != NoFault) {
|
||||||
|
interrupts.updateIntrInfo(tc);
|
||||||
checkInterrupts = false;
|
checkInterrupts = false;
|
||||||
interrupt->invoke(tc);
|
interrupt->invoke(tc);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue