diff --git a/riscemu/CPU.py b/riscemu/CPU.py index efb1892..469092f 100644 --- a/riscemu/CPU.py +++ b/riscemu/CPU.py @@ -47,8 +47,8 @@ class CPU: # setup CPU states self.pc = 0 self.cycle = 0 - self.exit = False - self.exit_code = 0 + self.exit: bool = False + self.exit_code: int = 0 self.conf = conf self.active_debug = False # if a debugging session is currently runnign diff --git a/riscemu/priv/CSR.py b/riscemu/priv/CSR.py index e39e06c..50ec515 100644 --- a/riscemu/priv/CSR.py +++ b/riscemu/priv/CSR.py @@ -1,5 +1,6 @@ from typing import Dict, Union, Callable from collections import defaultdict +from functools import wraps MSTATUS_OFFSETS = { 'uie': 0, @@ -54,6 +55,7 @@ class CSR: 'mhartid': 0xF14, 'time': 0xc01, 'timeh': 0xc81, + 'halt': 0x789 } """ Translation for named registers @@ -112,3 +114,9 @@ class CSR: off = MSTATUS_OFFSETS[name] mask = (2**size - 1) << off return (self.get('mstatus') & mask) >> off + + def callback(self, addr: Union[str, int]): + def inner(func: Callable[[int, int], None]): + self.set_listener(addr, func) + return func + return inner \ No newline at end of file diff --git a/riscemu/priv/PrivCPU.py b/riscemu/priv/PrivCPU.py index f4463c0..d46e7cc 100644 --- a/riscemu/priv/PrivCPU.py +++ b/riscemu/priv/PrivCPU.py @@ -49,13 +49,8 @@ class PrivCPU(CPU): self.pc = exec.run_ptr self.syscall_int = None - # set up CSR - self.csr = CSR() - # TODO: Actually populate the CSR with real data (vendorID, heartID, machine implementation etc) - self.csr.set('mhartid', 0) # core id - self.csr.set('mimpid', 1) # implementation id - # TODO: set correct misa - self.csr.set('misa', 1) # available ISA + # init csr + self._init_csr() def _run(self, verbose=False): if self.pc <= 0: @@ -133,3 +128,21 @@ class PrivCPU(CPU): print(FMT_CPU + '[CPU] Started running from 0x{:08X} ({})'.format(self.pc, "kernel") + FMT_NONE) self._run(True) + def _init_csr(self): + # set up CSR + self.csr = CSR() + # TODO: Actually populate the CSR with real data (vendorID, heartID, machine implementation etc) + self.csr.set('mhartid', 0) # core id + self.csr.set('mimpid', 1) # implementation id + # TODO: set correct misa + self.csr.set('misa', 1) # available ISA + + @self.csr.callback('halt') + def halt(old: int, new: int): + if new != 0: + self.exit = True + self.exit_code = new + + @self.csr.callback('mstatus') + def mstatus(old: int, new: int): + pass