diff --git a/riscemu/priv/PrivCPU.py b/riscemu/priv/PrivCPU.py index 8368e0f..8ca785b 100644 --- a/riscemu/priv/PrivCPU.py +++ b/riscemu/priv/PrivCPU.py @@ -173,6 +173,36 @@ class PrivCPU(CPU): if self._time_timecmp < (time.perf_counter_ns() // self.TIME_RESOLUTION_NS) - self._time_start: self.pending_traps.append(TimerInterrupt()) self._time_interrupt_enabled = False + print(FMT_CPU + "[CPU] raising timer interrupt: tartegt: {}, current: {}".format(self._time_timecmp, (time.perf_counter_ns() // self.TIME_RESOLUTION_NS) - self._time_start) + FMT_NONE) def _check_interrupt(self): - pass + if not (len(self.pending_traps) > 0 and self.csr.get_mstatus('mie')): + return + # select best interrupt + # TODO: actually select based on the official ranking + trap = self.pending_traps.pop() # use the most recent trap + print(FMT_CPU + "[CPU] taking trap {}!".format(trap) + FMT_NONE) + + if trap.priv != PrivModes.MACHINE: + print(FMT_CPU + "[CPU] Trap not targeting machine mode encountered! - undefined behaviour!" + FMT_NONE) + + if self.mode != PrivModes.USER: + print(FMT_CPU + "[CPU] Trap triggered outside of user mode?!" + FMT_NONE) + + self.csr.set_mstatus('mpie', self.csr.get_mstatus('mie')) + self.csr.set_mstatus('mpp', self.mode.value) + self.csr.set_mstatus('mie', 0) + self.csr.set('mcause', trap.mcause) + self.csr.set('mepc', self.pc) + self.csr.set('mtval', trap.mtval) + self.mode = trap.priv + mtvec = self.csr.get('mtvec') + if mtvec & 0b11 == 0: + self.pc = mtvec + if mtvec & 0b11 == 1: + self.pc = (mtvec & 0b11111111111111111111111111111100) + (trap.code * 4) + + + + +