1818from machine import MachineError , ExecutionTerminated , SetupError
1919import random
2020
21- # Helper functions
2221
2322def signed32 (val ):
2423 return val if val < 0x80000000 else val - 0x100000000
@@ -237,6 +236,7 @@ def exec_SYSTEM(cpu, ram, inst, rd, funct3, rs1, rs2, funct7):
237236 cpu .mtime = (cpu .csrs [0x7C1 ] << 32 ) | cpu .csrs [0x7C0 ]
238237 cpu .mtime_lo_updated = False
239238 cpu .mtime_hi_updated = False
239+ cpu .mtip = (cpu .mtime >= cpu .mtimecmp )
240240
241241 # Atomic update of mtimecmp
242242 if csr in (0x7C2 , 0x7C3 ):
@@ -246,7 +246,9 @@ def exec_SYSTEM(cpu, ram, inst, rd, funct3, rs1, rs2, funct7):
246246 cpu .mtimecmp = (cpu .csrs [0x7C3 ] << 32 ) | cpu .csrs [0x7C2 ]
247247 cpu .mtimecmp_lo_updated = False
248248 cpu .mtimecmp_hi_updated = False
249-
249+ cpu .mtime_countdown = cpu .mtimecmp - cpu .mtime
250+ cpu .mtip = (cpu .mtime >= cpu .mtimecmp )
251+
250252 elif funct3 in (0b010 , 0b110 ): # CSRRS / CSRRSI
251253 if rs1_val != 0 :
252254 cpu .csrs [csr ] = old | rs1_val
@@ -335,6 +337,7 @@ def __init__(self, ram, init_regs=None, logger=None, args=None):
335337 self .mtime_hi_updated = False
336338 self .mtimecmp_lo_updated = False
337339 self .mtimecmp_hi_updated = False
340+ self .mtip = False
338341
339342 # name - ID register maps
340343 self .REG_NUM_NAME = {}
@@ -418,20 +421,30 @@ def bypassed_trap_return(self, cause, mtval=0):
418421 self .csrs [0x300 ] |= (1 << 7 ) # MPIE = 1
419422 # (MIE, bit 3, stays unchanged)
420423
424+ # Machine timer interrupt logic
421425 def timer_update (self ):
422426 csrs = self .csrs
423- self . mtime = ( self .mtime + 1 ) & 0xFFFFFFFF_FFFFFFFF
427+ mtime = self .mtime
424428
425- # trigger Machine Timer Interrupt
426- if self .mtime >= self .mtimecmp :
427- csrs [0x344 ] |= (1 << 7 ) # set MTIP (timer interrupt)
428- else :
429- csrs [0x344 ] &= ~ (1 << 7 ) # clear MTIP
429+ self .mtime = (mtime + 1 ) # & 0xFFFFFFFF_FFFFFFFF # the counter should wrap, but it's unlikely to ever happen ;)
430+ mtip_asserted = (mtime >= self .mtimecmp )
430431
431- if (csrs [0x300 ] & (1 << 3 )) and (csrs [0x304 ] & (1 << 7 )) and (csrs [0x344 ] & (1 << 7 )):
432- self .trap (cause = 0x80000007 , sync = False ) # fire interrupt as an asynchronous trap
432+ # Set interrupt pending flag
433+ if mtip_asserted != self .mtip :
434+ if mtip_asserted :
435+ csrs [0x344 ] |= (1 << 7 ) # set MTIP
436+ else :
437+ csrs [0x344 ] &= ~ (1 << 7 ) # clear MTIP
438+ self .mtip = mtip_asserted
439+
440+ if not mtip_asserted :
441+ return
442+
443+ # Trigger Machine Timer Interrupt
444+ if (csrs [0x300 ] & (1 << 3 )) and (csrs [0x304 ] & (1 << 7 )):
445+ self .trap (cause = 0x80000007 , sync = False ) # fire timer interrupt as an asynchronous trap
433446
434- # CPU register initialization
447+ # CPU registers initialization
435448 def init_registers (self , mode = '0x00000000' ):
436449 self .registers [0 ] = 0
437450 if mode == 'random' :
0 commit comments