[CSR] added read/write checks and unified name to addr resuloution

kernel-mode
Anton Lydike 4 years ago
parent 291f44a192
commit 49b59cd46a

@ -1,6 +1,7 @@
from typing import Dict, Union, Callable
from typing import Dict, Union, Callable, Optional
from collections import defaultdict
from functools import wraps
from .privmodes import PrivModes
from .Exceptions import IllegalInstructionTrap
MSTATUS_OFFSETS = {
'uie': 0,
@ -68,27 +69,22 @@ class CSR:
self.listeners = defaultdict(lambda: (lambda x, y: None))
def set(self, addr: Union[str, int], val: int):
if isinstance(addr, str):
if addr not in self.name_to_addr:
print("Unknown CSR register {}".format(addr))
return
addr = self.name_to_addr[addr]
addr = self._addr_to_name(addr)
if addr is None:
return
self.listeners[addr](self.regs[addr], val)
self.regs[addr] = val
def get(self, addr: Union[str, int]):
if isinstance(addr, str):
if addr not in self.name_to_addr:
print("Unknown CSR register {}".format(addr))
return
addr = self.name_to_addr[addr]
addr = self._addr_to_name(addr)
if addr is None:
return
return self.regs[addr]
def set_listener(self, addr: Union[str, int], listener: Callable[[int, int], None]):
if isinstance(addr, str):
if not addr in self.name_to_addr:
print("Unknown CSR register {}".format(addr))
addr = self.name_to_addr[addr]
addr = self._addr_to_name(addr)
if addr is None:
return
self.listeners[addr] = listener
# mstatus properties
@ -121,4 +117,20 @@ class CSR:
def inner(func: Callable[[int, int], None]):
self.set_listener(addr, func)
return func
return inner
return inner
def assert_can_read(self, mode: PrivModes, addr: int):
if (addr >> 8) & 3 > mode.value():
raise IllegalInstructionTrap()
def assert_can_write(self, mode: PrivModes, addr: int):
if (addr >> 8) & 3 > mode.value() or addr >> 10 == 11:
raise IllegalInstructionTrap()
def _addr_to_name(self, addr: Union[str, int]) -> Optional[int]:
if isinstance(addr, str):
if addr not in self.name_to_addr:
print("Unknown CSR register {}".format(addr))
return None
return self.name_to_addr[addr]
return addr

@ -21,11 +21,15 @@ class PrivRV32I(RV32I):
"""
def instruction_csrrw(self, ins: 'LoadedInstruction'):
rd, rs, ind = self.parse_crs_ins(ins)
rd, rs, csr_addr = self.parse_crs_ins(ins)
if rd != 'zero':
old_val = int_from_bytes(self.cpu.csr[ind])
self.cpu.csr.assert_can_read(self.cpu.mode, csr_addr)
old_val = self.cpu.csr.get(csr_addr)
self.regs.set(rd, old_val)
self.cpu.csr.set(ind, rs)
if rs != 'zero':
new_val = self.regs.get(rs)
self.cpu.csr.assert_can_write(self.cpu.mode, csr_addr)
self.cpu.csr.set(csr_addr, new_val)
def instruction_csrrs(self, ins: 'LoadedInstruction'):
INS_NOT_IMPLEMENTED(ins)
@ -122,7 +126,7 @@ class PrivRV32I(RV32I):
def parse_crs_ins(self, ins: 'LoadedInstruction'):
ASSERT_LEN(ins.args, 3)
return ins.get_reg(0), self.get_reg_content(ins, 1), ins.get_imm(2)
return ins.get_reg(0), ins.get_reg(1), ins.get_imm(2)
def parse_mem_ins(self, ins: 'LoadedInstruction') -> Tuple[str, int]:
ASSERT_LEN(ins.args, 3)

Loading…
Cancel
Save