summaryrefslogtreecommitdiff
path: root/src/arch/riscv/interrupts.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/riscv/interrupts.hh')
-rw-r--r--src/arch/riscv/interrupts.hh97
1 files changed, 66 insertions, 31 deletions
diff --git a/src/arch/riscv/interrupts.hh b/src/arch/riscv/interrupts.hh
index 60a5b5bc5..729af6fb9 100644
--- a/src/arch/riscv/interrupts.hh
+++ b/src/arch/riscv/interrupts.hh
@@ -31,8 +31,14 @@
#ifndef __ARCH_RISCV_INTERRUPT_HH__
#define __ARCH_RISCV_INTERRUPT_HH__
+#include <bitset>
+#include <memory>
+
+#include "arch/riscv/faults.hh"
+#include "arch/riscv/registers.hh"
#include "base/logging.hh"
#include "cpu/thread_context.hh"
+#include "debug/Interrupt.hh"
#include "params/RiscvInterrupts.hh"
#include "sim/sim_object.hh"
@@ -41,10 +47,16 @@ class ThreadContext;
namespace RiscvISA {
+/*
+ * This is based on version 1.10 of the RISC-V privileged ISA reference,
+ * chapter 3.1.14.
+ */
class Interrupts : public SimObject
{
private:
BaseCPU * cpu;
+ std::bitset<NumInterruptTypes> ip;
+ std::bitset<NumInterruptTypes> ie;
public:
typedef RiscvInterruptsParams Params;
@@ -55,64 +67,87 @@ class Interrupts : public SimObject
return dynamic_cast<const Params *>(_params);
}
- Interrupts(Params * p) : SimObject(p), cpu(nullptr)
- {}
+ Interrupts(Params * p) : SimObject(p), cpu(nullptr), ip(0), ie(0) {}
- void
- setCPU(BaseCPU * _cpu)
+ void setCPU(BaseCPU * _cpu) { cpu = _cpu; }
+
+ std::bitset<NumInterruptTypes>
+ globalMask(ThreadContext *tc) const
+ {
+ INTERRUPT mask;
+ STATUS status = tc->readMiscReg(MISCREG_STATUS);
+ if (status.mie)
+ mask.mei = mask.mti = mask.msi = 1;
+ if (status.sie)
+ mask.sei = mask.sti = mask.ssi = 1;
+ if (status.uie)
+ mask.uei = mask.uti = mask.usi = 1;
+ return std::bitset<NumInterruptTypes>(mask);
+ }
+
+ bool checkInterrupt(int num) const { return ip[num] && ie[num]; }
+ bool checkInterrupts(ThreadContext *tc) const
+ {
+ return (ip & ie & globalMask(tc)).any();
+ }
+
+ Fault
+ getInterrupt(ThreadContext *tc) const
{
- cpu = _cpu;
+ assert(checkInterrupts(tc));
+ std::bitset<NumInterruptTypes> mask = globalMask(tc);
+ for (int c = 0; c < NumInterruptTypes; c++)
+ if (checkInterrupt(c) && mask[c])
+ return std::make_shared<InterruptFault>(c);
+ return NoFault;
}
+ void updateIntrInfo(ThreadContext *tc) {}
+
void
post(int int_num, int index)
{
- panic("Interrupts::post not implemented.\n");
+ DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
+ ip[int_num] = true;
}
void
clear(int int_num, int index)
{
- panic("Interrupts::clear not implemented.\n");
+ DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
+ ip[int_num] = false;
}
void
clearAll()
{
- warn_once("Interrupts::clearAll not implemented.\n");
+ DPRINTF(Interrupt, "All interrupts cleared\n");
+ ip = 0;
}
- bool
- checkInterrupts(ThreadContext *tc) const
- {
- warn_once("Interrupts::checkInterrupts just rudimentary implemented");
- /**
- * read the machine interrupt register in order to check if interrupts
- * are pending
- * should be sufficient for now, as interrupts
- * are not implemented at all
- */
- if (tc->readMiscReg(MISCREG_IP))
- return true;
-
- return false;
- }
+ MiscReg readIP() const { return (MiscReg)ip.to_ulong(); }
+ MiscReg readIE() const { return (MiscReg)ie.to_ulong(); }
+ void setIP(const MiscReg& val) { ip = val; }
+ void setIE(const MiscReg& val) { ie = val; }
- Fault
- getInterrupt(ThreadContext *tc)
+ void
+ serialize(CheckpointOut &cp)
{
- assert(checkInterrupts(tc));
- panic("Interrupts::getInterrupt not implemented.\n");
+ SERIALIZE_SCALAR(ip.to_ulong());
+ SERIALIZE_SCALAR(ie.to_ulong());
}
void
- updateIntrInfo(ThreadContext *tc)
+ unserialize(CheckpointIn &cp)
{
- panic("Interrupts::updateIntrInfo not implemented.\n");
+ long reg;
+ UNSERIALIZE_SCALAR(reg);
+ ip = reg;
+ UNSERIALIZE_SCALAR(reg);
+ ie = reg;
}
};
} // namespace RiscvISA
-#endif // __ARCH_RISCV_INTERRUPT_HH__
-
+#endif // __ARCH_RISCV_INTERRUPT_HH__ \ No newline at end of file