* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Gabe Black
+ * Authors: Ali Saidi
+ * Lisa Hsu
*/
#ifndef __ARCH_SPARC_INTERRUPT_HH__
#define __ARCH_SPARC_INTERRUPT_HH__
#include "arch/sparc/faults.hh"
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/registers.hh"
#include "cpu/thread_context.hh"
-
+#include "params/SparcInterrupts.hh"
+#include "sim/sim_object.hh"
namespace SparcISA
{
- class Interrupts
+
+class Interrupts : public SimObject
+{
+ private:
+ BaseCPU * cpu;
+
+ uint64_t interrupts[NumInterruptTypes];
+ uint64_t intStatus;
+
+ public:
+
+ void
+ setCPU(BaseCPU * _cpu)
{
- protected:
+ cpu = _cpu;
+ }
+ typedef SparcInterruptsParams Params;
- public:
- Interrupts()
- {
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(_params);
+ }
- }
- void post(int int_num, int index)
- {
+ Interrupts(Params * p) : SimObject(p), cpu(NULL)
+ {
+ clearAll();
+ }
- }
+ int
+ InterruptLevel(uint64_t softint)
+ {
+ if (softint & 0x10000 || softint & 0x1)
+ return 14;
+
+ int level = 15;
+ while (level > 0 && !(1 << level & softint))
+ level--;
+ if (1 << level & softint)
+ return level;
+ return 0;
+ }
+
+ void
+ post(int int_num, int index)
+ {
+ DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
+ assert(int_num >= 0 && int_num < NumInterruptTypes);
+ assert(index >= 0 && index < 64);
- void clear(int int_num, int index)
- {
+ interrupts[int_num] |= ULL(1) << index;
+ intStatus |= ULL(1) << int_num;
+ }
- }
+ void
+ clear(int int_num, int index)
+ {
+ DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
+ assert(int_num >= 0 && int_num < NumInterruptTypes);
+ assert(index >= 0 && index < 64);
- void clear_all()
- {
+ interrupts[int_num] &= ~(ULL(1) << index);
+ if (!interrupts[int_num])
+ intStatus &= ~(ULL(1) << int_num);
+ }
+ void
+ clearAll()
+ {
+ for (int i = 0; i < NumInterruptTypes; ++i) {
+ interrupts[i] = 0;
}
+ intStatus = 0;
+ }
- bool check_interrupts(ThreadContext * tc) const
- {
- // so far only handle softint interrupts
- int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
- if (int_level)
- return true;
- else
- return false;
- }
+ bool
+ checkInterrupts(ThreadContext *tc) const
+ {
+ return intStatus;
+ }
- Fault getInterrupt(ThreadContext * tc)
- {
- // conditioning the softint interrups
- if (tc->readMiscReg(MISCREG_HPSTATE) & hpriv) {
- // if running in privileged mode, then pend the interrupt
- return NoFault;
- } else {
- int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
- if ((int_level <= tc->readMiscReg(MISCREG_PIL)) ||
- !(tc->readMiscReg(MISCREG_PSTATE) & ie)) {
- // if PIL or no interrupt enabled, then pend the interrupt
- return NoFault;
- } else {
- return new InterruptLevelN(int_level);
+ Fault
+ getInterrupt(ThreadContext *tc)
+ {
+ int hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
+ int pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
+ bool ie = pstate & PSTATE::ie;
+
+ // 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 (interrupts[IT_HINTP]) {
+ // This will be cleaned by a HINTP write
+ return new HstickMatch;
+ }
+ if (interrupts[IT_INT_VEC]) {
+ // this will be cleared by an ASI read (or write)
+ return new InterruptVector;
}
}
- }
+ } else {
+ if (interrupts[IT_TRAP_LEVEL_ZERO]) {
+ // this is cleared by deasserting HPSTATE::tlz
+ return new TrapLevelZero;
+ }
+ // HStick matches always happen in priv mode (ie doesn't matter)
+ if (interrupts[IT_HINTP]) {
+ return new HstickMatch;
+ }
+ if (interrupts[IT_INT_VEC]) {
+ // this will be cleared by an ASI read (or write)
+ return new InterruptVector;
+ }
+ if (ie) {
+ if (interrupts[IT_CPU_MONDO]) {
+ return new CpuMondo;
+ }
+ if (interrupts[IT_DEV_MONDO]) {
+ return new DevMondo;
+ }
+ if (interrupts[IT_SOFT_INT]) {
+ int level = InterruptLevel(interrupts[IT_SOFT_INT]);
+ return new InterruptLevelN(level);
+ }
+
+ if (interrupts[IT_RES_ERROR]) {
+ return new ResumableError;
+ }
+ } // !hpriv && ie
+ } // !hpriv
+ return NoFault;
+ }
- void updateIntrInfo(ThreadContext * tc)
- {
+ void
+ updateIntrInfo(ThreadContext *tc)
+ {
- }
+ }
- void serialize(std::ostream &os)
- {
- }
+ uint64_t
+ get_vec(int int_num)
+ {
+ assert(int_num >= 0 && int_num < NumInterruptTypes);
+ return interrupts[int_num];
+ }
- void unserialize(Checkpoint *cp, const std::string §ion)
- {
- }
- };
-}
+ void
+ serialize(std::ostream &os)
+ {
+ SERIALIZE_ARRAY(interrupts,NumInterruptTypes);
+ SERIALIZE_SCALAR(intStatus);
+ }
+
+ void
+ unserialize(Checkpoint *cp, const std::string §ion)
+ {
+ UNSERIALIZE_ARRAY(interrupts,NumInterruptTypes);
+ UNSERIALIZE_SCALAR(intStatus);
+ }
+};
+} // namespace SPARC_ISA
#endif // __ARCH_SPARC_INTERRUPT_HH__