diff options
Diffstat (limited to 'src/arch/riscv/interrupts.hh')
-rw-r--r-- | src/arch/riscv/interrupts.hh | 97 |
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 |