This commit is contained in:
Nathan Binkert 2008-09-27 07:25:04 -07:00
parent 83f3bff643
commit 819023b8e2

View file

@ -37,140 +37,150 @@
#include "base/compiler.hh" #include "base/compiler.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
namespace AlphaISA namespace AlphaISA {
class Interrupts
{ {
class Interrupts private:
bool newInfoSet;
int newIpl;
int newSummary;
protected:
uint64_t interrupts[NumInterruptLevels];
uint64_t intstatus;
public:
Interrupts()
{ {
protected: memset(interrupts, 0, sizeof(interrupts));
uint64_t interrupts[NumInterruptLevels]; intstatus = 0;
uint64_t intstatus; newInfoSet = false;
}
public: void
Interrupts() post(int int_num, int index)
{ {
memset(interrupts, 0, sizeof(interrupts)); DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
intstatus = 0;
newInfoSet = false;
}
void post(int int_num, int index) if (int_num < 0 || int_num >= NumInterruptLevels)
{ panic("int_num out of bounds\n");
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
if (int_num < 0 || int_num >= NumInterruptLevels) if (index < 0 || index >= (int)sizeof(uint64_t) * 8)
panic("int_num out of bounds\n"); panic("int_num out of bounds\n");
if (index < 0 || index >= sizeof(uint64_t) * 8) interrupts[int_num] |= 1 << index;
panic("int_num out of bounds\n"); intstatus |= (ULL(1) << int_num);
}
interrupts[int_num] |= 1 << index; void
intstatus |= (ULL(1) << int_num); clear(int int_num, int index)
} {
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
void clear(int int_num, int index) if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
{ panic("int_num out of bounds\n");
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) if (index < 0 || index >= (int)sizeof(uint64_t) * 8)
panic("int_num out of bounds\n"); panic("int_num out of bounds\n");
if (index < 0 || index >= sizeof(uint64_t) * 8) interrupts[int_num] &= ~(1 << index);
panic("int_num out of bounds\n"); if (interrupts[int_num] == 0)
intstatus &= ~(ULL(1) << int_num);
}
interrupts[int_num] &= ~(1 << index); void
if (interrupts[int_num] == 0) clear_all()
intstatus &= ~(ULL(1) << int_num); {
} DPRINTF(Interrupt, "Interrupts all cleared\n");
void clear_all() memset(interrupts, 0, sizeof(interrupts));
{ intstatus = 0;
DPRINTF(Interrupt, "Interrupts all cleared\n"); }
memset(interrupts, 0, sizeof(interrupts)); void
intstatus = 0; serialize(std::ostream &os)
} {
SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
SERIALIZE_SCALAR(intstatus);
}
void serialize(std::ostream &os) void
{ unserialize(Checkpoint *cp, const std::string &section)
SERIALIZE_ARRAY(interrupts, NumInterruptLevels); {
SERIALIZE_SCALAR(intstatus); UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
} UNSERIALIZE_SCALAR(intstatus);
}
void unserialize(Checkpoint *cp, const std::string &section) bool
{ check_interrupts(ThreadContext *tc) const
UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); {
UNSERIALIZE_SCALAR(intstatus); return (intstatus != 0) && !(tc->readPC() & 0x3);
} }
bool check_interrupts(ThreadContext * tc) const Fault
{ getInterrupt(ThreadContext *tc)
return (intstatus != 0) && !(tc->readPC() & 0x3); {
} int ipl = 0;
int summary = 0;
Fault getInterrupt(ThreadContext * tc) if (tc->readMiscRegNoEffect(IPR_ASTRR))
{ panic("asynchronous traps not implemented\n");
int ipl = 0;
int summary = 0;
if (tc->readMiscRegNoEffect(IPR_ASTRR)) if (tc->readMiscRegNoEffect(IPR_SIRR)) {
panic("asynchronous traps not implemented\n"); for (int i = INTLEVEL_SOFTWARE_MIN;
i < INTLEVEL_SOFTWARE_MAX; i++) {
if (tc->readMiscRegNoEffect(IPR_SIRR)) { if (tc->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) {
for (int i = INTLEVEL_SOFTWARE_MIN; // See table 4-19 of 21164 hardware reference
i < INTLEVEL_SOFTWARE_MAX; i++) { ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
if (tc->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { summary |= (ULL(1) << i);
// See table 4-19 of 21164 hardware reference
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
}
} }
} }
}
uint64_t interrupts = intstatus; uint64_t interrupts = intstatus;
if (interrupts) { if (interrupts) {
for (int i = INTLEVEL_EXTERNAL_MIN; for (int i = INTLEVEL_EXTERNAL_MIN;
i < INTLEVEL_EXTERNAL_MAX; i++) { i < INTLEVEL_EXTERNAL_MAX; i++) {
if (interrupts & (ULL(1) << i)) { if (interrupts & (ULL(1) << i)) {
// See table 4-19 of 21164 hardware reference // See table 4-19 of 21164 hardware reference
ipl = i; ipl = i;
summary |= (ULL(1) << i); summary |= (ULL(1) << i);
}
} }
} }
if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) {
newIpl = ipl;
newSummary = summary;
newInfoSet = true;
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary);
return new InterruptFault;
} else {
return NoFault;
}
} }
void updateIntrInfo(ThreadContext *tc) if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) {
{ newIpl = ipl;
assert(newInfoSet); newSummary = summary;
tc->setMiscRegNoEffect(IPR_ISR, newSummary); newInfoSet = true;
tc->setMiscRegNoEffect(IPR_INTID, newIpl); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
newInfoSet = false; tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary);
return new InterruptFault;
} else {
return NoFault;
} }
}
uint64_t get_vec(int int_num) void
{ updateIntrInfo(ThreadContext *tc)
panic("Shouldn't be called for Alpha\n"); {
M5_DUMMY_RETURN assert(newInfoSet);
} tc->setMiscRegNoEffect(IPR_ISR, newSummary);
tc->setMiscRegNoEffect(IPR_INTID, newIpl);
newInfoSet = false;
}
private: uint64_t
bool newInfoSet; get_vec(int int_num)
int newIpl; {
int newSummary; panic("Shouldn't be called for Alpha\n");
}; M5_DUMMY_RETURN;
} }
};
#endif } // namespace AlphaISA
#endif // __ARCH_ALPHA_INTERRUPT_HH__