#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/registers.hh"
#include "cpu/thread_context.hh"
+#include "debug/Interrupt.hh"
+#include "params/SparcInterrupts.hh"
+#include "sim/sim_object.hh"
namespace SparcISA
{
-class Interrupts
+enum InterruptTypes
{
+ IT_TRAP_LEVEL_ZERO,
+ IT_HINTP,
+ IT_INT_VEC,
+ IT_CPU_MONDO,
+ IT_DEV_MONDO,
+ IT_RES_ERROR,
+ IT_SOFT_INT,
+ NumInterruptTypes
+};
+class Interrupts : public SimObject
+{
private:
+ BaseCPU * cpu;
uint64_t interrupts[NumInterruptTypes];
uint64_t intStatus;
public:
- Interrupts()
+
+ void
+ setCPU(BaseCPU * _cpu)
+ {
+ cpu = _cpu;
+ }
+
+ typedef SparcInterruptsParams Params;
+
+ const Params *
+ params() const
{
- clear_all();
+ return dynamic_cast<const Params *>(_params);
}
- int InterruptLevel(uint64_t softint)
+ Interrupts(Params * p) : SimObject(p), cpu(NULL)
+ {
+ clearAll();
+ }
+
+ int
+ InterruptLevel(uint64_t softint)
{
if (softint & 0x10000 || softint & 0x1)
return 14;
return 0;
}
- void post(int int_num, int index)
+ void
+ post(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
assert(int_num >= 0 && int_num < NumInterruptTypes);
intStatus |= ULL(1) << int_num;
}
- void clear(int int_num, int index)
+ void
+ clear(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
assert(int_num >= 0 && int_num < NumInterruptTypes);
intStatus &= ~(ULL(1) << int_num);
}
- void clear_all()
+ void
+ clearAll()
{
for (int i = 0; i < NumInterruptTypes; ++i) {
interrupts[i] = 0;
intStatus = 0;
}
- bool check_interrupts(ThreadContext * tc) const
+ bool
+ checkInterrupts(ThreadContext *tc) const
{
- return intStatus;
- }
+ if (!intStatus)
+ return false;
- Fault getInterrupt(ThreadContext * tc)
- {
- int hpstate = tc->readMiscReg(MISCREG_HPSTATE);
- int pstate = tc->readMiscReg(MISCREG_PSTATE);
- bool ie = pstate & PSTATE::ie;
+ HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
+ PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
// THESE ARE IN ORDER OF PRIORITY
// since there are early returns, and the highest
// priority interrupts should get serviced,
// it is v. important that new interrupts are inserted
// in the right order of processing
- if (hpstate & HPSTATE::hpriv) {
- if (ie) {
+ if (hpstate.hpriv) {
+ if (pstate.ie) {
if (interrupts[IT_HINTP]) {
// This will be cleaned by a HINTP write
- return new HstickMatch;
+ return true;
}
if (interrupts[IT_INT_VEC]) {
// this will be cleared by an ASI read (or write)
- return new InterruptVector;
+ return true;
}
}
} else {
if (interrupts[IT_TRAP_LEVEL_ZERO]) {
// this is cleared by deasserting HPSTATE::tlz
- return new TrapLevelZero;
+ return true;
}
// HStick matches always happen in priv mode (ie doesn't matter)
if (interrupts[IT_HINTP]) {
- return new HstickMatch;
+ return true;
}
if (interrupts[IT_INT_VEC]) {
// this will be cleared by an ASI read (or write)
- return new InterruptVector;
+ return true;
}
- if (ie) {
+ if (pstate.ie) {
if (interrupts[IT_CPU_MONDO]) {
- return new CpuMondo;
+ return true;
}
if (interrupts[IT_DEV_MONDO]) {
- return new DevMondo;
+ return true;
}
if (interrupts[IT_SOFT_INT]) {
- return new
- InterruptLevelN(InterruptLevel(interrupts[IT_SOFT_INT]));
+ return true;
}
if (interrupts[IT_RES_ERROR]) {
- return new ResumableError;
+ return true;
}
- } // !hpriv && ie
+ } // !hpriv && pstate.ie
} // !hpriv
- return NoFault;
+
+ return false;
}
- void updateIntrInfo(ThreadContext * tc)
+ Fault
+ getInterrupt(ThreadContext *tc)
{
+ assert(checkInterrupts(tc));
+
+ HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
+ PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
+ // THESE ARE IN ORDER OF PRIORITY
+ // since there are early returns, and the highest
+ // priority interrupts should get serviced,
+ // it is v. important that new interrupts are inserted
+ // in the right order of processing
+ if (hpstate.hpriv) {
+ if (pstate.ie) {
+ if (interrupts[IT_HINTP]) {
+ // This will be cleaned by a HINTP write
+ return std::make_shared<HstickMatch>();
+ }
+ if (interrupts[IT_INT_VEC]) {
+ // this will be cleared by an ASI read (or write)
+ return std::make_shared<InterruptVector>();
+ }
+ }
+ } else {
+ if (interrupts[IT_TRAP_LEVEL_ZERO]) {
+ // this is cleared by deasserting HPSTATE::tlz
+ return std::make_shared<TrapLevelZero>();
+ }
+ // HStick matches always happen in priv mode (ie doesn't matter)
+ if (interrupts[IT_HINTP]) {
+ return std::make_shared<HstickMatch>();
+ }
+ if (interrupts[IT_INT_VEC]) {
+ // this will be cleared by an ASI read (or write)
+ return std::make_shared<InterruptVector>();
+ }
+ if (pstate.ie) {
+ if (interrupts[IT_CPU_MONDO]) {
+ return std::make_shared<CpuMondo>();
+ }
+ if (interrupts[IT_DEV_MONDO]) {
+ return std::make_shared<DevMondo>();
+ }
+ if (interrupts[IT_SOFT_INT]) {
+ int level = InterruptLevel(interrupts[IT_SOFT_INT]);
+ return std::make_shared<InterruptLevelN>(level);
+ }
+
+ if (interrupts[IT_RES_ERROR]) {
+ return std::make_shared<ResumableError>();
+ }
+ } // !hpriv && pstate.ie
+ } // !hpriv
+ return NoFault;
}
- uint64_t get_vec(int int_num)
+ void
+ updateIntrInfo(ThreadContext *tc)
+ {}
+
+ uint64_t
+ get_vec(int int_num)
{
assert(int_num >= 0 && int_num < NumInterruptTypes);
return interrupts[int_num];
}
- void serialize(std::ostream &os)
+ void
+ serialize(CheckpointOut &cp) const override
{
SERIALIZE_ARRAY(interrupts,NumInterruptTypes);
SERIALIZE_SCALAR(intStatus);
}
- void unserialize(Checkpoint *cp, const std::string §ion)
+ void
+ unserialize(CheckpointIn &cp) override
{
UNSERIALIZE_ARRAY(interrupts,NumInterruptTypes);
UNSERIALIZE_SCALAR(intStatus);