#ifndef __ARCH_POWER_FAULTS_HH__
 #define __ARCH_POWER_FAULTS_HH__
 
+#include "cpu/thread_context.hh"
 #include "sim/faults.hh"
 
 namespace PowerISA
 {
 
-class PowerFault : public FaultBase
+class PowerFaultBase : public FaultBase
 {
   protected:
     FaultName _name;
 
-    PowerFault(FaultName name)
+    PowerFaultBase(FaultName name)
         : _name(name)
     {
     }
 };
 
 
-class UnimplementedOpcodeFault : public PowerFault
+class UnimplementedOpcodeFault : public PowerFaultBase
 {
   public:
     UnimplementedOpcodeFault()
-        : PowerFault("Unimplemented Opcode")
+        : PowerFaultBase("Unimplemented Opcode")
     {
     }
 };
 
 
-class MachineCheckFault : public PowerFault
+class MachineCheckFault : public PowerFaultBase
 {
   public:
     MachineCheckFault()
-        : PowerFault("Machine Check")
+        : PowerFaultBase("Machine Check")
     {
     }
 };
 
 
-class AlignmentFault : public PowerFault
+class AlignmentFault : public PowerFaultBase
 {
   public:
     AlignmentFault()
-        : PowerFault("Alignment")
+        : PowerFaultBase("Alignment")
     {
     }
 };
 
+
+class PowerInterrupt : public PowerFaultBase
+{
+  public:
+    PowerInterrupt()
+        : PowerFaultBase("Interrupt")
+    {
+    }
+};
+
+
+class DecrementerInterrupt : public PowerInterrupt
+{
+  public:
+    DecrementerInterrupt()
+    {
+    }
+    virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
+                        StaticInst::nullStaticInstPtr)
+    {
+      Msr msr = tc->readIntReg(MISCREG_MSR);
+      // Refer Power ISA Manual v3.0B Book-III, section 6.5.11
+      tc->setIntReg(INTREG_SRR0 , tc->instAddr());
+      uint64_t srr1 = msr & 0xffffffff78fc0fff;
+      tc->setIntReg(INTREG_SRR1 , srr1);
+      msr = msr & 0xffffffffffff76cd;
+      tc->setIntReg(INTREG_MSR , msr);
+      tc->pcState(0x900);
+    }
+};
+
 } // namespace PowerISA
 
 #endif // __ARCH_POWER_FAULTS_HH__
 
 #define __ARCH_POWER_INTERRUPT_HH__
 
 #include "arch/generic/interrupts.hh"
+#include "arch/power/faults.hh"
+#include "arch/power/registers.hh"
 #include "base/logging.hh"
 #include "params/PowerInterrupts.hh"
 
 
 class Interrupts : public BaseInterrupts
 {
+  private:
+    BaseCPU * cpu;
+    bool si = false;
+
   public:
     typedef PowerInterruptsParams Params;
 
     }
 
     bool
-    checkInterrupts() const
+    checkInterrupts(ThreadContext *tc)
     {
-        panic("Interrupts::checkInterrupts not implemented.\n");
+        //panic("Interrupts::checkInterrupts not implemented.\n");
+        if ( tc->readIntReg(INTREG_DEC) == 0) {
+           si = true;
+           return true;
+        }
+        else {
+           tc->setIntReg(INTREG_DEC , tc->readIntReg(INTREG_DEC)-1);
+           return false;
+        }
     }
 
     Fault
     getInterrupt()
     {
-        assert(checkInterrupts());
-        panic("Interrupts::getInterrupt not implemented.\n");
+        assert(checkInterrupts(tc));
+        if (si)
+        return std::make_shared<DecrementerInterrupt>();
+        else return NoFault;
     }
 
     void
     updateIntrInfo()
     {
-        panic("Interrupts::updateIntrInfo not implemented.\n");
+        tc->setIntReg(INTREG_DEC , 0xffffffffffffffff);
+        si = false;
     }
 };
 
 
     //Sixty Four, little endian,Hypervisor bits are enabled.
     // IR and DR bits are disabled.
     Msr msr = 0x9000000000000001;
+    tc->setIntReg(INTREG_DEC , 0xffffffffffffffff);
+    // This PVR is specific to power9
+    tc->setIntReg(INTREG_PVR , 0x004e1100);
     tc->setIntReg(INTREG_MSR , msr);
+    //ArgumentReg0 is initialized with 0xc00000 because in linux/system.cc
+    //dtb is loaded at 0xc00000
+    tc->setIntReg(ArgumentReg0, 0x1800000);
 }